dd-trace 2.2.0 → 2.3.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.
Files changed (55) hide show
  1. package/LICENSE-3rdparty.csv +0 -2
  2. package/index.d.ts +6 -12
  3. package/package.json +3 -5
  4. package/packages/datadog-instrumentations/index.js +9 -0
  5. package/packages/datadog-instrumentations/src/bunyan.js +22 -0
  6. package/packages/datadog-instrumentations/src/cucumber.js +116 -0
  7. package/packages/datadog-instrumentations/src/elasticsearch.js +15 -5
  8. package/packages/datadog-instrumentations/src/generic-pool.js +48 -0
  9. package/packages/datadog-instrumentations/src/ioredis.js +52 -0
  10. package/packages/datadog-instrumentations/src/mongoose.js +30 -0
  11. package/packages/datadog-instrumentations/src/pino.js +105 -0
  12. package/packages/datadog-instrumentations/src/redis.js +118 -0
  13. package/packages/datadog-instrumentations/src/sharedb.js +78 -0
  14. package/packages/datadog-instrumentations/src/winston.js +57 -0
  15. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -2
  16. package/packages/datadog-plugin-bunyan/src/index.js +5 -22
  17. package/packages/datadog-plugin-cucumber/src/index.js +83 -128
  18. package/packages/datadog-plugin-fastify/src/find-my-way.js +0 -1
  19. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +8 -6
  20. package/packages/datadog-plugin-graphql/src/index.js +34 -28
  21. package/packages/datadog-plugin-grpc/src/client.js +20 -6
  22. package/packages/datadog-plugin-http2/src/server.js +2 -0
  23. package/packages/datadog-plugin-ioredis/src/index.js +5 -35
  24. package/packages/datadog-plugin-jest/src/jest-environment.js +26 -30
  25. package/packages/datadog-plugin-koa/src/index.js +6 -2
  26. package/packages/datadog-plugin-microgateway-core/src/index.js +1 -3
  27. package/packages/datadog-plugin-mocha/src/index.js +5 -3
  28. package/packages/datadog-plugin-mongodb-core/src/util.js +31 -7
  29. package/packages/datadog-plugin-next/src/index.js +9 -4
  30. package/packages/datadog-plugin-oracledb/src/index.js +10 -7
  31. package/packages/datadog-plugin-pino/src/index.js +5 -158
  32. package/packages/datadog-plugin-redis/src/index.js +96 -80
  33. package/packages/datadog-plugin-restify/src/index.js +18 -3
  34. package/packages/datadog-plugin-rhea/src/index.js +8 -5
  35. package/packages/datadog-plugin-router/src/index.js +23 -14
  36. package/packages/datadog-plugin-sharedb/src/index.js +47 -87
  37. package/packages/datadog-plugin-winston/src/index.js +5 -113
  38. package/packages/datadog-shimmer/src/shimmer.js +1 -1
  39. package/packages/dd-trace/lib/version.js +1 -1
  40. package/packages/dd-trace/src/appsec/index.js +2 -1
  41. package/packages/dd-trace/src/appsec/reporter.js +3 -2
  42. package/packages/dd-trace/src/config.js +7 -1
  43. package/packages/dd-trace/src/constants.js +1 -6
  44. package/packages/dd-trace/src/opentracing/propagation/text_map.js +0 -34
  45. package/packages/dd-trace/src/opentracing/tracer.js +1 -1
  46. package/packages/dd-trace/src/plugins/index.js +0 -2
  47. package/packages/dd-trace/src/plugins/log_plugin.js +49 -0
  48. package/packages/dd-trace/src/plugins/plugin.js +7 -0
  49. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  50. package/packages/dd-trace/src/plugins/util/web.js +102 -84
  51. package/packages/dd-trace/src/priority_sampler.js +1 -49
  52. package/packages/dd-trace/src/scope.js +47 -23
  53. package/packages/dd-trace/src/span_processor.js +22 -7
  54. package/packages/datadog-plugin-generic-pool/src/index.js +0 -52
  55. package/packages/datadog-plugin-mongoose/src/index.js +0 -51
