dd-trace 2.3.1 → 2.4.2
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/ci/init.js +26 -2
- package/index.d.ts +51 -0
- package/package.json +2 -2
- package/packages/datadog-instrumentations/index.js +10 -0
- package/packages/datadog-instrumentations/src/amqp10.js +70 -0
- package/packages/datadog-instrumentations/src/amqplib.js +58 -0
- package/packages/datadog-instrumentations/src/cassandra-driver.js +191 -0
- package/packages/datadog-instrumentations/src/cucumber.js +27 -12
- package/packages/datadog-instrumentations/src/helpers/hook.js +44 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +31 -58
- package/packages/datadog-instrumentations/src/http/client.js +170 -0
- package/packages/datadog-instrumentations/src/http/server.js +61 -0
- package/packages/datadog-instrumentations/src/http.js +4 -0
- package/packages/datadog-instrumentations/src/mocha.js +139 -0
- package/packages/datadog-instrumentations/src/mongodb-core.js +179 -0
- package/packages/datadog-instrumentations/src/net.js +117 -0
- package/packages/datadog-instrumentations/src/pg.js +75 -0
- package/packages/datadog-instrumentations/src/rhea.js +224 -0
- package/packages/datadog-instrumentations/src/tedious.js +66 -0
- package/packages/datadog-plugin-amqp10/src/index.js +79 -122
- package/packages/datadog-plugin-amqplib/src/index.js +77 -142
- package/packages/datadog-plugin-cassandra-driver/src/index.js +52 -224
- package/packages/datadog-plugin-cucumber/src/index.js +3 -1
- package/packages/datadog-plugin-elasticsearch/src/index.js +4 -2
- package/packages/datadog-plugin-http/src/client.js +112 -252
- package/packages/datadog-plugin-http/src/index.js +29 -3
- package/packages/datadog-plugin-http/src/server.js +54 -32
- package/packages/datadog-plugin-jest/src/jest-environment.js +3 -3
- package/packages/datadog-plugin-jest/src/jest-jasmine2.js +5 -3
- package/packages/datadog-plugin-mocha/src/index.js +96 -207
- package/packages/datadog-plugin-mongodb-core/src/index.js +119 -3
- package/packages/datadog-plugin-net/src/index.js +65 -121
- package/packages/datadog-plugin-next/src/index.js +10 -10
- package/packages/datadog-plugin-pg/src/index.js +32 -69
- package/packages/datadog-plugin-rhea/src/index.js +59 -225
- package/packages/datadog-plugin-tedious/src/index.js +38 -86
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/appsec/recommended.json +235 -315
- package/packages/dd-trace/src/config.js +6 -0
- package/packages/dd-trace/src/iitm.js +5 -1
- package/packages/dd-trace/src/loader.js +6 -4
- package/packages/dd-trace/src/noop/tracer.js +4 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +34 -1
- package/packages/dd-trace/src/opentracing/span.js +34 -0
- package/packages/dd-trace/src/plugin_manager.js +4 -0
- package/packages/dd-trace/src/plugins/plugin.js +3 -1
- package/packages/dd-trace/src/plugins/util/web.js +99 -93
- package/packages/dd-trace/src/proxy.js +4 -0
- package/packages/dd-trace/src/ritm.js +60 -25
- package/packages/dd-trace/src/tracer.js +16 -0
- package/packages/datadog-plugin-mongodb-core/src/legacy.js +0 -59
- package/packages/datadog-plugin-mongodb-core/src/unified.js +0 -138
- package/packages/datadog-plugin-mongodb-core/src/util.js +0 -143
|
@@ -1,40 +1,29 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
|
+
const { storage } = require('../../datadog-core')
|
|
5
5
|
const tags = require('../../../ext/tags')
|
|
6
|
-
const
|
|
6
|
+
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
7
7
|
const formats = require('../../../ext/formats')
|
|
8
|
+
const HTTP_HEADERS = formats.HTTP_HEADERS
|
|
8
9
|
const urlFilter = require('../../dd-trace/src/plugins/util/urlfilter')
|
|
9
|
-
const
|
|
10
|
-
const
|
|
10
|
+
const log = require('../../dd-trace/src/log')
|
|
11
|
+
const url = require('url')
|
|
11
12
|
|
|
12
|
-
const HTTP_HEADERS = formats.HTTP_HEADERS
|
|
13
13
|
const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
|
|
14
14
|
const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
|
|
15
15
|
const HTTP_RESPONSE_HEADERS = tags.HTTP_RESPONSE_HEADERS
|
|
16
|
-
const SPAN_KIND = tags.SPAN_KIND
|
|
17
|
-
const CLIENT = kinds.CLIENT
|
|
18
|
-
|
|
19
|
-
function patch (http, methodName, tracer, config) {
|
|
20
|
-
config = normalizeConfig(tracer, config)
|
|
21
|
-
this.wrap(http, methodName, fn => makeRequestTrace(fn))
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (store && store.noop) return request.apply(this, arguments)
|
|
28
|
-
|
|
29
|
-
let args
|
|
17
|
+
class HttpClientPlugin extends Plugin {
|
|
18
|
+
static get name () {
|
|
19
|
+
return 'http'
|
|
20
|
+
}
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
} catch (e) {
|
|
34
|
-
log.error(e)
|
|
35
|
-
return request.apply(this, arguments)
|
|
36
|
-
}
|
|
22
|
+
constructor (...args) {
|
|
23
|
+
super(...args)
|
|
37
24
|
|
|
25
|
+
this.addSub('apm:http:client:request:start', ({ args, http }) => {
|
|
26
|
+
const store = storage.getStore()
|
|
38
27
|
const options = args.options
|
|
39
28
|
const agent = options.agent || options._defaultAgent || http.globalAgent
|
|
40
29
|
const protocol = options.protocol || agent.protocol || 'http:'
|
|
@@ -43,17 +32,13 @@ function patch (http, methodName, tracer, config) {
|
|
|
43
32
|
const path = options.path ? options.path.split(/[?#]/)[0] : '/'
|
|
44
33
|
const uri = `${protocol}//${host}${path}`
|
|
45
34
|
|
|
46
|
-
let callback = args.callback
|
|
47
|
-
|
|
48
35
|
const method = (options.method || 'GET').toUpperCase()
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
const childOf = scope.active()
|
|
52
|
-
const span = tracer.startSpan('http.request', {
|
|
36
|
+
const childOf = store ? store.span : store
|
|
37
|
+
const span = this.tracer.startSpan('http.request', {
|
|
53
38
|
childOf,
|
|
54
39
|
tags: {
|
|
55
|
-
|
|
56
|
-
'service.name': getServiceName(tracer, config, options),
|
|
40
|
+
'span.kind': 'client',
|
|
41
|
+
'service.name': getServiceName(this.tracer, this.config, options),
|
|
57
42
|
'resource.name': method,
|
|
58
43
|
'span.type': 'http',
|
|
59
44
|
'http.method': method,
|
|
@@ -61,184 +46,117 @@ function patch (http, methodName, tracer, config) {
|
|
|
61
46
|
}
|
|
62
47
|
})
|
|
63
48
|
|
|
64
|
-
if (!(hasAmazonSignature(options) || !config.propagationFilter(uri))) {
|
|
65
|
-
tracer.inject(span, HTTP_HEADERS, options.headers)
|
|
49
|
+
if (!(hasAmazonSignature(options) || !this.config.propagationFilter(uri))) {
|
|
50
|
+
this.tracer.inject(span, HTTP_HEADERS, options.headers)
|
|
66
51
|
}
|
|
67
52
|
|
|
68
|
-
analyticsSampler.sample(span, config.measured)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const req = scope.bind(request, span).call(this, options, callback)
|
|
73
|
-
const emit = req.emit
|
|
74
|
-
|
|
75
|
-
req.emit = function (eventName, arg) {
|
|
76
|
-
switch (eventName) {
|
|
77
|
-
case 'response': {
|
|
78
|
-
const res = arg
|
|
53
|
+
analyticsSampler.sample(span, this.config.measured)
|
|
54
|
+
this.enter(span, store)
|
|
55
|
+
})
|
|
79
56
|
|
|
80
|
-
|
|
57
|
+
this.addSub('apm:http:client:request:end', this.exit.bind(this))
|
|
81
58
|
|
|
82
|
-
|
|
59
|
+
this.addSub('apm:http:client:request:async-end', ({ req, res }) => {
|
|
60
|
+
const span = storage.getStore().span
|
|
61
|
+
if (res) {
|
|
62
|
+
span.setTag(HTTP_STATUS_CODE, res.statusCode)
|
|
83
63
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
case 'error':
|
|
87
|
-
addError(span, arg)
|
|
88
|
-
case 'abort': // eslint-disable-line no-fallthrough
|
|
89
|
-
case 'timeout': // eslint-disable-line no-fallthrough
|
|
90
|
-
finish(req, null, span, config)
|
|
64
|
+
if (!this.config.validateStatus(res.statusCode)) {
|
|
65
|
+
span.setTag('error', 1)
|
|
91
66
|
}
|
|
92
67
|
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
scope.bind(req)
|
|
97
|
-
|
|
98
|
-
return req
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function finish (req, res, span, config) {
|
|
103
|
-
if (res) {
|
|
104
|
-
span.setTag(HTTP_STATUS_CODE, res.statusCode)
|
|
105
|
-
|
|
106
|
-
if (!config.validateStatus(res.statusCode)) {
|
|
68
|
+
addResponseHeaders(res, span, this.config)
|
|
69
|
+
} else {
|
|
107
70
|
span.setTag('error', 1)
|
|
108
71
|
}
|
|
109
72
|
|
|
110
|
-
|
|
111
|
-
} else {
|
|
112
|
-
span.setTag('error', 1)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
addRequestHeaders(req, span, config)
|
|
73
|
+
addRequestHeaders(req, span, this.config)
|
|
116
74
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
span.finish()
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function addError (span, error) {
|
|
123
|
-
span.addTags({
|
|
124
|
-
'error.type': error.name,
|
|
125
|
-
'error.msg': error.message,
|
|
126
|
-
'error.stack': error.stack
|
|
75
|
+
this.config.hooks.request(span, req, res)
|
|
76
|
+
span.finish()
|
|
127
77
|
})
|
|
128
78
|
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function addRequestHeaders (req, span, config) {
|
|
133
|
-
config.headers.forEach(key => {
|
|
134
|
-
const value = req.getHeader(key)
|
|
135
|
-
|
|
136
|
-
if (value) {
|
|
137
|
-
span.setTag(`${HTTP_REQUEST_HEADERS}.${key}`, value)
|
|
138
|
-
}
|
|
139
|
-
})
|
|
79
|
+
this.addSub('apm:http:client:request:error', errorHandler)
|
|
140
80
|
}
|
|
141
81
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const value = res.headers[key]
|
|
145
|
-
|
|
146
|
-
if (value) {
|
|
147
|
-
span.setTag(`${HTTP_RESPONSE_HEADERS}.${key}`, value)
|
|
148
|
-
}
|
|
149
|
-
})
|
|
82
|
+
configure (config) {
|
|
83
|
+
return super.configure(normalizeClientConfig(config))
|
|
150
84
|
}
|
|
85
|
+
}
|
|
151
86
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
87
|
+
function errorHandler (err) {
|
|
88
|
+
const span = storage.getStore().span
|
|
89
|
+
span.addTags({
|
|
90
|
+
'error.type': err.name,
|
|
91
|
+
'error.msg': err.message,
|
|
92
|
+
'error.stack': err.stack
|
|
93
|
+
})
|
|
94
|
+
}
|
|
159
95
|
|
|
160
|
-
|
|
161
|
-
|
|
96
|
+
function addResponseHeaders (res, span, config) {
|
|
97
|
+
config.headers.forEach(key => {
|
|
98
|
+
const value = res.headers[key]
|
|
162
99
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return [inputOptions, inputURL || {}]
|
|
166
|
-
} else {
|
|
167
|
-
return [callback, inputOptions]
|
|
100
|
+
if (value) {
|
|
101
|
+
span.setTag(`${HTTP_RESPONSE_HEADERS}.${key}`, value)
|
|
168
102
|
}
|
|
169
|
-
}
|
|
103
|
+
})
|
|
104
|
+
}
|
|
170
105
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
106
|
+
function addRequestHeaders (req, span, config) {
|
|
107
|
+
config.headers.forEach(key => {
|
|
108
|
+
const value = req.getHeader(key)
|
|
109
|
+
|
|
110
|
+
if (value) {
|
|
111
|
+
span.setTag(`${HTTP_REQUEST_HEADERS}.${key}`, value)
|
|
176
112
|
}
|
|
177
|
-
}
|
|
113
|
+
})
|
|
114
|
+
}
|
|
178
115
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
116
|
+
function normalizeClientConfig (config) {
|
|
117
|
+
const validateStatus = getStatusValidator(config)
|
|
118
|
+
const propagationFilter = getFilter({ blocklist: config.propagationBlocklist })
|
|
119
|
+
const headers = getHeaders(config)
|
|
120
|
+
const hooks = getHooks(config)
|
|
182
121
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
: url.hostname ||
|
|
191
|
-
url.host ||
|
|
192
|
-
'localhost',
|
|
193
|
-
hash: url.hash,
|
|
194
|
-
search: url.search,
|
|
195
|
-
pathname: url.pathname,
|
|
196
|
-
path: `${url.pathname || ''}${url.search || ''}`,
|
|
197
|
-
href: url.href
|
|
198
|
-
}
|
|
199
|
-
if (url.port !== '') {
|
|
200
|
-
options.port = Number(url.port)
|
|
201
|
-
}
|
|
202
|
-
if (url.username || url.password) {
|
|
203
|
-
options.auth = `${url.username}:${url.password}`
|
|
204
|
-
}
|
|
205
|
-
return options
|
|
206
|
-
}
|
|
122
|
+
return Object.assign({}, config, {
|
|
123
|
+
validateStatus,
|
|
124
|
+
propagationFilter,
|
|
125
|
+
headers,
|
|
126
|
+
hooks
|
|
127
|
+
})
|
|
128
|
+
}
|
|
207
129
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return url.parse(inputURL)
|
|
214
|
-
}
|
|
215
|
-
} else if (inputURL instanceof url.URL) {
|
|
216
|
-
return urlToOptions(inputURL)
|
|
217
|
-
} else {
|
|
218
|
-
return inputURL
|
|
219
|
-
}
|
|
130
|
+
function getStatusValidator (config) {
|
|
131
|
+
if (typeof config.validateStatus === 'function') {
|
|
132
|
+
return config.validateStatus
|
|
133
|
+
} else if (config.hasOwnProperty('validateStatus')) {
|
|
134
|
+
log.error('Expected `validateStatus` to be a function.')
|
|
220
135
|
}
|
|
136
|
+
return code => code < 400 || code >= 500
|
|
221
137
|
}
|
|
222
138
|
|
|
223
|
-
function
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
139
|
+
function getFilter (config) {
|
|
140
|
+
config = Object.assign({}, config, {
|
|
141
|
+
blocklist: config.blocklist || []
|
|
142
|
+
})
|
|
227
143
|
|
|
228
|
-
|
|
229
|
-
|
|
144
|
+
return urlFilter.getFilter(config)
|
|
145
|
+
}
|
|
230
146
|
|
|
231
|
-
|
|
147
|
+
function getHeaders (config) {
|
|
148
|
+
if (!Array.isArray(config.headers)) return []
|
|
149
|
+
|
|
150
|
+
return config.headers
|
|
151
|
+
.filter(key => typeof key === 'string')
|
|
152
|
+
.map(key => key.toLowerCase())
|
|
232
153
|
}
|
|
233
154
|
|
|
234
|
-
function
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
} else if (config.service) {
|
|
238
|
-
return config.service
|
|
239
|
-
}
|
|
155
|
+
function getHooks (config) {
|
|
156
|
+
const noop = () => {}
|
|
157
|
+
const request = (config.hooks && config.hooks.request) || noop
|
|
240
158
|
|
|
241
|
-
return
|
|
159
|
+
return { request }
|
|
242
160
|
}
|
|
243
161
|
|
|
244
162
|
function hasAmazonSignature (options) {
|
|
@@ -264,87 +182,29 @@ function hasAmazonSignature (options) {
|
|
|
264
182
|
return options.path && options.path.toLowerCase().indexOf('x-amz-signature=') !== -1
|
|
265
183
|
}
|
|
266
184
|
|
|
267
|
-
function
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
this.unwrap(http, 'request')
|
|
273
|
-
this.unwrap(http, 'get')
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function getStatusValidator (config) {
|
|
277
|
-
if (typeof config.validateStatus === 'function') {
|
|
278
|
-
return config.validateStatus
|
|
279
|
-
} else if (config.hasOwnProperty('validateStatus')) {
|
|
280
|
-
log.error('Expected `validateStatus` to be a function.')
|
|
185
|
+
function getServiceName (tracer, config, options) {
|
|
186
|
+
if (config.splitByDomain) {
|
|
187
|
+
return getHost(options)
|
|
188
|
+
} else if (config.service) {
|
|
189
|
+
return config.service
|
|
281
190
|
}
|
|
282
|
-
return code => code < 400 || code >= 500
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function getFilter (config) {
|
|
286
|
-
config = Object.assign({}, config, {
|
|
287
|
-
blocklist: config.blocklist || []
|
|
288
|
-
})
|
|
289
191
|
|
|
290
|
-
return
|
|
192
|
+
return `${tracer._service}-http-client`
|
|
291
193
|
}
|
|
292
194
|
|
|
293
|
-
function
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const propagationFilter = getFilter({ blocklist: config.propagationBlocklist })
|
|
298
|
-
const headers = getHeaders(config)
|
|
299
|
-
const hooks = getHooks(config)
|
|
300
|
-
|
|
301
|
-
return Object.assign({}, config, {
|
|
302
|
-
validateStatus,
|
|
303
|
-
propagationFilter,
|
|
304
|
-
headers,
|
|
305
|
-
hooks
|
|
306
|
-
})
|
|
307
|
-
}
|
|
195
|
+
function getHost (options) {
|
|
196
|
+
if (typeof options === 'string') {
|
|
197
|
+
return url.parse(options).host
|
|
198
|
+
}
|
|
308
199
|
|
|
309
|
-
|
|
310
|
-
|
|
200
|
+
const hostname = options.hostname || options.host || 'localhost'
|
|
201
|
+
const port = options.port
|
|
311
202
|
|
|
312
|
-
return
|
|
313
|
-
.filter(key => typeof key === 'string')
|
|
314
|
-
.map(key => key.toLowerCase())
|
|
203
|
+
return [hostname, port].filter(val => val).join(':')
|
|
315
204
|
}
|
|
316
205
|
|
|
317
|
-
function
|
|
318
|
-
|
|
319
|
-
const request = (config.hooks && config.hooks.request) || noop
|
|
320
|
-
|
|
321
|
-
return { request }
|
|
206
|
+
function startsWith (searchString) {
|
|
207
|
+
return value => String(value).startsWith(searchString)
|
|
322
208
|
}
|
|
323
209
|
|
|
324
|
-
module.exports =
|
|
325
|
-
{
|
|
326
|
-
name: 'http',
|
|
327
|
-
patch: function (http, tracer, config) {
|
|
328
|
-
if (config.client === false) return
|
|
329
|
-
|
|
330
|
-
patch.call(this, http, 'request', tracer, config)
|
|
331
|
-
/**
|
|
332
|
-
* References internal to modules, such as `http(s).get` calling
|
|
333
|
-
* `http(s).request`, do not use externally patched versions, which is
|
|
334
|
-
* why we need to also patch `get` here separately.
|
|
335
|
-
*/
|
|
336
|
-
patch.call(this, http, 'get', tracer, config)
|
|
337
|
-
},
|
|
338
|
-
unpatch
|
|
339
|
-
},
|
|
340
|
-
{
|
|
341
|
-
name: 'https',
|
|
342
|
-
patch: function (http, tracer, config) {
|
|
343
|
-
if (config.client === false) return
|
|
344
|
-
|
|
345
|
-
patch.call(this, http, 'request', tracer, config)
|
|
346
|
-
patch.call(this, http, 'get', tracer, config)
|
|
347
|
-
},
|
|
348
|
-
unpatch
|
|
349
|
-
}
|
|
350
|
-
]
|
|
210
|
+
module.exports = HttpClientPlugin
|
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
|
+
const HttpServerPlugin = require('./server')
|
|
5
|
+
const HttpClientPlugin = require('./client')
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
class HttpPlugin extends Plugin {
|
|
8
|
+
static get name () {
|
|
9
|
+
return 'http'
|
|
10
|
+
}
|
|
11
|
+
constructor (...args) {
|
|
12
|
+
super(...args)
|
|
13
|
+
this.server = new HttpServerPlugin(...args)
|
|
14
|
+
this.client = new HttpClientPlugin(...args)
|
|
15
|
+
}
|
|
16
|
+
configure (config) {
|
|
17
|
+
const clientConfig = config.client === false ? false : {
|
|
18
|
+
...config,
|
|
19
|
+
...config.client
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const serverConfig = config.server === false ? false : {
|
|
23
|
+
...config,
|
|
24
|
+
...config.server
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
this.server.configure(serverConfig)
|
|
28
|
+
this.client.configure(clientConfig)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = HttpPlugin
|
|
@@ -1,47 +1,69 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
|
+
const { storage } = require('../../datadog-core')
|
|
3
5
|
const web = require('../../dd-trace/src/plugins/util/web')
|
|
4
|
-
const Scope = require('../../dd-trace/src/scope')
|
|
5
6
|
const { incomingHttpRequestStart } = require('../../dd-trace/src/appsec/gateway/channels')
|
|
7
|
+
const tags = require('../../../ext/tags')
|
|
8
|
+
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
9
|
+
const SERVICE_NAME = tags.SERVICE_NAME
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
class HttpServerPlugin extends Plugin {
|
|
12
|
+
static get name () {
|
|
13
|
+
return 'http'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
constructor (...args) {
|
|
17
|
+
super(...args)
|
|
9
18
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return web.instrument(tracer, config, req, res, 'http.request', () => {
|
|
14
|
-
if (incomingHttpRequestStart.hasSubscribers) {
|
|
15
|
-
incomingHttpRequestStart.publish({ req, res })
|
|
16
|
-
}
|
|
19
|
+
this.addSub('apm:http:server:request:start', ({ req, res }) => {
|
|
20
|
+
const store = storage.getStore()
|
|
21
|
+
const span = web.startSpan(this.tracer, this.config, req, res, 'http.request')
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
if (this.config.service) {
|
|
24
|
+
span.setTag(SERVICE_NAME, this.config.service)
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
}
|
|
27
|
+
analyticsSampler.sample(span, this.config.measured, true)
|
|
28
|
+
this.enter(span, store)
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
name,
|
|
30
|
-
patch (http, tracer, config) {
|
|
31
|
-
if (config.server === false) return
|
|
30
|
+
const context = web.getContext(req)
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
if (!context.instrumented) {
|
|
33
|
+
context.res.writeHead = web.wrapWriteHead(context)
|
|
34
|
+
context.instrumented = true
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
|
|
37
|
+
if (incomingHttpRequestStart.hasSubscribers) {
|
|
38
|
+
incomingHttpRequestStart.publish({ req, res })
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
this.addSub('apm:http:server:request:end', () => {
|
|
43
|
+
this.exit()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
this.addSub('apm:http:server:request:error', (error) => {
|
|
47
|
+
const span = storage.getStore().span
|
|
48
|
+
span.addTags({
|
|
49
|
+
'error.type': error.name,
|
|
50
|
+
'error.msg': error.message,
|
|
51
|
+
'error.stack': error.stack
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
this.addSub('apm:http:server:request:async-end', ({ req }) => {
|
|
56
|
+
const context = web.getContext(req)
|
|
57
|
+
|
|
58
|
+
if (!context) return // Not created by a http.Server instance.
|
|
59
|
+
|
|
60
|
+
web.wrapRes(context, context.req, context.res, context.res.end)()
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
configure (config) {
|
|
65
|
+
return super.configure(web.normalizeConfig(config))
|
|
41
66
|
}
|
|
42
67
|
}
|
|
43
68
|
|
|
44
|
-
module.exports =
|
|
45
|
-
plugin('http'),
|
|
46
|
-
plugin('https')
|
|
47
|
-
]
|
|
69
|
+
module.exports = HttpServerPlugin
|
|
@@ -56,10 +56,10 @@ function createWrapTeardown (tracer, instrumenter) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
instrumenter.unwrap(this.global.test, 'each')
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
|
|
60
|
+
return teardown.apply(this, arguments).finally(() => {
|
|
61
|
+
return new Promise(resolve => tracer._exporter._writer.flush(resolve))
|
|
61
62
|
})
|
|
62
|
-
return teardown.apply(this, arguments)
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -97,9 +97,11 @@ function createWrapOnException (tracer, globalInput) {
|
|
|
97
97
|
if (isActiveSpanFailing && !testStatus) {
|
|
98
98
|
activeTestSpan.setTag(TEST_STATUS, 'fail')
|
|
99
99
|
// If we don't do this, jest will show this file on its error message
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
if (err.stack) {
|
|
101
|
+
const stackFrames = err.stack.split('\n')
|
|
102
|
+
const filteredStackFrames = stackFrames.filter(frame => !frame.includes(__dirname)).join('\n')
|
|
103
|
+
err.stack = filteredStackFrames
|
|
104
|
+
}
|
|
103
105
|
activeTestSpan.setTag('error', err)
|
|
104
106
|
// need to manually finish, as it will not be caught in `itWithTrace`
|
|
105
107
|
activeTestSpan.finish()
|