dd-trace 2.9.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/packages/datadog-instrumentations/index.js +5 -0
- package/packages/datadog-instrumentations/src/connect.js +3 -0
- package/packages/datadog-instrumentations/src/fastify.js +21 -15
- package/packages/datadog-instrumentations/src/graphql.js +354 -0
- package/packages/datadog-instrumentations/src/grpc/client.js +250 -0
- package/packages/datadog-instrumentations/src/grpc/server.js +144 -0
- package/packages/{datadog-plugin-grpc/src/kinds.js → datadog-instrumentations/src/grpc/types.js} +0 -0
- package/packages/datadog-instrumentations/src/grpc.js +4 -0
- package/packages/datadog-instrumentations/src/http/client.js +1 -1
- package/packages/datadog-instrumentations/src/http2/client.js +67 -0
- package/packages/datadog-instrumentations/src/http2/server.js +3 -0
- package/packages/datadog-instrumentations/src/http2.js +4 -0
- package/packages/datadog-instrumentations/src/jest.js +14 -14
- package/packages/datadog-instrumentations/src/koa.js +12 -3
- package/packages/datadog-instrumentations/src/microgateway-core.js +66 -0
- package/packages/datadog-instrumentations/src/mocha.js +129 -63
- package/packages/datadog-instrumentations/src/next.js +140 -0
- package/packages/datadog-instrumentations/src/router.js +3 -0
- package/packages/datadog-instrumentations/src/tedious.js +1 -1
- package/packages/datadog-plugin-graphql/src/index.js +123 -412
- package/packages/datadog-plugin-graphql/src/resolve.js +120 -0
- package/packages/datadog-plugin-grpc/src/client.js +54 -283
- package/packages/datadog-plugin-grpc/src/index.js +31 -3
- package/packages/datadog-plugin-grpc/src/server.js +50 -145
- package/packages/datadog-plugin-http/src/client.js +10 -7
- package/packages/datadog-plugin-http2/src/client.js +72 -120
- package/packages/datadog-plugin-http2/src/index.js +32 -3
- package/packages/datadog-plugin-http2/src/server.js +6 -214
- package/packages/datadog-plugin-jest/src/util.js +13 -1
- package/packages/datadog-plugin-microgateway-core/src/index.js +14 -145
- package/packages/datadog-plugin-mocha/src/index.js +8 -36
- package/packages/datadog-plugin-next/src/index.js +56 -168
- package/packages/datadog-plugin-router/src/index.js +7 -3
- package/packages/dd-trace/src/config.js +3 -2
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/opentracing/span.js +6 -3
- package/packages/dd-trace/src/plugin_manager.js +21 -0
- package/packages/dd-trace/src/plugins/plugin.js +3 -1
- package/packages/dd-trace/src/plugins/util/test.js +3 -0
- package/packages/dd-trace/src/plugins/util/web.js +0 -7
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/startup-log.js +1 -1
- package/packages/dd-trace/src/telemetry.js +1 -1
- package/packages/dd-trace/lib/version.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
"node": ">=12"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@datadog/native-appsec": "^1.2.
|
|
62
|
-
"@datadog/native-metrics": "^1.
|
|
63
|
-
"@datadog/pprof": "^0.
|
|
64
|
-
"@datadog/sketches-js": "^1.0.
|
|
61
|
+
"@datadog/native-appsec": "^1.2.1",
|
|
62
|
+
"@datadog/native-metrics": "^1.4.0",
|
|
63
|
+
"@datadog/pprof": "^0.5.1",
|
|
64
|
+
"@datadog/sketches-js": "^1.0.5",
|
|
65
65
|
"@types/node": ">=12",
|
|
66
66
|
"crypto-randomuuid": "^1.0.0",
|
|
67
67
|
"diagnostics_channel": "^1.1.0",
|
|
@@ -106,8 +106,8 @@
|
|
|
106
106
|
"jszip": "^3.5.0",
|
|
107
107
|
"mkdirp": "^0.5.1",
|
|
108
108
|
"mocha": "8",
|
|
109
|
-
"multer": "^1.4.2",
|
|
110
109
|
"msgpack-lite": "^0.1.26",
|
|
110
|
+
"multer": "^1.4.5-lts.1",
|
|
111
111
|
"nock": "^11.3.3",
|
|
112
112
|
"nyc": "^15.1.0",
|
|
113
113
|
"proxyquire": "^1.8.0",
|
|
@@ -16,14 +16,18 @@ require('./src/fastify')
|
|
|
16
16
|
require('./src/find-my-way')
|
|
17
17
|
require('./src/generic-pool')
|
|
18
18
|
require('./src/google-cloud-pubsub')
|
|
19
|
+
require('./src/graphql')
|
|
20
|
+
require('./src/grpc')
|
|
19
21
|
require('./src/hapi')
|
|
20
22
|
require('./src/http')
|
|
23
|
+
require('./src/http2')
|
|
21
24
|
require('./src/ioredis')
|
|
22
25
|
require('./src/jest')
|
|
23
26
|
require('./src/kafkajs')
|
|
24
27
|
require('./src/knex')
|
|
25
28
|
require('./src/koa')
|
|
26
29
|
require('./src/memcached')
|
|
30
|
+
require('./src/microgateway-core')
|
|
27
31
|
require('./src/moleculer')
|
|
28
32
|
require('./src/mongodb-core')
|
|
29
33
|
require('./src/mongoose')
|
|
@@ -31,6 +35,7 @@ require('./src/mysql')
|
|
|
31
35
|
require('./src/mysql2')
|
|
32
36
|
require('./src/mocha')
|
|
33
37
|
require('./src/net')
|
|
38
|
+
require('./src/next')
|
|
34
39
|
require('./src/oracledb')
|
|
35
40
|
require('./src/paperplane')
|
|
36
41
|
require('./src/pino')
|
|
@@ -4,6 +4,7 @@ const shimmer = require('../../datadog-shimmer')
|
|
|
4
4
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
5
5
|
|
|
6
6
|
const enterChannel = channel('apm:connect:middleware:enter')
|
|
7
|
+
const exitChannel = channel('apm:connect:middleware:exit')
|
|
7
8
|
const errorChannel = channel('apm:connect:middleware:error')
|
|
8
9
|
const nextChannel = channel('apm:connect:middleware:next')
|
|
9
10
|
const handleChannel = channel('apm:connect:request:handle')
|
|
@@ -80,6 +81,7 @@ function wrapLayerHandle (layer) {
|
|
|
80
81
|
} catch (e) {
|
|
81
82
|
errorChannel.publish(e)
|
|
82
83
|
nextChannel.publish({ req })
|
|
84
|
+
exitChannel.publish({ req })
|
|
83
85
|
|
|
84
86
|
throw e
|
|
85
87
|
}
|
|
@@ -94,6 +96,7 @@ function wrapNext (req, next) {
|
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
nextChannel.publish({ req })
|
|
99
|
+
exitChannel.publish({ req })
|
|
97
100
|
|
|
98
101
|
next.apply(null, arguments)
|
|
99
102
|
}
|
|
@@ -85,8 +85,8 @@ function wrapAddHook (addHook) {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
function onRequest (request, reply,
|
|
89
|
-
if (typeof
|
|
88
|
+
function onRequest (request, reply, done) {
|
|
89
|
+
if (typeof done !== 'function') return
|
|
90
90
|
|
|
91
91
|
const req = getReq(request)
|
|
92
92
|
const res = getRes(reply)
|
|
@@ -96,37 +96,41 @@ function onRequest (request, reply, next) {
|
|
|
96
96
|
|
|
97
97
|
return requestResource.runInAsyncScope(() => {
|
|
98
98
|
handleChannel.publish({ req, res })
|
|
99
|
-
return
|
|
99
|
+
return done()
|
|
100
100
|
})
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
function preHandler (request, reply,
|
|
104
|
-
if (typeof
|
|
105
|
-
if (!reply || typeof reply.send !== 'function') return
|
|
103
|
+
function preHandler (request, reply, done) {
|
|
104
|
+
if (typeof done !== 'function') return
|
|
105
|
+
if (!reply || typeof reply.send !== 'function') return done()
|
|
106
106
|
|
|
107
107
|
const req = getReq(request)
|
|
108
108
|
const requestResource = requestResources.get(req)
|
|
109
109
|
|
|
110
110
|
reply.send = wrapSend(reply.send, requestResource)
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
done()
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
function preValidation (request, reply,
|
|
115
|
+
function preValidation (request, reply, done) {
|
|
116
116
|
const req = getReq(request)
|
|
117
117
|
const parsingResource = parsingResources.get(req)
|
|
118
118
|
|
|
119
|
-
if (!parsingResource) return
|
|
119
|
+
if (!parsingResource) return done()
|
|
120
120
|
|
|
121
|
-
parsingResource.runInAsyncScope(() =>
|
|
121
|
+
parsingResource.runInAsyncScope(() => done())
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
function preParsing (request, reply,
|
|
124
|
+
function preParsing (request, reply, payload, done) {
|
|
125
|
+
if (typeof done !== 'function') {
|
|
126
|
+
done = payload
|
|
127
|
+
}
|
|
128
|
+
|
|
125
129
|
const req = getReq(request)
|
|
126
130
|
const parsingResource = new AsyncResource('bound-anonymous-fn')
|
|
127
131
|
|
|
128
132
|
parsingResources.set(req, parsingResource)
|
|
129
|
-
parsingResource.runInAsyncScope(() =>
|
|
133
|
+
parsingResource.runInAsyncScope(() => done())
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
function wrapSend (send, resource) {
|
|
@@ -150,9 +154,11 @@ function getRes (reply) {
|
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
function publishError (error, resource) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
157
|
+
if (error) {
|
|
158
|
+
resource.runInAsyncScope(() => {
|
|
159
|
+
errorChannel.publish(error)
|
|
160
|
+
})
|
|
161
|
+
}
|
|
156
162
|
|
|
157
163
|
return error
|
|
158
164
|
}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
addHook,
|
|
5
|
+
channel,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
/** cached objects */
|
|
11
|
+
|
|
12
|
+
const contexts = new WeakMap()
|
|
13
|
+
const documentSources = new WeakMap()
|
|
14
|
+
const patchedResolvers = new WeakSet()
|
|
15
|
+
const patchedTypes = new WeakSet()
|
|
16
|
+
|
|
17
|
+
/** CHANNELS */
|
|
18
|
+
|
|
19
|
+
// execute channels
|
|
20
|
+
const startResolveCh = channel('apm:graphql:resolve:start')
|
|
21
|
+
const startExecuteCh = channel('apm:graphql:execute:start')
|
|
22
|
+
const finishExecuteCh = channel('apm:graphql:execute:finish')
|
|
23
|
+
const finishResolveCh = channel('apm:graphql:resolve:finish')
|
|
24
|
+
const updateFieldCh = channel('apm:graphql:resolve:updateField')
|
|
25
|
+
const executeErrorCh = channel('apm:graphql:execute:error')
|
|
26
|
+
|
|
27
|
+
// parse channels
|
|
28
|
+
const parseStartCh = channel('apm:graphql:parser:start')
|
|
29
|
+
const parseFinishCh = channel('apm:graphql:parser:finish')
|
|
30
|
+
const parseErrorCh = channel('apm:graphql:parser:error')
|
|
31
|
+
|
|
32
|
+
// validate channels
|
|
33
|
+
const validateStartCh = channel('apm:graphql:validate:start')
|
|
34
|
+
const validateFinishCh = channel('apm:graphql:validate:finish')
|
|
35
|
+
const validateErrorCh = channel('apm:graphql:validate:error')
|
|
36
|
+
|
|
37
|
+
function getOperation (document, operationName) {
|
|
38
|
+
if (!document || !Array.isArray(document.definitions)) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const definitions = document.definitions.filter(def => def)
|
|
43
|
+
const types = ['query', 'mutation', 'subscription']
|
|
44
|
+
|
|
45
|
+
if (operationName) {
|
|
46
|
+
return definitions
|
|
47
|
+
.filter(def => types.indexOf(def.operation) !== -1)
|
|
48
|
+
.find(def => operationName === (def.name && def.name.value))
|
|
49
|
+
} else {
|
|
50
|
+
return definitions.find(def => types.indexOf(def.operation) !== -1)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function normalizeArgs (args, defaultFieldResolver) {
|
|
55
|
+
if (args.length !== 1) return normalizePositional(args, defaultFieldResolver)
|
|
56
|
+
|
|
57
|
+
args[0].contextValue = args[0].contextValue || {}
|
|
58
|
+
args[0].fieldResolver = wrapResolve(args[0].fieldResolver || defaultFieldResolver)
|
|
59
|
+
|
|
60
|
+
return args[0]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function normalizePositional (args, defaultFieldResolver) {
|
|
64
|
+
args[3] = args[3] || {} // contextValue
|
|
65
|
+
args[6] = wrapResolve(args[6] || defaultFieldResolver) // fieldResolver
|
|
66
|
+
args.length = Math.max(args.length, 7)
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
schema: args[0],
|
|
70
|
+
document: args[1],
|
|
71
|
+
rootValue: args[2],
|
|
72
|
+
contextValue: args[3],
|
|
73
|
+
variableValues: args[4],
|
|
74
|
+
operationName: args[5],
|
|
75
|
+
fieldResolver: args[6]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function wrapParse (parse) {
|
|
80
|
+
return function (source) {
|
|
81
|
+
if (!parseStartCh.hasSubscribers) {
|
|
82
|
+
return parse.apply(this, arguments)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
86
|
+
|
|
87
|
+
return asyncResource.runInAsyncScope(() => {
|
|
88
|
+
parseStartCh.publish()
|
|
89
|
+
let document
|
|
90
|
+
try {
|
|
91
|
+
document = parse.apply(this, arguments)
|
|
92
|
+
const operation = getOperation(document)
|
|
93
|
+
|
|
94
|
+
if (!operation) return document
|
|
95
|
+
|
|
96
|
+
if (source) {
|
|
97
|
+
documentSources.set(document, source.body || source)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return document
|
|
101
|
+
} catch (err) {
|
|
102
|
+
err.stack
|
|
103
|
+
parseErrorCh.publish(err)
|
|
104
|
+
|
|
105
|
+
throw err
|
|
106
|
+
} finally {
|
|
107
|
+
parseFinishCh.publish({ source, document, docSource: documentSources.get(document) })
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function wrapValidate (validate) {
|
|
114
|
+
return function (_schema, document, _rules, _typeInfo) {
|
|
115
|
+
if (!validateStartCh.hasSubscribers) {
|
|
116
|
+
return validate.apply(this, arguments)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
120
|
+
|
|
121
|
+
return asyncResource.runInAsyncScope(() => {
|
|
122
|
+
validateStartCh.publish({ docSource: documentSources.get(document), document })
|
|
123
|
+
|
|
124
|
+
let errors
|
|
125
|
+
try {
|
|
126
|
+
errors = validate.apply(this, arguments)
|
|
127
|
+
validateErrorCh.publish(errors && errors[0])
|
|
128
|
+
return errors
|
|
129
|
+
} catch (err) {
|
|
130
|
+
err.stack
|
|
131
|
+
validateErrorCh.publish(err)
|
|
132
|
+
|
|
133
|
+
throw err
|
|
134
|
+
} finally {
|
|
135
|
+
validateFinishCh.publish({ document, errors })
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function wrapExecute (execute) {
|
|
142
|
+
return function (exe) {
|
|
143
|
+
const defaultFieldResolver = execute.defaultFieldResolver
|
|
144
|
+
return function () {
|
|
145
|
+
if (!startExecuteCh.hasSubscribers) {
|
|
146
|
+
return exe.apply(this, arguments)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
150
|
+
return asyncResource.runInAsyncScope(() => {
|
|
151
|
+
const args = normalizeArgs(arguments, defaultFieldResolver)
|
|
152
|
+
const schema = args.schema
|
|
153
|
+
const document = args.document
|
|
154
|
+
const source = documentSources.get(document)
|
|
155
|
+
const contextValue = args.contextValue
|
|
156
|
+
const operation = getOperation(document, args.operationName)
|
|
157
|
+
|
|
158
|
+
if (contexts.has(contextValue)) {
|
|
159
|
+
return exe.apply(this, arguments)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (schema) {
|
|
163
|
+
wrapFields(schema._queryType)
|
|
164
|
+
wrapFields(schema._mutationType)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
startExecuteCh.publish({
|
|
168
|
+
operation,
|
|
169
|
+
args,
|
|
170
|
+
docSource: documentSources.get(document)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const context = { source, asyncResource, fields: {} }
|
|
174
|
+
|
|
175
|
+
contexts.set(contextValue, context)
|
|
176
|
+
|
|
177
|
+
return callInAsyncScope(exe, asyncResource, this, arguments, (err, res) => {
|
|
178
|
+
if (finishResolveCh.hasSubscribers) finishResolvers(context)
|
|
179
|
+
|
|
180
|
+
executeErrorCh.publish(err || (res && res.errors && res.errors[0]))
|
|
181
|
+
finishExecuteCh.publish({ res, args })
|
|
182
|
+
})
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function wrapResolve (resolve) {
|
|
189
|
+
if (typeof resolve !== 'function' || patchedResolvers.has(resolve)) return resolve
|
|
190
|
+
|
|
191
|
+
function resolveAsync (source, args, contextValue, info) {
|
|
192
|
+
if (!startResolveCh.hasSubscribers) return resolve.apply(this, arguments)
|
|
193
|
+
|
|
194
|
+
const context = contexts.get(contextValue)
|
|
195
|
+
|
|
196
|
+
if (!context) return resolve.apply(this, arguments)
|
|
197
|
+
|
|
198
|
+
const field = assertField(context, info)
|
|
199
|
+
|
|
200
|
+
return callInAsyncScope(resolve, field.asyncResource, this, arguments, (err) => {
|
|
201
|
+
updateFieldCh.publish({ field, info, err })
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
patchedResolvers.add(resolveAsync)
|
|
206
|
+
|
|
207
|
+
return resolveAsync
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function callInAsyncScope (fn, aR, thisArg, args, cb) {
|
|
211
|
+
cb = cb || (() => {})
|
|
212
|
+
|
|
213
|
+
return aR.runInAsyncScope(() => {
|
|
214
|
+
try {
|
|
215
|
+
const result = fn.apply(thisArg, args)
|
|
216
|
+
if (result && typeof result.then === 'function') {
|
|
217
|
+
// bind callback to this scope
|
|
218
|
+
result.then(
|
|
219
|
+
aR.bind(res => cb(null, res)),
|
|
220
|
+
aR.bind(err => cb(err))
|
|
221
|
+
)
|
|
222
|
+
} else {
|
|
223
|
+
cb(null, result)
|
|
224
|
+
}
|
|
225
|
+
return result
|
|
226
|
+
} catch (err) {
|
|
227
|
+
cb(err)
|
|
228
|
+
throw err
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function pathToArray (path) {
|
|
234
|
+
const flattened = []
|
|
235
|
+
let curr = path
|
|
236
|
+
while (curr) {
|
|
237
|
+
flattened.push(curr.key)
|
|
238
|
+
curr = curr.prev
|
|
239
|
+
}
|
|
240
|
+
return flattened.reverse()
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function assertField (context, info) {
|
|
244
|
+
const pathInfo = info && info.path
|
|
245
|
+
|
|
246
|
+
const path = pathToArray(pathInfo)
|
|
247
|
+
|
|
248
|
+
const pathString = path.join('.')
|
|
249
|
+
const fields = context.fields
|
|
250
|
+
|
|
251
|
+
let field = fields[pathString]
|
|
252
|
+
|
|
253
|
+
if (!field) {
|
|
254
|
+
const parent = getParentField(context, path)
|
|
255
|
+
|
|
256
|
+
// we want to spawn the new span off of the parent, not a new async resource
|
|
257
|
+
parent.asyncResource.runInAsyncScope(() => {
|
|
258
|
+
/* this child resource will run a branched scope off of the parent resource, which
|
|
259
|
+
accesses the parent span from the storage unit in its own scope */
|
|
260
|
+
const childResource = new AsyncResource('bound-anonymous-fn')
|
|
261
|
+
|
|
262
|
+
childResource.runInAsyncScope(() => {
|
|
263
|
+
startResolveCh.publish({
|
|
264
|
+
info,
|
|
265
|
+
context
|
|
266
|
+
})
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
field = fields[pathString] = {
|
|
270
|
+
parent,
|
|
271
|
+
asyncResource: childResource,
|
|
272
|
+
error: null
|
|
273
|
+
}
|
|
274
|
+
})
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return field
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function getParentField (context, path) {
|
|
281
|
+
for (let i = path.length - 1; i > 0; i--) {
|
|
282
|
+
const field = getField(context, path.slice(0, i))
|
|
283
|
+
if (field) {
|
|
284
|
+
return field
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
asyncResource: context.asyncResource
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function getField (context, path) {
|
|
294
|
+
return context.fields[path.join('.')]
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function wrapFields (type) {
|
|
298
|
+
if (!type || !type._fields || patchedTypes.has(type)) {
|
|
299
|
+
return
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
patchedTypes.add(type)
|
|
303
|
+
|
|
304
|
+
Object.keys(type._fields).forEach(key => {
|
|
305
|
+
const field = type._fields[key]
|
|
306
|
+
|
|
307
|
+
wrapFieldResolve(field)
|
|
308
|
+
wrapFieldType(field)
|
|
309
|
+
})
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function wrapFieldResolve (field) {
|
|
313
|
+
if (!field || !field.resolve) return
|
|
314
|
+
field.resolve = wrapResolve(field.resolve)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function wrapFieldType (field) {
|
|
318
|
+
if (!field || !field.type) return
|
|
319
|
+
|
|
320
|
+
let unwrappedType = field.type
|
|
321
|
+
|
|
322
|
+
while (unwrappedType.ofType) {
|
|
323
|
+
unwrappedType = unwrappedType.ofType
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
wrapFields(unwrappedType)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function finishResolvers ({ fields }) {
|
|
330
|
+
Object.keys(fields).reverse().forEach(key => {
|
|
331
|
+
const field = fields[key]
|
|
332
|
+
const asyncResource = field.asyncResource
|
|
333
|
+
asyncResource.runInAsyncScope(() => {
|
|
334
|
+
executeErrorCh.publish(field.error)
|
|
335
|
+
finishResolveCh.publish(field.finishTime)
|
|
336
|
+
})
|
|
337
|
+
})
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
addHook({ name: 'graphql', file: 'execution/execute.js', versions: ['>=0.10'] }, execute => {
|
|
341
|
+
shimmer.wrap(execute, 'execute', wrapExecute(execute))
|
|
342
|
+
return execute
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
addHook({ name: 'graphql', file: 'language/parser.js', versions: ['>=0.10'] }, parser => {
|
|
346
|
+
shimmer.wrap(parser, 'parse', wrapParse)
|
|
347
|
+
return parser
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
addHook({ name: 'graphql', file: 'validation/validate.js', versions: ['>=0.10'] }, validate => {
|
|
351
|
+
shimmer.wrap(validate, 'validate', wrapValidate)
|
|
352
|
+
|
|
353
|
+
return validate
|
|
354
|
+
})
|