@@ -7,6 +7,7 @@ const { incomingHttpRequestStart, incomingHttpRequestEnd } = require('./gateway/
7
7
  const Gateway = require('./gateway/engine')
8
8
  const addresses = require('./addresses')
9
9
  const Reporter = require('./reporter')
10
+ const web = require('../plugins/util/web')
10
11
 
11
12
  function enable (config) {
12
13
  try {
@@ -39,7 +40,7 @@ function enable (config) {
39
40
 
40
41
  function incomingHttpStartTranslator (data) {
41
42
  // TODO: get span from datadog-core storage instead
42
- const topSpan = data.req._datadog && data.req._datadog.span
43
+ const topSpan = web.root(data.req)
43
44
  if (topSpan) {
44
45
  topSpan.addTags({
45
46
  '_dd.appsec.enabled': 1,
@@ -2,6 +2,7 @@
2
2
 
3
3
  const addresses = require('./addresses')
4
4
  const Limiter = require('../rate_limiter')
5
+ const web = require('../plugins/util/web')
5
6
 
6
7
  // default limiter, configurable with setRateLimit()
7
8
  let limiter = new Limiter(100)
@@ -83,7 +84,7 @@ function formatHeaderName (name) {
83
84
 
84
85
  function reportAttack (attackData, store) {
85
86
  const req = store && store.get('req')
86
- const topSpan = req && req._datadog && req._datadog.span
87
+ const topSpan = web.root(req)
87
88
  if (!topSpan) return false
88
89
 
89
90
  const currentTags = topSpan.context()._tags
@@ -129,7 +130,7 @@ function reportAttack (attackData, store) {
129
130
  }
130
131
 
131
132
  function finishAttacks (req, context) {
132
- const topSpan = req && req._datadog && req._datadog.span
133
+ const topSpan = web.root(req)
133
134
  if (!topSpan || !context) return false
134
135
 
135
136
  const resolvedResponse = resolveHTTPResponse(context)
@@ -99,6 +99,11 @@ class Config {
99
99
  process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
100
100
  '0.4'
101
101
  )
102
+ const DD_TRACE_PARTIAL_FLUSH_MIN_SPANS = coalesce(
103
+ parseInt(options.flushMinSpans),
104
+ parseInt(process.env.DD_TRACE_PARTIAL_FLUSH_MIN_SPANS),
105
+ 1000
106
+ )
102
107
  const DD_TRACE_B3_ENABLED = coalesce(
103
108
  options.experimental && options.experimental.b3,
104
109
  process.env.DD_TRACE_EXPERIMENTAL_B3_ENABLED,
@@ -166,6 +171,7 @@ class Config {
166
171
  this.hostname = DD_AGENT_HOST || (this.url && this.url.hostname)
167
172
  this.port = String(DD_TRACE_AGENT_PORT || (this.url && this.url.port))
168
173
  this.flushInterval = coalesce(parseInt(options.flushInterval, 10), defaultFlushInterval)
174
+ this.flushMinSpans = DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
169
175
  this.sampleRate = coalesce(Math.min(Math.max(sampler.sampleRate, 0), 1), 1)
170
176
  this.logger = options.logger
171
177
  this.plugins = !!coalesce(options.plugins, true)
@@ -229,7 +235,7 @@ function getAgentUrl (url, options) {
229
235
  !process.env.DD_TRACE_AGENT_PORT &&
230
236
  fs.existsSync('/var/run/datadog/apm.socket')
231
237
  ) {
232
- return new URL('file:///var/run/datadog/apm.socket')
238
+ return new URL('unix:///var/run/datadog/apm.socket')
233
239
  }
234
240
  }
235
241
 
@@ -8,10 +8,5 @@ module.exports = {
8
8
  SAMPLING_RULE_DECISION: '_dd.rule_psr',
9
9
  SAMPLING_LIMIT_DECISION: '_dd.limit_psr',
10
10
  SAMPLING_AGENT_DECISION: '_dd.agent_psr',
11
- SAMPLING_MECHANISM_DEFAULT: 0,
12
- SAMPLING_MECHANISM_AGENT: 1,
13
- SAMPLING_MECHANISM_RULE: 3,
14
- SAMPLING_MECHANISM_MANUAL: 4,
15
- DATADOG_LAMBDA_EXTENSION_PATH: '/opt/extensions/datadog-agent',
16
- UPSTREAM_SERVICES_KEY: '_dd.p.upstream_services'
11
+ DATADOG_LAMBDA_EXTENSION_PATH: '/opt/extensions/datadog-agent'
17
12
  }
@@ -11,7 +11,6 @@ const traceKey = 'x-datadog-trace-id'
11
11
  const spanKey = 'x-datadog-parent-id'
12
12
  const originKey = 'x-datadog-origin'
13
13
  const samplingKey = 'x-datadog-sampling-priority'
14
- const tagsKey = 'x-datadog-tags'
15
14
  const baggagePrefix = 'ot-baggage-'
16
15
  const b3TraceKey = 'x-b3-traceid'
17
16
  const b3TraceExpr = /^([0-9a-f]{16}){1,2}$/i
@@ -41,7 +40,6 @@ class TextMapPropagator {
41
40
  this._injectSamplingPriority(spanContext, carrier)
42
41
  this._injectBaggageItems(spanContext, carrier)
43
42
  this._injectB3(spanContext, carrier)
44
- this._injectTags(spanContext, carrier)
45
43
 
46
44
  log.debug(() => `Inject into carrier: ${JSON.stringify(pick(carrier, logKeys))}.`)
47
45
  }
@@ -78,25 +76,6 @@ class TextMapPropagator {
78
76
  })
79
77
  }
80
78
 
81
- _injectTags (spanContext, carrier) {
82
- const trace = spanContext._trace
83
- const tags = []
84
-
85
- for (const key in trace.tags) {
86
- if (!key.startsWith('_dd.p.')) continue
87
-
88
- tags.push(`${key}=${trace.tags[key]}`)
89
- }
90
-
91
- const header = tags.join(',')
92
-
93
- if (header.length <= 512) {
94
- carrier[tagsKey] = header
95
- } else {
96
- trace.tags['_dd.propagation_error:max_size'] = 1
97
- }
98
- }
99
-
100
79
  _injectB3 (spanContext, carrier) {
101
80
  if (!this._config.experimental.b3) return
102
81
 
@@ -124,7 +103,6 @@ class TextMapPropagator {
124
103
  this._extractOrigin(carrier, spanContext)
125
104
  this._extractBaggageItems(carrier, spanContext)
126
105
  this._extractSamplingPriority(carrier, spanContext)
127
- this._extractTags(carrier, spanContext)
128
106
  }
129
107
 
130
108
  return spanContext
@@ -262,18 +240,6 @@ class TextMapPropagator {
262
240
  }
263
241
  }
264
242
 
265
- _extractTags (carrier, spanContext) {
266
- if (!carrier[tagsKey]) return
267
-
268
- const pairs = carrier[tagsKey].split(',')
269
-
270
- for (const pair of pairs) {
271
- const [key, value] = pair.split('=')
272
-
273
- spanContext._trace.tags[key] = value
274
- }
275
- }
276
-
277
243
  _getPriority (sampled, debug) {
278
244
  if (debug) {
279
245
  return USER_KEEP
@@ -35,7 +35,7 @@ class DatadogTracer extends Tracer {
35
35
  this._debug = config.debug
36
36
  this._prioritySampler = new PrioritySampler(config.env, config.experimental.sampler)
37
37
  this._exporter = new Exporter(config, this._prioritySampler)
38
- this._processor = new SpanProcessor(this._exporter, this._prioritySampler)
38
+ this._processor = new SpanProcessor(this._exporter, this._prioritySampler, config)
39
39
  this._url = this._exporter._url
40
40
  this._enableGetRumData = config.experimental.enableGetRumData
41
41
  this._propagators = {
@@ -15,7 +15,6 @@ module.exports = {
15
15
  'express': require('../../../datadog-plugin-express/src'),
16
16
  'fastify': require('../../../datadog-plugin-fastify/src'),
17
17
  'fs': require('../../../datadog-plugin-fs/src'),
18
- 'generic-pool': require('../../../datadog-plugin-generic-pool/src'),
19
18
  'google-cloud-pubsub': require('../../../datadog-plugin-google-cloud-pubsub/src'),
20
19
  'graphql': require('../../../datadog-plugin-graphql/src'),
21
20
  'grpc': require('../../../datadog-plugin-grpc/src'),
@@ -33,7 +32,6 @@ module.exports = {
33
32
  'mocha': require('../../../datadog-plugin-mocha/src'),
34
33
  'moleculer': require('../../../datadog-plugin-moleculer/src'),
35
34
  'mongodb-core': require('../../../datadog-plugin-mongodb-core/src'),
36
- 'mongoose': require('../../../datadog-plugin-mongoose/src'),
37
35
  'mysql': require('../../../datadog-plugin-mysql/src'),
38
36
  'mysql2': require('../../../datadog-plugin-mysql2/src'),
39
37
  'net': require('../../../datadog-plugin-net/src'),
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ const { LOG } = require('../../../../ext/formats')
4
+ const Plugin = require('./plugin')
5
+ const { storage } = require('../../../datadog-core')
6
+
7
+ const hasOwn = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
8
+
9
+ function messageProxy (message, holder) {
10
+ return new Proxy(message, {
11
+ get (target, p, receiver) {
12
+ switch (p) {
13
+ case Symbol.toStringTag:
14
+ return Object.prototype.toString.call(target).slice(8, -1)
15
+ case 'dd':
16
+ return holder.dd
17
+ default:
18
+ return Reflect.get(target, p, receiver)
19
+ }
20
+ },
21
+ ownKeys (target) {
22
+ const ownKeys = Reflect.ownKeys(target)
23
+ return hasOwn(target, 'dd') ? ownKeys : ['dd', ...ownKeys]
24
+ },
25
+ getOwnPropertyDescriptor (target, p) {
26
+ return Reflect.getOwnPropertyDescriptor(p === 'dd' ? holder : target, p)
27
+ }
28
+ })
29
+ }
30
+
31
+ module.exports = class LogPlugin extends Plugin {
32
+ constructor (...args) {
33
+ super(...args)
34
+ this.addSub(`apm:${this.constructor.name}:log`, (arg) => {
35
+ // TODO rather than checking this every time, setting it ought to enable/disable any plugin
36
+ // extending from this one
37
+ if (!this.tracer._logInjection) return
38
+
39
+ const store = storage.getStore()
40
+ const span = store && store.span
41
+
42
+ if (!span) return
43
+
44
+ const holder = {}
45
+ this.tracer.inject(span, LOG, holder)
46
+ arg.message = messageProxy(arg.message, holder)
47
+ })
48
+ }
49
+ }
@@ -42,6 +42,13 @@ module.exports = class Plugin {
42
42
  storage.enterWith({ ...store, span })
43
43
  }
44
44
 
45
+ /** Prevents creation of spans here and for all async descendants. */
46
+ skip () {
47
+ const store = storage.getStore()
48
+ this._storeStack.push(store)
49
+ storage.enterWith({ noop: true })
50
+ }
51
+
45
52
  exit () {
46
53
  storage.enterWith(this._storeStack.pop())
47
54
  }
@@ -37,7 +37,7 @@ function getGitMetadata (ciMetadata) {
37
37
  committerName,
38
38
  committerEmail,
39
39
  committerDate
40
- ] = sanitizedExec('git show -s --format=%an,%ae,%ad,%cn,%ce,%cd', { stdio: 'pipe' }).split(',')
40
+ ] = sanitizedExec('git show -s --format=%an,%ae,%aI,%cn,%ce,%cI', { stdio: 'pipe' }).split(',')
41
41
 
42
42
  return {
43
43
  [GIT_REPOSITORY_URL]:
@@ -29,6 +29,9 @@ const HTTP2_HEADER_AUTHORITY = ':authority'
29
29
  const HTTP2_HEADER_SCHEME = ':scheme'
30
30
  const HTTP2_HEADER_PATH = ':path'
31
31
 
32
+ const contexts = new WeakMap()
33
+ const ends = new WeakMap()
34
+
32
35
  const web = {
33
36
  // Ensure the configuration has the correct structure and defaults.
34
37
  normalizeConfig (config) {
@@ -51,8 +54,7 @@ const web = {
51
54
 
52
55
  // Start a span and activate a scope for a request.
53
56
  instrument (tracer, config, req, res, name, callback) {
54
- this.patch(req)
55
-
57
+ const context = this.patch(req)
56
58
  const span = startSpan(tracer, config, req, res, name)
57
59
 
58
60
  if (!config.filter(req.url)) {
@@ -65,11 +67,11 @@ const web = {
65
67
 
66
68
  analyticsSampler.sample(span, config.measured, true)
67
69
 
68
- if (!req._datadog.instrumented) {
69
- wrapEnd(req)
70
- wrapEvents(req)
70
+ if (!context.instrumented) {
71
+ wrapEnd(context)
72
+ wrapEvents(context)
71
73
 
72
- req._datadog.instrumented = true
74
+ context.instrumented = true
73
75
  }
74
76
 
75
77
  return callback && tracer.scope().activate(span, () => callback(span))
@@ -83,22 +85,23 @@ const web = {
83
85
  // Add a route segment that will be used for the resource name.
84
86
  enterRoute (req, path) {
85
87
  if (typeof path === 'string') {
86
- req._datadog.paths.push(path)
88
+ contexts.get(req).paths.push(path)
87
89
  }
88
90
  },
89
91
 
90
92
  // Remove the current route segment.
91
93
  exitRoute (req) {
92
- req._datadog.paths.pop()
94
+ contexts.get(req).paths.pop()
93
95
  },
94
96
 
95
97
  // Start a new middleware span and activate a new scope with the span.
96
98
  wrapMiddleware (req, middleware, name, fn) {
97
99
  if (!this.active(req)) return fn()
98
100
 
99
- const tracer = req._datadog.tracer
101
+ const context = contexts.get(req)
102
+ const tracer = context.tracer
100
103
  const childOf = this.active(req)
101
- const config = req._datadog.config
104
+ const config = context.config
102
105
 
103
106
  if (config.middleware === false) return this.bindAndWrapMiddlewareErrors(fn, req, tracer, childOf)
104
107
 
@@ -110,7 +113,7 @@ const web = {
110
113
  [RESOURCE_NAME]: middleware._name || middleware.name || '<anonymous>'
111
114
  })
112
115
 
113
- req._datadog.middleware.push(span)
116
+ context.middleware.push(span)
114
117
 
115
118
  return tracer.scope().activate(span, fn)
116
119
  },
@@ -129,7 +132,8 @@ const web = {
129
132
  finish (req, error) {
130
133
  if (!this.active(req)) return
131
134
 
132
- const span = req._datadog.middleware.pop()
135
+ const context = contexts.get(req)
136
+ const span = context.middleware.pop()
133
137
 
134
138
  if (span) {
135
139
  if (error) {
@@ -146,38 +150,50 @@ const web = {
146
150
 
147
151
  // Register a callback to run before res.end() is called.
148
152
  beforeEnd (req, callback) {
149
- req._datadog.beforeEnd.push(callback)
153
+ contexts.get(req).beforeEnd.push(callback)
150
154
  },
151
155
 
152
156
  // Prepare the request for instrumentation.
153
157
  patch (req) {
154
- if (req._datadog) return
158
+ let context = contexts.get(req)
159
+
160
+ if (context) return context
155
161
 
156
- if (req.stream && req.stream._datadog) {
157
- req._datadog = req.stream._datadog
158
- return
162
+ context = req.stream && contexts.get(req.stream)
163
+
164
+ if (context) {
165
+ contexts.set(req, context)
166
+ return context
159
167
  }
160
168
 
161
- req._datadog = {
169
+ context = {
170
+ req,
162
171
  span: null,
163
172
  paths: [],
164
173
  middleware: [],
165
174
  beforeEnd: [],
166
175
  config: {}
167
176
  }
177
+
178
+ contexts.set(req, context)
179
+
180
+ return context
168
181
  },
169
182
 
170
183
  // Return the request root span.
171
184
  root (req) {
172
- return req._datadog ? req._datadog.span : null
185
+ const context = contexts.get(req)
186
+ return context ? context.span : null
173
187
  },
174
188
 
175
189
  // Return the active span.
176
190
  active (req) {
177
- if (!req._datadog) return null
178
- if (req._datadog.middleware.length === 0) return req._datadog.span || null
191
+ const context = contexts.get(req)
179
192
 
180
- return req._datadog.middleware.slice(-1)[0]
193
+ if (!context) return null
194
+ if (context.middleware.length === 0) return context.span || null
195
+
196
+ return context.middleware.slice(-1)[0]
181
197
  },
182
198
 
183
199
  // Extract the parent span from the headers and start a new span as its child
@@ -190,10 +206,11 @@ const web = {
190
206
 
191
207
  // Validate a request's status code and then add error tags if necessary
192
208
  addStatusError (req, statusCode) {
193
- const span = req._datadog.span
194
- const error = req._datadog.error
209
+ const context = contexts.get(req)
210
+ const span = context.span
211
+ const error = context.error
195
212
 
196
- if (!req._datadog.config.validateStatus(statusCode)) {
213
+ if (!context.config.validateStatus(statusCode)) {
197
214
  span.setTag(ERROR, error || true)
198
215
  }
199
216
  },
@@ -201,94 +218,95 @@ const web = {
201
218
  // Add an error to the request
202
219
  addError (req, error) {
203
220
  if (error instanceof Error) {
204
- req._datadog.error = req._datadog.error || error
221
+ const context = contexts.get(req)
222
+ context.error = context.error || error
205
223
  }
206
224
  }
207
225
  }
208
226
 
209
227
  function startSpan (tracer, config, req, res, name) {
210
- req._datadog.config = config
228
+ const context = contexts.get(req)
229
+
230
+ context.config = config
211
231
 
212
232
  let span
213
233
 
214
- if (req._datadog.span) {
215
- req._datadog.span.context()._name = name
216
- span = req._datadog.span
234
+ if (context.span) {
235
+ context.span.context()._name = name
236
+ span = context.span
217
237
  } else {
218
238
  span = web.startChildSpan(tracer, name, req.headers)
219
239
  }
220
240
 
221
- configureDatadogObject(tracer, span, req, res)
241
+ context.tracer = tracer
242
+ context.span = span
243
+ context.res = res
222
244
 
223
245
  return span
224
246
  }
225
247
 
226
- function configureDatadogObject (tracer, span, req, res) {
227
- const ddObj = req._datadog
228
- ddObj.tracer = tracer
229
- ddObj.span = span
230
- ddObj.res = res
231
- }
248
+ function finish (context) {
249
+ const { req, res } = context
232
250
 
233
- function finish (req, res) {
234
- if (req._datadog.finished && !req.stream) return
251
+ if (context.finished && !req.stream) return
235
252
 
236
- addRequestTags(req)
237
- addResponseTags(req)
253
+ addRequestTags(context)
254
+ addResponseTags(context)
238
255
 
239
- req._datadog.config.hooks.request(req._datadog.span, req, res)
240
- addResourceTag(req)
256
+ context.config.hooks.request(context.span, req, res)
257
+ addResourceTag(context)
241
258
 
242
- req._datadog.span.finish()
243
- req._datadog.finished = true
259
+ context.span.finish()
260
+ context.finished = true
244
261
  }
245
262
 
246
- function finishMiddleware (req, res) {
247
- if (req._datadog.finished) return
263
+ function finishMiddleware (context) {
264
+ if (context.finished) return
248
265
 
249
266
  let span
250
267
 
251
- while ((span = req._datadog.middleware.pop())) {
268
+ while ((span = context.middleware.pop())) {
252
269
  span.finish()
253
270
  }
254
271
  }
255
272
 
256
- function wrapEnd (req) {
257
- const scope = req._datadog.tracer.scope()
258
- const res = req._datadog.res
273
+ function wrapEnd (context) {
274
+ const scope = context.tracer.scope()
275
+ const req = context.req
276
+ const res = context.res
259
277
  const end = res.end
260
278
 
261
- res.writeHead = wrapWriteHead(req)
279
+ res.writeHead = wrapWriteHead(context)
262
280
 
263
- res._datadog_end = function () {
264
- for (const beforeEnd of req._datadog.beforeEnd) {
281
+ ends.set(res, function () {
282
+ for (const beforeEnd of context.beforeEnd) {
265
283
  beforeEnd()
266
284
  }
267
285
 
268
- finishMiddleware(req, res)
286
+ finishMiddleware(context)
269
287
 
270
288
  if (incomingHttpRequestEnd.hasSubscribers) incomingHttpRequestEnd.publish({ req, res })
271
289
 
272
290
  const returnValue = end.apply(res, arguments)
273
291
 
274
- finish(req, res)
292
+ finish(context)
275
293
 
276
294
  return returnValue
277
- }
295
+ })
278
296
 
279
297
  Object.defineProperty(res, 'end', {
280
298
  configurable: true,
281
299
  get () {
282
- return this._datadog_end
300
+ return ends.get(this)
283
301
  },
284
302
  set (value) {
285
- this._datadog_end = scope.bind(value, req._datadog.span)
303
+ ends.set(this, scope.bind(value, context.span))
286
304
  }
287
305
  })
288
306
  }
289
307
 
290
- function wrapWriteHead (req) {
291
- const res = req._datadog.res
308
+ function wrapWriteHead (context) {
309
+ const { req, res } = context
292
310
  const writeHead = res.writeHead
293
311
 
294
312
  return function (statusCode, statusMessage, headers) {
@@ -296,15 +314,14 @@ function wrapWriteHead (req) {
296
314
  headers = Object.assign(res.getHeaders(), headers)
297
315
 
298
316
  if (req.method.toLowerCase() === 'options' && isOriginAllowed(req, headers)) {
299
- addAllowHeaders(req, headers)
317
+ addAllowHeaders(req, res, headers)
300
318
  }
301
319
 
302
320
  return writeHead.apply(this, arguments)
303
321
  }
304
322
  }
305
323
 
306
- function addAllowHeaders (req, headers) {
307
- const res = req._datadog.res
324
+ function addAllowHeaders (req, res, headers) {
308
325
  const allowHeaders = splitHeader(headers['access-control-allow-headers'])
309
326
  const requestHeaders = splitHeader(req.headers['access-control-request-headers'])
310
327
  const contextHeaders = [
@@ -337,22 +354,24 @@ function splitHeader (str) {
337
354
  return typeof str === 'string' ? str.split(/\s*,\s*/) : []
338
355
  }
339
356
 
340
- function wrapEvents (req) {
341
- const scope = req._datadog.tracer.scope()
342
- const res = req._datadog.res
357
+ function wrapEvents (context) {
358
+ const scope = context.tracer.scope()
359
+ const res = context.res
343
360
 
344
- scope.bind(res, req._datadog.span)
361
+ scope.bind(res, context.span)
345
362
  }
346
363
 
347
364
  function reactivate (req, fn) {
348
- return req._datadog
349
- ? req._datadog.tracer.scope().activate(req._datadog.span, fn)
365
+ const context = contexts.get(req)
366
+
367
+ return context
368
+ ? context.tracer.scope().activate(context.span, fn)
350
369
  : fn()
351
370
  }
352
371
 
353
- function addRequestTags (req) {
372
+ function addRequestTags (context) {
373
+ const { req, span } = context
354
374
  const url = extractURL(req)
355
- const span = req._datadog.span
356
375
 
357
376
  span.addTags({
358
377
  [HTTP_URL]: url.split('?')[0],
@@ -361,15 +380,14 @@ function addRequestTags (req) {
361
380
  [SPAN_TYPE]: WEB
362
381
  })
363
382
 
364
- addHeaders(req)
383
+ addHeaders(context)
365
384
  }
366
385
 
367
- function addResponseTags (req) {
368
- const span = req._datadog.span
369
- const res = req._datadog.res
386
+ function addResponseTags (context) {
387
+ const { req, res, paths, span } = context
370
388
 
371
- if (req._datadog.paths.length > 0) {
372
- span.setTag(HTTP_ROUTE, req._datadog.paths.join(''))
389
+ if (paths.length > 0) {
390
+ span.setTag(HTTP_ROUTE, paths.join(''))
373
391
  }
374
392
 
375
393
  span.addTags({
@@ -379,8 +397,8 @@ function addResponseTags (req) {
379
397
  web.addStatusError(req, res.statusCode)
380
398
  }
381
399
 
382
- function addResourceTag (req) {
383
- const span = req._datadog.span
400
+ function addResourceTag (context) {
401
+ const { req, span } = context
384
402
  const tags = span.context()._tags
385
403
 
386
404
  if (tags['resource.name']) return
@@ -392,12 +410,12 @@ function addResourceTag (req) {
392
410
  span.setTag(RESOURCE_NAME, resource)
393
411
  }
394
412
 
395
- function addHeaders (req) {
396
- const span = req._datadog.span
413
+ function addHeaders (context) {
414
+ const { req, res, config, span } = context
397
415
 
398
- req._datadog.config.headers.forEach(key => {
416
+ config.headers.forEach(key => {
399
417
  const reqHeader = req.headers[key]
400
- const resHeader = req._datadog.res.getHeader(key)
418
+ const resHeader = res.getHeader(key)
401
419
 
402
420
  if (reqHeader) {
403
421
  span.setTag(`${HTTP_REQUEST_HEADERS}.${key}`, reqHeader)