dd-trace 4.8.0 → 4.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "4.8.0",
3
+ "version": "4.8.1",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -177,7 +177,6 @@ addHook({ name: '@aws-sdk/smithy-client', versions: ['>=3'] }, smithy => {
177
177
  })
178
178
 
179
179
  addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
180
- shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
181
180
  shimmer.wrap(AWS.config, 'setPromisesDependency', setPromisesDependency => {
182
181
  return function wrappedSetPromisesDependency (dep) {
183
182
  const result = setPromisesDependency.apply(this, arguments)
@@ -188,9 +187,14 @@ addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
188
187
  return AWS
189
188
  })
190
189
 
190
+ addHook({ name: 'aws-sdk', file: 'lib/core.js', versions: ['>=2.3.0'] }, AWS => {
191
+ shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
192
+ return AWS
193
+ })
194
+
191
195
  // <2.1.35 has breaking changes for instrumentation
192
196
  // https://github.com/aws/aws-sdk-js/pull/629
193
- addHook({ name: 'aws-sdk', versions: ['>=2.1.35'] }, AWS => {
197
+ addHook({ name: 'aws-sdk', file: 'lib/core.js', versions: ['>=2.1.35'] }, AWS => {
194
198
  shimmer.wrap(AWS.Request.prototype, 'send', wrapRequest)
195
199
  return AWS
196
200
  })
@@ -17,29 +17,32 @@ function wrapFetch (fetch, Request) {
17
17
  const headers = req.headers
18
18
  const message = { req, headers }
19
19
 
20
- startChannel.publish(message)
21
-
22
- // Request object is read-only so we need new objects to change headers.
23
- arguments[0] = message.req
24
- arguments[1] = { headers: message.headers }
25
-
26
- return fetch.apply(this, arguments)
27
- .then(
28
- res => {
29
- finishChannel.publish({ req, res })
30
-
31
- return res
32
- },
33
- err => {
34
- if (err.name !== 'AbortError') {
35
- errorChannel.publish(err)
36
- }
20
+ return startChannel.runStores(message, () => {
21
+ // Request object is read-only so we need new objects to change headers.
22
+ arguments[0] = message.req
23
+ arguments[1] = { headers: message.headers }
24
+
25
+ return fetch.apply(this, arguments)
26
+ .then(
27
+ res => {
28
+ message.res = res
29
+
30
+ finishChannel.publish(message)
37
31
 
38
- finishChannel.publish({ req })
32
+ return res
33
+ },
34
+ err => {
35
+ if (err.name !== 'AbortError') {
36
+ message.error = err
37
+ errorChannel.publish(message)
38
+ }
39
39
 
40
- throw err
41
- }
42
- )
40
+ finishChannel.publish(message)
41
+
42
+ throw err
43
+ }
44
+ )
45
+ })
43
46
  }
44
47
  }
45
48
 
@@ -10,6 +10,7 @@ module.exports = {
10
10
  '@grpc/grpc-js': () => require('../grpc'),
11
11
  '@hapi/hapi': () => require('../hapi'),
12
12
  '@jest/core': () => require('../jest'),
13
+ '@jest/transform': () => require('../jest'),
13
14
  '@jest/reporters': () => require('../jest'),
14
15
  '@koa/router': () => require('../koa'),
15
16
  '@node-redis/client': () => require('../redis'),
@@ -3,18 +3,16 @@
3
3
  /* eslint-disable no-fallthrough */
4
4
 
5
5
  const url = require('url')
6
- const {
7
- channel,
8
- addHook,
9
- AsyncResource
10
- } = require('../helpers/instrument')
6
+ const { channel, addHook } = require('../helpers/instrument')
11
7
  const shimmer = require('../../../datadog-shimmer')
12
8
 
13
9
  const log = require('../../../dd-trace/src/log')
14
10
 
15
- const startClientCh = channel('apm:http:client:request:start')
16
- const finishClientCh = channel('apm:http:client:request:finish')
17
- const errorClientCh = channel('apm:http:client:request:error')
11
+ const startChannel = channel('apm:http:client:request:start')
12
+ const finishChannel = channel('apm:http:client:request:finish')
13
+ const endChannel = channel('apm:http:client:request:end')
14
+ const asyncStartChannel = channel('apm:http:client:request:asyncStart')
15
+ const errorChannel = channel('apm:http:client:request:error')
18
16
 
19
17
  addHook({ name: 'https' }, hookFn)
20
18
 
@@ -32,7 +30,7 @@ function patch (http, methodName) {
32
30
 
33
31
  function instrumentRequest (request) {
34
32
  return function () {
35
- if (!startClientCh.hasSubscribers) {
33
+ if (!startChannel.hasSubscribers) {
36
34
  return request.apply(this, arguments)
37
35
  }
38
36
 
@@ -45,57 +43,68 @@ function patch (http, methodName) {
45
43
  return request.apply(this, arguments)
46
44
  }
47
45
 
48
- const callbackResource = new AsyncResource('bound-anonymous-fn')
49
- const asyncResource = new AsyncResource('bound-anonymous-fn')
50
-
51
- return asyncResource.runInAsyncScope(() => {
52
- startClientCh.publish({ args, http })
46
+ const ctx = { args, http }
53
47
 
48
+ return startChannel.runStores(ctx, () => {
54
49
  let finished = false
55
50
  let callback = args.callback
56
51
 
57
52
  if (callback) {
58
- callback = callbackResource.bind(callback)
53
+ callback = function () {
54
+ return asyncStartChannel.runStores(ctx, () => {
55
+ return args.callback.apply(this, arguments)
56
+ })
57
+ }
59
58
  }
60
59
 
61
60
  const options = args.options
62
- const req = request.call(this, options, callback)
63
- const emit = req.emit
64
-
65
- const finish = (req, res) => {
61
+ const finish = () => {
66
62
  if (!finished) {
67
63
  finished = true
68
- finishClientCh.publish({ req, res })
64
+ finishChannel.publish(ctx)
69
65
  }
70
66
  }
71
67
 
72
- req.emit = function (eventName, arg) {
73
- asyncResource.runInAsyncScope(() => {
68
+ try {
69
+ const req = request.call(this, options, callback)
70
+ const emit = req.emit
71
+
72
+ ctx.req = req
73
+
74
+ req.emit = function (eventName, arg) {
74
75
  switch (eventName) {
75
76
  case 'response': {
76
77
  const res = arg
77
- const listener = asyncResource.bind(() => finish(req, res))
78
- res.on('end', listener)
79
- res.on('error', listener)
78
+ ctx.res = res
79
+ res.on('end', finish)
80
+ res.on('error', finish)
80
81
  break
81
82
  }
82
83
  case 'connect':
83
84
  case 'upgrade':
84
- finish(req, arg)
85
+ ctx.res = arg
86
+ finish()
85
87
  break
86
88
  case 'error':
87
89
  case 'timeout':
88
- errorClientCh.publish(arg)
90
+ ctx.error = arg
91
+ errorChannel.publish(ctx)
89
92
  case 'abort': // deprecated and replaced by `close` in node 17
90
93
  case 'close':
91
- finish(req)
94
+ finish()
92
95
  }
93
- })
94
96
 
95
- return emit.apply(this, arguments)
96
- }
97
+ return emit.apply(this, arguments)
98
+ }
97
99
 
98
- return req
100
+ return req
101
+ } catch (e) {
102
+ ctx.error = e
103
+ errorChannel.publish(ctx)
104
+ throw e
105
+ } finally {
106
+ endChannel.publish(ctx)
107
+ }
99
108
  })
100
109
  }
101
110
  }
@@ -42,6 +42,7 @@ function createWrapRequest (authority, options) {
42
42
  } catch (e) {
43
43
  ctx.error = e
44
44
  errorChannel.publish(ctx)
45
+ throw e
45
46
  } finally {
46
47
  endChannel.publish(ctx)
47
48
  }
@@ -410,6 +410,32 @@ function jestConfigSyncWrapper (jestConfig) {
410
410
  return jestConfig
411
411
  }
412
412
 
413
+ addHook({
414
+ name: '@jest/transform',
415
+ versions: ['>=24.8.0'],
416
+ file: 'build/ScriptTransformer.js'
417
+ }, transformPackage => {
418
+ const originalCreateScriptTransformer = transformPackage.createScriptTransformer
419
+
420
+ transformPackage.createScriptTransformer = async function (config) {
421
+ const { testEnvironmentOptions, ...restOfConfig } = config
422
+ const {
423
+ _ddTestModuleId,
424
+ _ddTestSessionId,
425
+ _ddTestCommand,
426
+ ...restOfTestEnvironmentOptions
427
+ } = testEnvironmentOptions
428
+
429
+ restOfConfig.testEnvironmentOptions = restOfTestEnvironmentOptions
430
+
431
+ arguments[0] = restOfConfig
432
+
433
+ return originalCreateScriptTransformer.apply(this, arguments)
434
+ }
435
+
436
+ return transformPackage
437
+ })
438
+
413
439
  /**
414
440
  * Hook to remove the test paths (test suite) that are part of `skippableSuites`
415
441
  */
@@ -1,35 +1,29 @@
1
1
  'use strict'
2
2
 
3
3
  const HttpClientPlugin = require('../../datadog-plugin-http/src/client')
4
- const { HTTP_HEADERS } = require('../../../ext/formats')
5
4
 
6
5
  class FetchPlugin extends HttpClientPlugin {
7
6
  static get id () { return 'fetch' }
7
+ static get prefix () { return `apm:fetch:request` }
8
8
 
9
9
  addTraceSub (eventName, handler) {
10
10
  this.addSub(`apm:${this.constructor.id}:${this.operation}:${eventName}`, handler)
11
11
  }
12
12
 
13
- start (message) {
13
+ bindStart (message) {
14
14
  const req = message.req
15
15
  const options = new URL(req.url)
16
16
  const headers = options.headers = Object.fromEntries(req.headers.entries())
17
17
 
18
- const args = { options }
18
+ options.method = req.method
19
19
 
20
- super.start({ args })
20
+ message.args = { options }
21
21
 
22
- message.req = new globalThis.Request(req, { headers })
23
- }
22
+ const store = super.bindStart(message)
24
23
 
25
- _inject (span, headers) {
26
- const carrier = {}
27
-
28
- this.tracer.inject(span, HTTP_HEADERS, carrier)
24
+ message.req = new globalThis.Request(req, { headers })
29
25
 
30
- for (const name in carrier) {
31
- headers.append(name, carrier[name])
32
- }
26
+ return store
33
27
  }
34
28
  }
35
29
 
@@ -16,15 +16,11 @@ const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
16
16
  const HTTP_RESPONSE_HEADERS = tags.HTTP_RESPONSE_HEADERS
17
17
 
18
18
  class HttpClientPlugin extends ClientPlugin {
19
- static get id () {
20
- return 'http'
21
- }
22
-
23
- addTraceSub (eventName, handler) {
24
- this.addSub(`apm:${this.constructor.id}:client:${this.operation}:${eventName}`, handler)
25
- }
19
+ static get id () { return 'http' }
20
+ static get prefix () { return `apm:http:client:request` }
26
21
 
27
- start ({ args, http = {} }) {
22
+ bindStart (message) {
23
+ const { args, http = {} } = message
28
24
  const store = storage.getStore()
29
25
  const options = args.options
30
26
  const agent = options.agent || options._defaultAgent || http.globalAgent || {}
@@ -55,7 +51,7 @@ class HttpClientPlugin extends ClientPlugin {
55
51
  metrics: {
56
52
  [CLIENT_PORT_KEY]: parseInt(options.port)
57
53
  }
58
- })
54
+ }, false)
59
55
 
60
56
  // TODO: Figure out a better way to do this for any span.
61
57
  if (!allowed) {
@@ -67,11 +63,19 @@ class HttpClientPlugin extends ClientPlugin {
67
63
  }
68
64
 
69
65
  analyticsSampler.sample(span, this.config.measured)
70
- this.enter(span, store)
66
+
67
+ message.span = span
68
+ message.parentStore = store
69
+ message.currentStore = { ...store, span }
70
+
71
+ return message.currentStore
71
72
  }
72
73
 
73
- finish ({ req, res }) {
74
- const span = storage.getStore().span
74
+ bindAsyncStart ({ parentStore }) {
75
+ return parentStore
76
+ }
77
+
78
+ finish ({ req, res, span }) {
75
79
  if (res) {
76
80
  const status = res.status || res.statusCode
77
81
 
@@ -87,17 +91,18 @@ class HttpClientPlugin extends ClientPlugin {
87
91
  addRequestHeaders(req, span, this.config)
88
92
 
89
93
  this.config.hooks.request(span, req, res)
90
- super.finish()
91
- }
92
94
 
93
- error (err) {
94
- const span = storage.getStore().span
95
+ this.tagPeerService(span)
96
+
97
+ span.finish()
98
+ }
95
99
 
96
- if (err) {
100
+ error ({ span, error }) {
101
+ if (error) {
97
102
  span.addTags({
98
- [ERROR_TYPE]: err.name,
99
- [ERROR_MESSAGE]: err.message || err.code,
100
- [ERROR_STACK]: err.stack
103
+ [ERROR_TYPE]: error.name,
104
+ [ERROR_MESSAGE]: error.message || error.code,
105
+ [ERROR_STACK]: error.stack
101
106
  })
102
107
  } else {
103
108
  span.setTag('error', 1)
@@ -10,6 +10,7 @@ module.exports = {
10
10
  get '@grpc/grpc-js' () { return require('../../../datadog-plugin-grpc/src') },
11
11
  get '@hapi/hapi' () { return require('../../../datadog-plugin-hapi/src') },
12
12
  get '@jest/core' () { return require('../../../datadog-plugin-jest/src') },
13
+ get '@jest/transform' () { return require('../../../datadog-plugin-jest/src') },
13
14
  get '@koa/router' () { return require('../../../datadog-plugin-koa/src') },
14
15
  get '@node-redis/client' () { return require('../../../datadog-plugin-redis/src') },
15
16
  get '@opensearch-project/opensearch' () { return require('../../../datadog-plugin-opensearch/src') },
@@ -64,7 +64,7 @@ if (!Channel.prototype.runStores) {
64
64
  this._stores.set(store, transform)
65
65
  }
66
66
 
67
- Channel.prototype.unbindStore = ActiveChannelPrototype.runStores = function (store) {
67
+ Channel.prototype.unbindStore = ActiveChannelPrototype.unbindStore = function (store) {
68
68
  if (!this._stores) return
69
69
  this._stores.delete(store)
70
70
  }