UNPKG

2.36 kBPlain TextView Raw
1import { responsePathAsArray, GraphQLResolveInfo } from "graphql";
2
3type HighResolutionTime = [number, number];
4
5const traceHRStartTime = Symbol("HR Start Time");
6const traceWallStartTime = Symbol("Wall Start Time");
7export const apolloTracingContext = Symbol("Apollo Tracing Context");
8
9export interface ApolloTracingContext {
10 [traceHRStartTime]: HighResolutionTime;
11 [traceWallStartTime]: Date;
12 version: 1;
13 startTime: string;
14 endTime: string;
15 duration: number;
16 execution: {
17 parsing?: {
18 startOffset: number;
19 duration: number;
20 };
21 validation?: {
22 startOffset: number;
23 duration: number;
24 };
25 resolvers: ApolloTracingResolverStats[];
26 };
27}
28
29export interface ApolloTracingResolverStats {
30 path: (string | number)[];
31 parentType: string;
32 fieldName: string;
33 returnType: string;
34 startOffset: number;
35 duration: number;
36}
37
38function durationHrTimeToNanos(hrtime: HighResolutionTime): number {
39 return hrtime[0] * 1e9 + hrtime[1];
40}
41
42export async function apolloTracingGraphQLMiddleware(
43 resolve: Function,
44 parent: any,
45 args: any,
46 context: { [apolloTracingContext]: ApolloTracingContext },
47 info: GraphQLResolveInfo
48): Promise<any> {
49 const startOffset = durationHrTimeToNanos(
50 process.hrtime(context[apolloTracingContext][traceHRStartTime])
51 );
52 try {
53 return await resolve(parent, args, context, info);
54 } finally {
55 context[apolloTracingContext].execution.resolvers.push({
56 path: [...responsePathAsArray(info.path)],
57 parentType: info.parentType.toString(),
58 fieldName: info.fieldName,
59 returnType: info.returnType.toString(),
60 startOffset,
61 duration:
62 durationHrTimeToNanos(
63 process.hrtime(context[apolloTracingContext][traceHRStartTime])
64 ) - startOffset
65 });
66 }
67}
68
69export function startTracingContext(): ApolloTracingContext {
70 const wallStartTime = new Date();
71 return {
72 [traceHRStartTime]: process.hrtime(),
73 [traceWallStartTime]: wallStartTime,
74 version: 1,
75 startTime: wallStartTime.toISOString(),
76 endTime: "",
77 duration: 0,
78 execution: {
79 resolvers: []
80 }
81 };
82}
83
84export function endTracingContext(context: ApolloTracingContext): void {
85 context.endTime = new Date().toISOString();
86 context.duration = durationHrTimeToNanos(
87 process.hrtime(context[traceHRStartTime])
88 );
89}