dd-trace 2.10.0 → 2.12.1
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/LICENSE-3rdparty.csv +0 -1
- package/index.d.ts +3 -3
- package/package.json +5 -6
- package/packages/datadog-core/src/storage/async_hooks.js +4 -4
- package/packages/datadog-core/src/storage/async_resource.js +14 -4
- package/packages/datadog-instrumentations/index.js +4 -0
- package/packages/datadog-instrumentations/src/connect.js +7 -4
- package/packages/datadog-instrumentations/src/couchbase.js +166 -61
- package/packages/datadog-instrumentations/src/fastify.js +14 -25
- package/packages/datadog-instrumentations/src/graphql.js +23 -9
- 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/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/koa.js +15 -6
- package/packages/datadog-instrumentations/src/microgateway-core.js +66 -0
- package/packages/datadog-instrumentations/src/mocha.js +198 -62
- package/packages/datadog-instrumentations/src/next.js +140 -0
- package/packages/datadog-instrumentations/src/restify.js +4 -8
- package/packages/datadog-instrumentations/src/router.js +7 -4
- package/packages/datadog-plugin-couchbase/src/index.js +8 -10
- package/packages/datadog-plugin-graphql/src/resolve.js +14 -17
- 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/server.js +3 -8
- 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-microgateway-core/src/index.js +14 -145
- package/packages/datadog-plugin-mocha/src/index.js +88 -39
- package/packages/datadog-plugin-next/src/index.js +56 -168
- package/packages/datadog-plugin-router/src/index.js +46 -13
- package/packages/dd-trace/src/config.js +2 -1
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +111 -15
- package/packages/dd-trace/src/opentracing/span.js +6 -3
- package/packages/dd-trace/src/plugin_manager.js +49 -33
- package/packages/dd-trace/src/plugins/plugin.js +3 -1
- package/packages/dd-trace/src/plugins/util/test.js +32 -1
- package/packages/dd-trace/src/plugins/util/web.js +25 -24
- package/packages/dd-trace/src/profiling/config.js +10 -2
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -2
- package/packages/dd-trace/src/profiling/exporters/form-data.js +53 -0
- package/packages/dd-trace/src/profiling/index.js +2 -0
- package/packages/dd-trace/src/profiling/profiler.js +6 -1
- package/packages/dd-trace/src/profiling/profilers/cpu.js +126 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const types = require('./types')
|
|
4
|
+
const { addHook, channel, AsyncResource } = require('../helpers/instrument')
|
|
5
|
+
const shimmer = require('../../../datadog-shimmer')
|
|
6
|
+
|
|
7
|
+
const patched = new WeakSet()
|
|
8
|
+
const instances = new WeakMap()
|
|
9
|
+
|
|
10
|
+
const startChannel = channel('apm:grpc:client:request:start')
|
|
11
|
+
const errorChannel = channel('apm:grpc:client:request:error')
|
|
12
|
+
const finishChannel = channel('apm:grpc:client:request:finish')
|
|
13
|
+
|
|
14
|
+
function createWrapMakeRequest (type) {
|
|
15
|
+
return function wrapMakeRequest (makeRequest) {
|
|
16
|
+
return function (path) {
|
|
17
|
+
const args = ensureMetadata(this, arguments, 4)
|
|
18
|
+
|
|
19
|
+
return callMethod(this, makeRequest, args, path, args[4], type)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function createWrapLoadPackageDefinition () {
|
|
25
|
+
return function wrapLoadPackageDefinition (loadPackageDefinition) {
|
|
26
|
+
return function (packageDef) {
|
|
27
|
+
const result = loadPackageDefinition.apply(this, arguments)
|
|
28
|
+
|
|
29
|
+
if (!result) return result
|
|
30
|
+
|
|
31
|
+
wrapPackageDefinition(result)
|
|
32
|
+
|
|
33
|
+
return result
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function createWrapMakeClientConstructor () {
|
|
39
|
+
return function wrapMakeClientConstructor (makeClientConstructor) {
|
|
40
|
+
return function (methods) {
|
|
41
|
+
const ServiceClient = makeClientConstructor.apply(this, arguments)
|
|
42
|
+
|
|
43
|
+
wrapClientConstructor(ServiceClient, methods)
|
|
44
|
+
|
|
45
|
+
return ServiceClient
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function wrapPackageDefinition (def) {
|
|
51
|
+
for (const name in def) {
|
|
52
|
+
if (def[name].format) continue
|
|
53
|
+
if (def[name].service && def[name].prototype) {
|
|
54
|
+
wrapClientConstructor(def[name], def[name].service)
|
|
55
|
+
} else {
|
|
56
|
+
wrapPackageDefinition(def[name])
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function wrapClientConstructor (ServiceClient, methods) {
|
|
62
|
+
const proto = ServiceClient.prototype
|
|
63
|
+
|
|
64
|
+
if (typeof methods !== 'object' || 'format' in methods) return
|
|
65
|
+
|
|
66
|
+
Object.keys(methods)
|
|
67
|
+
.forEach(name => {
|
|
68
|
+
if (!methods[name]) return
|
|
69
|
+
|
|
70
|
+
const originalName = methods[name].originalName
|
|
71
|
+
const path = methods[name].path
|
|
72
|
+
const type = getType(methods[name])
|
|
73
|
+
|
|
74
|
+
if (methods[name]) {
|
|
75
|
+
proto[name] = wrapMethod(proto[name], path, type)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (originalName) {
|
|
79
|
+
proto[originalName] = wrapMethod(proto[originalName], path, type)
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function wrapMethod (method, path, type) {
|
|
85
|
+
if (typeof method !== 'function' || patched.has(method)) {
|
|
86
|
+
return method
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const wrapped = function () {
|
|
90
|
+
const args = ensureMetadata(this, arguments, 1)
|
|
91
|
+
|
|
92
|
+
return callMethod(this, method, args, path, args[1], type)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
Object.assign(wrapped, method)
|
|
96
|
+
|
|
97
|
+
patched.add(wrapped)
|
|
98
|
+
|
|
99
|
+
return wrapped
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function wrapCallback (requestResource, parentResource, callback) {
|
|
103
|
+
return function (err) {
|
|
104
|
+
if (err) {
|
|
105
|
+
requestResource.runInAsyncScope(() => {
|
|
106
|
+
errorChannel.publish(err)
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (callback) {
|
|
111
|
+
return parentResource.runInAsyncScope(() => {
|
|
112
|
+
return callback.apply(this, arguments)
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function wrapStream (call, requestResource, parentResource) {
|
|
119
|
+
if (!call || typeof call.emit !== 'function') return
|
|
120
|
+
|
|
121
|
+
shimmer.wrap(call, 'emit', emit => {
|
|
122
|
+
return function (eventName, ...args) {
|
|
123
|
+
requestResource.runInAsyncScope(() => {
|
|
124
|
+
switch (eventName) {
|
|
125
|
+
case 'error':
|
|
126
|
+
errorChannel.publish(args[0])
|
|
127
|
+
|
|
128
|
+
break
|
|
129
|
+
case 'status':
|
|
130
|
+
finishChannel.publish(args[0])
|
|
131
|
+
|
|
132
|
+
break
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
return parentResource.runInAsyncScope(() => {
|
|
137
|
+
return emit.apply(this, arguments)
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function callMethod (client, method, args, path, metadata, type) {
|
|
144
|
+
if (!startChannel.hasSubscribers) return method.apply(client, args)
|
|
145
|
+
|
|
146
|
+
const length = args.length
|
|
147
|
+
const callback = args[length - 1]
|
|
148
|
+
const parentResource = new AsyncResource('bound-anonymous-fn')
|
|
149
|
+
const requestResource = new AsyncResource('bound-anonymous-fn')
|
|
150
|
+
|
|
151
|
+
return requestResource.runInAsyncScope(() => {
|
|
152
|
+
startChannel.publish({ metadata, path, type })
|
|
153
|
+
|
|
154
|
+
if (type === types.unary || type === types.client_stream) {
|
|
155
|
+
if (typeof callback === 'function') {
|
|
156
|
+
args[length - 1] = wrapCallback(requestResource, parentResource, callback)
|
|
157
|
+
} else {
|
|
158
|
+
args[length] = wrapCallback(requestResource, parentResource)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const call = method.apply(client, args)
|
|
163
|
+
|
|
164
|
+
wrapStream(call, requestResource, parentResource)
|
|
165
|
+
|
|
166
|
+
return call
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function ensureMetadata (client, args, index) {
|
|
171
|
+
const grpc = getGrpc(client)
|
|
172
|
+
|
|
173
|
+
if (!client || !grpc) return args
|
|
174
|
+
|
|
175
|
+
const meta = args[index]
|
|
176
|
+
const normalized = []
|
|
177
|
+
|
|
178
|
+
for (let i = 0; i < index; i++) {
|
|
179
|
+
normalized.push(args[i])
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (!meta || !meta.constructor || meta.constructor.name !== 'Metadata') {
|
|
183
|
+
normalized.push(new grpc.Metadata())
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (meta) {
|
|
187
|
+
normalized.push(meta)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
for (let i = index + 1; i < args.length; i++) {
|
|
191
|
+
normalized.push(args[i])
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return normalized
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function getType (definition) {
|
|
198
|
+
if (definition.requestStream) {
|
|
199
|
+
if (definition.responseStream) {
|
|
200
|
+
return types.bidi
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return types.client_stream
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (definition.responseStream) {
|
|
207
|
+
return types.server_stream
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return types.unary
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function getGrpc (client) {
|
|
214
|
+
let proto = client
|
|
215
|
+
|
|
216
|
+
do {
|
|
217
|
+
const instance = instances.get(proto)
|
|
218
|
+
if (instance) return instance
|
|
219
|
+
} while ((proto = Object.getPrototypeOf(proto)))
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function patch (grpc) {
|
|
223
|
+
const proto = grpc.Client.prototype
|
|
224
|
+
|
|
225
|
+
instances.set(proto, grpc)
|
|
226
|
+
|
|
227
|
+
shimmer.wrap(proto, 'makeBidiStreamRequest', createWrapMakeRequest(types.bidi))
|
|
228
|
+
shimmer.wrap(proto, 'makeClientStreamRequest', createWrapMakeRequest(types.clientStream))
|
|
229
|
+
shimmer.wrap(proto, 'makeServerStreamRequest', createWrapMakeRequest(types.serverStream))
|
|
230
|
+
shimmer.wrap(proto, 'makeUnaryRequest', createWrapMakeRequest(types.unary))
|
|
231
|
+
|
|
232
|
+
return grpc
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
addHook({ name: 'grpc', versions: ['>=1.20.2'] }, patch)
|
|
236
|
+
|
|
237
|
+
addHook({ name: 'grpc', versions: ['>=1.20.2'], file: 'src/client.js' }, client => {
|
|
238
|
+
shimmer.wrap(client, 'makeClientConstructor', createWrapMakeClientConstructor())
|
|
239
|
+
|
|
240
|
+
return client
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
addHook({ name: '@grpc/grpc-js', versions: ['>=1.0.3'] }, patch)
|
|
244
|
+
|
|
245
|
+
addHook({ name: '@grpc/grpc-js', versions: ['>=1.0.3'], file: 'build/src/make-client.js' }, client => {
|
|
246
|
+
shimmer.wrap(client, 'makeClientConstructor', createWrapMakeClientConstructor())
|
|
247
|
+
shimmer.wrap(client, 'loadPackageDefinition', createWrapLoadPackageDefinition())
|
|
248
|
+
|
|
249
|
+
return client
|
|
250
|
+
})
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const types = require('./types')
|
|
4
|
+
const { channel, addHook, AsyncResource } = require('../helpers/instrument')
|
|
5
|
+
const shimmer = require('../../../datadog-shimmer')
|
|
6
|
+
|
|
7
|
+
const startChannel = channel('apm:grpc:server:request:start')
|
|
8
|
+
const errorChannel = channel('apm:grpc:server:request:error')
|
|
9
|
+
const updateChannel = channel('apm:grpc:server:request:update')
|
|
10
|
+
const finishChannel = channel('apm:grpc:server:request:finish')
|
|
11
|
+
|
|
12
|
+
// https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
|
|
13
|
+
const OK = 0
|
|
14
|
+
const CANCELLED = 1
|
|
15
|
+
|
|
16
|
+
function wrapHandler (func, name) {
|
|
17
|
+
const isValid = (server, args) => {
|
|
18
|
+
if (!startChannel.hasSubscribers) return false
|
|
19
|
+
if (!server || !server.type) return false
|
|
20
|
+
if (!args[0]) return false
|
|
21
|
+
if (server.type !== 'unary' && !isEmitter(args[0])) return false
|
|
22
|
+
if (server.type === 'unary' && typeof args[1] !== 'function') return false
|
|
23
|
+
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return function (call, callback) {
|
|
28
|
+
if (!isValid(this, arguments)) return func.apply(this, arguments)
|
|
29
|
+
|
|
30
|
+
const metadata = call.metadata
|
|
31
|
+
const type = types[this.type]
|
|
32
|
+
const isStream = type !== 'unary'
|
|
33
|
+
|
|
34
|
+
const parentResource = new AsyncResource('bound-anonymous-fn')
|
|
35
|
+
const requestResource = new AsyncResource('bound-anonymous-fn')
|
|
36
|
+
|
|
37
|
+
return requestResource.runInAsyncScope(() => {
|
|
38
|
+
startChannel.publish({ name, metadata, type })
|
|
39
|
+
|
|
40
|
+
// Finish the span if the call was cancelled.
|
|
41
|
+
call.once('cancelled', requestResource.bind(() => {
|
|
42
|
+
finishChannel.publish({ code: CANCELLED })
|
|
43
|
+
}))
|
|
44
|
+
|
|
45
|
+
if (isStream) {
|
|
46
|
+
wrapStream(call, requestResource, parentResource)
|
|
47
|
+
} else {
|
|
48
|
+
arguments[1] = wrapCallback(callback, requestResource, parentResource)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
shimmer.wrap(call, 'emit', emit => requestResource.bind(emit))
|
|
52
|
+
|
|
53
|
+
return func.apply(this, arguments)
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function wrapRegister (register) {
|
|
59
|
+
return function (name, handler, serialize, deserialize, type) {
|
|
60
|
+
if (typeof handler === 'function') {
|
|
61
|
+
arguments[1] = wrapHandler(handler, name)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return register.apply(this, arguments)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function wrapStream (call, requestResource) {
|
|
69
|
+
if (call.call && call.call.sendStatus) {
|
|
70
|
+
call.call.sendStatus = wrapSendStatus(call.call.sendStatus, requestResource)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
shimmer.wrap(call, 'emit', emit => {
|
|
74
|
+
return function (eventName, ...args) {
|
|
75
|
+
switch (eventName) {
|
|
76
|
+
case 'error':
|
|
77
|
+
errorChannel.publish(args[0])
|
|
78
|
+
finishChannel.publish({ code: args[0].code })
|
|
79
|
+
|
|
80
|
+
break
|
|
81
|
+
|
|
82
|
+
// Finish the span of the response only if it was successful.
|
|
83
|
+
// Otherwise it'll be finished in the `error` listener.
|
|
84
|
+
case 'finish':
|
|
85
|
+
if (call.status) {
|
|
86
|
+
updateChannel.publish(call.status)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!call.status || call.status.code === 0) {
|
|
90
|
+
finishChannel.publish()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
break
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return emit.apply(this, arguments)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function wrapCallback (callback, requestResource, parentResource) {
|
|
102
|
+
return function (err, value, trailer, flags) {
|
|
103
|
+
requestResource.runInAsyncScope(() => {
|
|
104
|
+
if (err instanceof Error) {
|
|
105
|
+
errorChannel.publish(err)
|
|
106
|
+
finishChannel.publish(err)
|
|
107
|
+
} else {
|
|
108
|
+
finishChannel.publish({ code: OK, trailer })
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
if (callback) {
|
|
113
|
+
return parentResource.runInAsyncScope(() => {
|
|
114
|
+
return callback.apply(this, arguments)
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function wrapSendStatus (sendStatus, requestResource) {
|
|
121
|
+
return function (status) {
|
|
122
|
+
requestResource.runInAsyncScope(() => {
|
|
123
|
+
updateChannel.publish(status)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
return sendStatus.apply(this, arguments)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function isEmitter (obj) {
|
|
131
|
+
return typeof obj.emit === 'function' && typeof obj.once === 'function'
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
addHook({ name: 'grpc', versions: ['>=1.20.2'], file: 'src/server.js' }, server => {
|
|
135
|
+
shimmer.wrap(server.Server.prototype, 'register', wrapRegister)
|
|
136
|
+
|
|
137
|
+
return server
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
addHook({ name: '@grpc/grpc-js', versions: ['>=1.0.3'], file: 'build/src/server.js' }, server => {
|
|
141
|
+
shimmer.wrap(server.Server.prototype, 'register', wrapRegister)
|
|
142
|
+
|
|
143
|
+
return server
|
|
144
|
+
})
|
package/packages/{datadog-plugin-grpc/src/kinds.js → datadog-instrumentations/src/grpc/types.js}
RENAMED
|
File without changes
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../../datadog-shimmer')
|
|
4
|
+
const { addHook, channel, AsyncResource } = require('../helpers/instrument')
|
|
5
|
+
|
|
6
|
+
const startChannel = channel('apm:http2:client:request:start')
|
|
7
|
+
const finishChannel = channel('apm:http2:client:request:finish')
|
|
8
|
+
const errorChannel = channel('apm:http2:client:request:error')
|
|
9
|
+
const responseChannel = channel('apm:http2:client:response')
|
|
10
|
+
|
|
11
|
+
function createWrapEmit (requestResource, parentResource) {
|
|
12
|
+
return function wrapEmit (emit) {
|
|
13
|
+
return function (event, arg1) {
|
|
14
|
+
requestResource.runInAsyncScope(() => {
|
|
15
|
+
switch (event) {
|
|
16
|
+
case 'response':
|
|
17
|
+
responseChannel.publish(arg1)
|
|
18
|
+
break
|
|
19
|
+
case 'error':
|
|
20
|
+
errorChannel.publish(arg1)
|
|
21
|
+
case 'close': // eslint-disable-line no-fallthrough
|
|
22
|
+
finishChannel.publish()
|
|
23
|
+
break
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
return parentResource.runInAsyncScope(() => {
|
|
28
|
+
return emit.apply(this, arguments)
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function createWrapRequest (authority, options) {
|
|
35
|
+
return function wrapRequest (request) {
|
|
36
|
+
return function (headers) {
|
|
37
|
+
const parentResource = new AsyncResource('bound-anonymous-fn')
|
|
38
|
+
const requestResource = new AsyncResource('bound-anonymous-fn')
|
|
39
|
+
|
|
40
|
+
return requestResource.runInAsyncScope(() => {
|
|
41
|
+
startChannel.publish({ headers, authority, options })
|
|
42
|
+
|
|
43
|
+
const req = request.apply(this, arguments)
|
|
44
|
+
|
|
45
|
+
shimmer.wrap(req, 'emit', createWrapEmit(requestResource, parentResource))
|
|
46
|
+
|
|
47
|
+
return req
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function wrapConnect (connect) {
|
|
54
|
+
return function (authority, options) {
|
|
55
|
+
const session = connect.apply(this, arguments)
|
|
56
|
+
|
|
57
|
+
shimmer.wrap(session, 'request', createWrapRequest(authority, options))
|
|
58
|
+
|
|
59
|
+
return session
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
addHook({ name: 'http2' }, http2 => {
|
|
64
|
+
shimmer.wrap(http2, 'connect', wrapConnect)
|
|
65
|
+
|
|
66
|
+
return http2
|
|
67
|
+
})
|
|
@@ -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:koa:middleware:enter')
|
|
7
|
+
const exitChannel = channel('apm:koa:middleware:exit')
|
|
7
8
|
const errorChannel = channel('apm:koa:middleware:error')
|
|
8
9
|
const nextChannel = channel('apm:koa:middleware:next')
|
|
9
10
|
const handleChannel = channel('apm:koa:request:handle')
|
|
@@ -95,7 +96,7 @@ function wrapMiddleware (fn, layer) {
|
|
|
95
96
|
enterChannel.publish({ req, name, route })
|
|
96
97
|
|
|
97
98
|
if (typeof next === 'function') {
|
|
98
|
-
arguments[1] = next
|
|
99
|
+
arguments[1] = wrapNext(req, next)
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
try {
|
|
@@ -125,19 +126,27 @@ function wrapMiddleware (fn, layer) {
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
function fulfill (ctx, error) {
|
|
128
|
-
if (error) {
|
|
129
|
-
errorChannel.publish(error)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
129
|
const req = ctx.req
|
|
133
130
|
const route = ctx.routePath
|
|
134
131
|
|
|
132
|
+
if (error) {
|
|
133
|
+
errorChannel.publish({ req, error })
|
|
134
|
+
}
|
|
135
|
+
|
|
135
136
|
// TODO: make sure that the parent class cannot override this in `enter`
|
|
136
137
|
if (route) {
|
|
137
138
|
routeChannel.publish({ req, route })
|
|
138
139
|
}
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
exitChannel.publish({ req })
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function wrapNext (req, next) {
|
|
145
|
+
return function () {
|
|
146
|
+
nextChannel.publish({ req })
|
|
147
|
+
|
|
148
|
+
return next.apply(null, arguments)
|
|
149
|
+
}
|
|
141
150
|
}
|
|
142
151
|
|
|
143
152
|
addHook({ name: 'koa', versions: ['>=2'] }, Koa => {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
5
|
+
|
|
6
|
+
const handleChannel = channel('apm:microgateway-core:request:handle')
|
|
7
|
+
const routeChannel = channel('apm:microgateway-core:request:route')
|
|
8
|
+
const errorChannel = channel('apm:microgateway-core:request:error')
|
|
9
|
+
|
|
10
|
+
const name = 'microgateway-core'
|
|
11
|
+
const versions = ['>=2.1']
|
|
12
|
+
const requestResources = new WeakMap()
|
|
13
|
+
|
|
14
|
+
function wrapConfigProxyFactory (configProxyFactory) {
|
|
15
|
+
return function () {
|
|
16
|
+
const configProxy = configProxyFactory.apply(this, arguments)
|
|
17
|
+
|
|
18
|
+
return function (req, res, next) {
|
|
19
|
+
const requestResource = new AsyncResource('bound-anonymous-fn')
|
|
20
|
+
|
|
21
|
+
requestResources.set(req, requestResource)
|
|
22
|
+
|
|
23
|
+
handleChannel.publish({ req, res })
|
|
24
|
+
|
|
25
|
+
return configProxy.apply(this, arguments)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function wrapPluginsFactory (pluginsFactory) {
|
|
31
|
+
return function (plugins) {
|
|
32
|
+
const pluginsMiddleware = pluginsFactory.apply(this, arguments)
|
|
33
|
+
|
|
34
|
+
return function pluginsMiddlewareWithTrace (req, res, next) {
|
|
35
|
+
arguments[2] = wrapNext(req, res, next)
|
|
36
|
+
|
|
37
|
+
return pluginsMiddleware.apply(this, arguments)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function wrapNext (req, res, next) {
|
|
43
|
+
return function nextWithTrace (err) {
|
|
44
|
+
const requestResource = requestResources.get(req)
|
|
45
|
+
|
|
46
|
+
requestResource.runInAsyncScope(() => {
|
|
47
|
+
if (err) {
|
|
48
|
+
errorChannel.publish(err)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (res.proxy && res.proxy.base_path) {
|
|
52
|
+
routeChannel.publish({ req, res, route: res.proxy.base_path })
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
return next.apply(this, arguments)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
addHook({ name, versions, file: 'lib/config-proxy-middleware.js' }, configProxyFactory => {
|
|
61
|
+
return shimmer.wrap(configProxyFactory, wrapConfigProxyFactory(configProxyFactory))
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
addHook({ name, versions, file: 'lib/plugins-middleware.js' }, pluginsFactory => {
|
|
65
|
+
return shimmer.wrap(pluginsFactory, wrapPluginsFactory(pluginsFactory))
|
|
66
|
+
})
|