dd-trace 4.5.0 → 4.7.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.
Files changed (62) hide show
  1. package/package.json +3 -3
  2. package/packages/datadog-instrumentations/src/cucumber.js +5 -2
  3. package/packages/datadog-instrumentations/src/grpc/client.js +44 -42
  4. package/packages/datadog-instrumentations/src/grpc/server.js +69 -60
  5. package/packages/datadog-instrumentations/src/http2/client.js +25 -26
  6. package/packages/datadog-instrumentations/src/jest.js +3 -1
  7. package/packages/datadog-instrumentations/src/kafkajs.js +11 -2
  8. package/packages/datadog-instrumentations/src/mocha.js +5 -3
  9. package/packages/datadog-instrumentations/src/redis.js +48 -5
  10. package/packages/datadog-plugin-cypress/src/plugin.js +4 -2
  11. package/packages/datadog-plugin-grpc/src/client.js +29 -11
  12. package/packages/datadog-plugin-grpc/src/server.js +22 -6
  13. package/packages/datadog-plugin-http2/src/client.js +46 -29
  14. package/packages/datadog-plugin-kafkajs/src/producer.js +6 -1
  15. package/packages/datadog-plugin-openai/src/services.js +14 -10
  16. package/packages/datadog-plugin-router/src/index.js +1 -1
  17. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +3 -0
  18. package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +7 -1
  19. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +3 -0
  20. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +19 -15
  21. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +5 -2
  22. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +2 -0
  23. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +3 -1
  24. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +18 -19
  25. package/packages/dd-trace/src/appsec/iast/analyzers/weak-cipher-analyzer.js +3 -0
  26. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +3 -0
  27. package/packages/dd-trace/src/appsec/iast/iast-log.js +1 -1
  28. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +205 -0
  29. package/packages/dd-trace/src/appsec/iast/index.js +6 -5
  30. package/packages/dd-trace/src/appsec/iast/tags.js +2 -1
  31. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +6 -6
  32. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +3 -3
  33. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +23 -4
  34. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +32 -16
  35. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +33 -0
  36. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +23 -16
  37. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +76 -37
  38. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +101 -0
  39. package/packages/dd-trace/src/appsec/iast/telemetry/index.js +45 -0
  40. package/packages/dd-trace/src/appsec/iast/telemetry/{logs.js → log/index.js} +5 -5
  41. package/packages/dd-trace/src/appsec/iast/telemetry/{log_collector.js → log/log-collector.js} +1 -1
  42. package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +76 -0
  43. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +53 -0
  44. package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +42 -0
  45. package/packages/dd-trace/src/config.js +21 -2
  46. package/packages/dd-trace/src/constants.js +1 -0
  47. package/packages/dd-trace/src/dogstatsd.js +14 -1
  48. package/packages/dd-trace/src/metrics.js +2 -2
  49. package/packages/dd-trace/src/opentracing/tracer.js +1 -0
  50. package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
  51. package/packages/dd-trace/src/plugins/outbound.js +29 -12
  52. package/packages/dd-trace/src/plugins/plugin.js +28 -0
  53. package/packages/dd-trace/src/plugins/tracing.js +33 -16
  54. package/packages/dd-trace/src/plugins/util/ci.js +1 -1
  55. package/packages/dd-trace/src/plugins/util/test.js +55 -11
  56. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -22
  57. package/packages/dd-trace/src/profiling/config.js +0 -3
  58. package/packages/dd-trace/src/profiling/index.js +0 -2
  59. package/packages/dd-trace/src/profiling/profilers/wall.js +23 -11
  60. package/packages/diagnostics_channel/src/index.js +64 -0
  61. package/packages/dd-trace/src/profiling/profilers/cpu.js +0 -126
  62. /package/packages/dd-trace/src/appsec/iast/taint-tracking/{origin-types.js → source-types.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -70,7 +70,7 @@
70
70
  "@datadog/native-iast-rewriter": "2.0.1",
71
71
  "@datadog/native-iast-taint-tracking": "^1.5.0",
72
72
  "@datadog/native-metrics": "^2.0.0",
73
- "@datadog/pprof": "2.2.3",
73
+ "@datadog/pprof": "3.0.0",
74
74
  "@datadog/sketches-js": "^2.1.0",
75
75
  "@opentelemetry/api": "^1.0.0",
76
76
  "@opentelemetry/core": "^1.14.0",
@@ -94,7 +94,7 @@
94
94
  "node-abort-controller": "^3.0.1",
95
95
  "opentracing": ">=0.12.1",
96
96
  "path-to-regexp": "^0.1.2",
97
- "protobufjs": "^7.1.2",
97
+ "protobufjs": "^7.2.4",
98
98
  "retry": "^0.10.1",
99
99
  "semver": "^7.3.8"
100
100
  },
@@ -37,6 +37,7 @@ const patched = new WeakSet()
37
37
 
38
38
  let pickleByFile = {}
39
39
  const pickleResultByFile = {}
40
+ let isSuitesSkipped = false
40
41
 
41
42
  function getSuiteStatusFromTestStatuses (testStatuses) {
42
43
  if (testStatuses.some(status => status === 'fail')) {
@@ -264,7 +265,9 @@ addHook({
264
265
  const { err, skippableSuites } = await skippableSuitesPromise
265
266
 
266
267
  if (!err) {
267
- this.pickleIds = getPicklesToRun(this, skippableSuites)
268
+ const newPickleIds = getPicklesToRun(this, skippableSuites)
269
+ isSuitesSkipped = newPickleIds.length !== this.pickleIds.length
270
+ this.pickleIds = newPickleIds
268
271
  }
269
272
 
270
273
  pickleByFile = getPickleByFile(this)
@@ -292,7 +295,7 @@ addHook({
292
295
  asyncResource.runInAsyncScope(() => {
293
296
  sessionFinishCh.publish({
294
297
  status: success ? 'pass' : 'fail',
295
- isSuitesSkipped: skippableSuites ? !!skippableSuites.length : false,
298
+ isSuitesSkipped,
296
299
  testCodeCoverageLinesTotal
297
300
  })
298
301
  })
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const types = require('./types')
4
- const { addHook, channel, AsyncResource } = require('../helpers/instrument')
4
+ const { addHook, channel } = require('../helpers/instrument')
5
5
  const shimmer = require('../../../datadog-shimmer')
6
6
 
7
7
  const nodeMajor = parseInt(process.versions.node.split('.')[0])
@@ -10,8 +10,10 @@ const patched = new WeakSet()
10
10
  const instances = new WeakMap()
11
11
 
12
12
  const startChannel = channel('apm:grpc:client:request:start')
13
+ const asyncStartChannel = channel('apm:grpc:client:request:asyncStart')
13
14
  const errorChannel = channel('apm:grpc:client:request:error')
14
15
  const finishChannel = channel('apm:grpc:client:request:finish')
16
+ const emitChannel = channel('apm:grpc:client:request:emit')
15
17
 
16
18
  function createWrapMakeRequest (type) {
17
19
  return function wrapMakeRequest (makeRequest) {
@@ -101,45 +103,39 @@ function wrapMethod (method, path, type) {
101
103
  return wrapped
102
104
  }
103
105
 
104
- function wrapCallback (requestResource, parentResource, callback) {
106
+ function wrapCallback (ctx, callback = () => { }) {
105
107
  return function (err) {
106
108
  if (err) {
107
- requestResource.runInAsyncScope(() => {
108
- errorChannel.publish(err)
109
- })
109
+ ctx.error = err
110
+ errorChannel.publish(ctx)
110
111
  }
111
112
 
112
- if (callback) {
113
- return parentResource.runInAsyncScope(() => {
114
- return callback.apply(this, arguments)
115
- })
116
- }
113
+ return asyncStartChannel.runStores(ctx, () => {
114
+ return callback.apply(this, arguments)
115
+ // No async end channel needed
116
+ })
117
117
  }
118
118
  }
119
119
 
120
- function wrapStream (call, requestResource, parentResource) {
121
- if (!call || typeof call.emit !== 'function') return
122
-
123
- shimmer.wrap(call, 'emit', emit => {
124
- return function (eventName, ...args) {
125
- requestResource.runInAsyncScope(() => {
126
- switch (eventName) {
127
- case 'error':
128
- errorChannel.publish(args[0])
129
-
130
- break
131
- case 'status':
132
- finishChannel.publish(args[0])
133
-
134
- break
135
- }
136
- })
120
+ function createWrapEmit (ctx) {
121
+ return function wrapEmit (emit) {
122
+ return function (event, arg1) {
123
+ switch (event) {
124
+ case 'error':
125
+ ctx.error = arg1
126
+ errorChannel.publish(ctx)
127
+ break
128
+ case 'status':
129
+ ctx.result = arg1
130
+ finishChannel.publish(ctx)
131
+ break
132
+ }
137
133
 
138
- return parentResource.runInAsyncScope(() => {
134
+ return emitChannel.runStores(ctx, () => {
139
135
  return emit.apply(this, arguments)
140
136
  })
141
137
  }
142
- })
138
+ }
143
139
  }
144
140
 
145
141
  function callMethod (client, method, args, path, metadata, type) {
@@ -147,25 +143,31 @@ function callMethod (client, method, args, path, metadata, type) {
147
143
 
148
144
  const length = args.length
149
145
  const callback = args[length - 1]
150
- const parentResource = new AsyncResource('bound-anonymous-fn')
151
- const requestResource = new AsyncResource('bound-anonymous-fn')
152
146
 
153
- return requestResource.runInAsyncScope(() => {
154
- startChannel.publish({ metadata, path, type })
147
+ const ctx = { metadata, path, type }
155
148
 
156
- if (type === types.unary || type === types.client_stream) {
157
- if (typeof callback === 'function') {
158
- args[length - 1] = wrapCallback(requestResource, parentResource, callback)
159
- } else {
160
- args[length] = wrapCallback(requestResource, parentResource)
149
+ return startChannel.runStores(ctx, () => {
150
+ try {
151
+ if (type === types.unary || type === types.client_stream) {
152
+ if (typeof callback === 'function') {
153
+ args[length - 1] = wrapCallback(ctx, callback)
154
+ } else {
155
+ args[length] = wrapCallback(ctx)
156
+ }
161
157
  }
162
- }
163
158
 
164
- const call = method.apply(client, args)
159
+ const call = method.apply(client, args)
165
160
 
166
- wrapStream(call, requestResource, parentResource)
161
+ if (call && typeof call.emit === 'function') {
162
+ shimmer.wrap(call, 'emit', createWrapEmit(ctx))
163
+ }
167
164
 
168
- return call
165
+ return call
166
+ } catch (e) {
167
+ ctx.error = e
168
+ errorChannel.publish(ctx)
169
+ }
170
+ // No end channel needed
169
171
  })
170
172
  }
171
173
 
@@ -1,15 +1,17 @@
1
1
  'use strict'
2
2
 
3
3
  const types = require('./types')
4
- const { channel, addHook, AsyncResource } = require('../helpers/instrument')
4
+ const { channel, addHook } = require('../helpers/instrument')
5
5
  const shimmer = require('../../../datadog-shimmer')
6
6
 
7
7
  const nodeMajor = parseInt(process.versions.node.split('.')[0])
8
8
 
9
9
  const startChannel = channel('apm:grpc:server:request:start')
10
+ const asyncStartChannel = channel('apm:grpc:server:request:asyncStart')
10
11
  const errorChannel = channel('apm:grpc:server:request:error')
11
12
  const updateChannel = channel('apm:grpc:server:request:update')
12
13
  const finishChannel = channel('apm:grpc:server:request:finish')
14
+ const emitChannel = channel('apm:grpc:server:request:emit')
13
15
 
14
16
  // https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
15
17
  const OK = 0
@@ -33,28 +35,38 @@ function wrapHandler (func, name) {
33
35
  const type = types[this.type]
34
36
  const isStream = type !== 'unary'
35
37
 
36
- const parentResource = new AsyncResource('bound-anonymous-fn')
37
- const requestResource = new AsyncResource('bound-anonymous-fn')
38
-
39
- return requestResource.runInAsyncScope(() => {
40
- startChannel.publish({ name, metadata, type })
41
-
42
- const onCancel = requestResource.bind(() => {
43
- finishChannel.publish({ code: CANCELLED })
44
- })
45
-
46
- // Finish the span if the call was cancelled.
47
- call.once('cancelled', onCancel)
38
+ const ctx = { name, metadata, type }
39
+
40
+ return startChannel.runStores(ctx, () => {
41
+ try {
42
+ const onCancel = () => {
43
+ ctx.code = CANCELLED
44
+ finishChannel.publish(ctx)
45
+ }
46
+
47
+ // Finish the span if the call was cancelled.
48
+ call.once('cancelled', onCancel)
49
+
50
+ if (isStream) {
51
+ wrapStream(call, ctx, onCancel)
52
+ } else {
53
+ arguments[1] = wrapCallback(callback, call, ctx, onCancel)
54
+ }
55
+
56
+ shimmer.wrap(call, 'emit', emit => {
57
+ return function () {
58
+ return emitChannel.runStores(ctx, () => {
59
+ return emit.apply(this, arguments)
60
+ })
61
+ }
62
+ })
48
63
 
49
- if (isStream) {
50
- wrapStream(call, requestResource, onCancel)
51
- } else {
52
- arguments[1] = wrapCallback(callback, call, requestResource, parentResource, onCancel)
64
+ return func.apply(this, arguments)
65
+ } catch (e) {
66
+ ctx.error = e
67
+ errorChannel.publish(ctx)
53
68
  }
54
-
55
- shimmer.wrap(call, 'emit', emit => requestResource.bind(emit))
56
-
57
- return func.apply(this, arguments)
69
+ // No end channel needed
58
70
  })
59
71
  }
60
72
  }
@@ -69,69 +81,66 @@ function wrapRegister (register) {
69
81
  }
70
82
  }
71
83
 
72
- function wrapStream (call, requestResource, onCancel) {
73
- if (call.call && call.call.sendStatus) {
74
- call.call.sendStatus = wrapSendStatus(call.call.sendStatus, requestResource)
75
- }
76
-
77
- shimmer.wrap(call, 'emit', emit => {
78
- return function (eventName, ...args) {
79
- switch (eventName) {
84
+ function createWrapEmit (call, ctx, onCancel) {
85
+ return function wrapEmit (emit) {
86
+ return function (event, arg1) {
87
+ switch (event) {
80
88
  case 'error':
81
- errorChannel.publish(args[0])
82
- finishChannel.publish({ code: args[0].code })
83
-
89
+ ctx.error = arg1
90
+ errorChannel.publish(ctx)
91
+ ctx.code = arg1.code
92
+ finishChannel.publish(ctx)
84
93
  call.removeListener('cancelled', onCancel)
85
-
86
94
  break
87
-
88
- // Finish the span of the response only if it was successful.
89
- // Otherwise it'll be finished in the `error` listener.
90
95
  case 'finish':
91
96
  if (call.status) {
92
97
  updateChannel.publish(call.status)
93
98
  }
94
-
95
99
  if (!call.status || call.status.code === 0) {
96
- finishChannel.publish()
100
+ finishChannel.publish(ctx)
97
101
  }
98
-
99
102
  call.removeListener('cancelled', onCancel)
100
-
101
103
  break
102
104
  }
103
105
 
104
106
  return emit.apply(this, arguments)
105
107
  }
106
- })
108
+ }
107
109
  }
108
110
 
109
- function wrapCallback (callback, call, requestResource, parentResource, onCancel) {
110
- return function (err, value, trailer, flags) {
111
- requestResource.runInAsyncScope(() => {
112
- if (err) {
113
- errorChannel.publish(err)
114
- finishChannel.publish(err)
115
- } else {
116
- finishChannel.publish({ code: OK, trailer })
117
- }
111
+ function wrapStream (call, ctx, onCancel) {
112
+ if (call.call && call.call.sendStatus) {
113
+ call.call.sendStatus = wrapSendStatus(call.call.sendStatus, ctx)
114
+ }
118
115
 
119
- call.removeListener('cancelled', onCancel)
120
- })
116
+ shimmer.wrap(call, 'emit', createWrapEmit(call, ctx, onCancel))
117
+ }
121
118
 
122
- if (callback) {
123
- return parentResource.runInAsyncScope(() => {
124
- return callback.apply(this, arguments)
125
- })
119
+ function wrapCallback (callback = () => {}, call, ctx, onCancel) {
120
+ return function (err, value, trailer, flags) {
121
+ if (err) {
122
+ ctx.error = err
123
+ errorChannel.publish(ctx)
124
+ } else {
125
+ ctx.code = OK
126
+ ctx.trailer = trailer
126
127
  }
128
+
129
+ finishChannel.publish(ctx)
130
+
131
+ call.removeListener('cancelled', onCancel)
132
+
133
+ return asyncStartChannel.runStores(ctx, () => {
134
+ return callback.apply(this, arguments)
135
+ // No async end channel needed
136
+ })
127
137
  }
128
138
  }
129
139
 
130
- function wrapSendStatus (sendStatus, requestResource) {
140
+ function wrapSendStatus (sendStatus, ctx) {
131
141
  return function (status) {
132
- requestResource.runInAsyncScope(() => {
133
- updateChannel.publish(status)
134
- })
142
+ ctx.status = status
143
+ updateChannel.publish(ctx)
135
144
 
136
145
  return sendStatus.apply(this, arguments)
137
146
  }
@@ -1,32 +1,27 @@
1
1
  'use strict'
2
2
 
3
3
  const shimmer = require('../../../datadog-shimmer')
4
- const { addHook, channel, AsyncResource } = require('../helpers/instrument')
4
+ const { addHook, channel } = require('../helpers/instrument')
5
5
 
6
6
  const connectChannel = channel('apm:http2:client:connect:start')
7
7
  const startChannel = channel('apm:http2:client:request:start')
8
- const finishChannel = channel('apm:http2:client:request:finish')
8
+ const endChannel = channel('apm:http2:client:request:end')
9
+ const asyncStartChannel = channel('apm:http2:client:request:asyncStart')
10
+ const asyncEndChannel = channel('apm:http2:client:request:asyncEnd')
9
11
  const errorChannel = channel('apm:http2:client:request:error')
10
- const responseChannel = channel('apm:http2:client:response')
11
12
 
12
- function createWrapEmit (requestResource, parentResource) {
13
+ function createWrapEmit (ctx) {
13
14
  return function wrapEmit (emit) {
14
15
  return function (event, arg1) {
15
- requestResource.runInAsyncScope(() => {
16
- switch (event) {
17
- case 'response':
18
- responseChannel.publish(arg1)
19
- break
20
- case 'error':
21
- errorChannel.publish(arg1)
22
- case 'close': // eslint-disable-line no-fallthrough
23
- finishChannel.publish()
24
- break
25
- }
26
- })
16
+ ctx.eventName = event
17
+ ctx.eventData = arg1
27
18
 
28
- return parentResource.runInAsyncScope(() => {
29
- return emit.apply(this, arguments)
19
+ return asyncStartChannel.runStores(ctx, () => {
20
+ try {
21
+ return emit.apply(this, arguments)
22
+ } finally {
23
+ asyncEndChannel.publish(ctx)
24
+ }
30
25
  })
31
26
  }
32
27
  }
@@ -35,17 +30,21 @@ function createWrapEmit (requestResource, parentResource) {
35
30
  function createWrapRequest (authority, options) {
36
31
  return function wrapRequest (request) {
37
32
  return function (headers) {
38
- const parentResource = new AsyncResource('bound-anonymous-fn')
39
- const requestResource = new AsyncResource('bound-anonymous-fn')
33
+ const ctx = { headers, authority, options }
40
34
 
41
- return requestResource.runInAsyncScope(() => {
42
- startChannel.publish({ headers, authority, options })
35
+ return startChannel.runStores(ctx, () => {
36
+ try {
37
+ const req = request.apply(this, arguments)
43
38
 
44
- const req = request.apply(this, arguments)
39
+ shimmer.wrap(req, 'emit', createWrapEmit(ctx))
45
40
 
46
- shimmer.wrap(req, 'emit', createWrapEmit(requestResource, parentResource))
47
-
48
- return req
41
+ return req
42
+ } catch (e) {
43
+ ctx.error = e
44
+ errorChannel.publish(ctx)
45
+ } finally {
46
+ endChannel.publish(ctx)
47
+ }
49
48
  })
50
49
  }
51
50
  }
@@ -42,6 +42,7 @@ const jestItrConfigurationCh = channel('ci:jest:itr-configuration')
42
42
  let skippableSuites = []
43
43
  let isCodeCoverageEnabled = false
44
44
  let isSuitesSkippingEnabled = false
45
+ let isSuitesSkipped = false
45
46
 
46
47
  const sessionAsyncResource = new AsyncResource('bound-anonymous-fn')
47
48
 
@@ -227,7 +228,6 @@ function cliWrapper (cli, jestVersion) {
227
228
  log.error(err)
228
229
  }
229
230
  }
230
- const isSuitesSkipped = !!skippableSuites.length
231
231
 
232
232
  const processArgv = process.argv.slice(2).join(' ')
233
233
  sessionAsyncResource.runInAsyncScope(() => {
@@ -430,6 +430,8 @@ addHook({
430
430
 
431
431
  const filteredTests = getJestSuitesToRun(skippableSuites, tests, rootDir)
432
432
 
433
+ isSuitesSkipped = filteredTests.length !== tests.length
434
+
433
435
  skippableSuites = []
434
436
 
435
437
  return { ...testPaths, tests: filteredTests }
@@ -16,10 +16,19 @@ const consumerFinishCh = channel('apm:kafkajs:consume:finish')
16
16
  const consumerErrorCh = channel('apm:kafkajs:consume:error')
17
17
 
18
18
  addHook({ name: 'kafkajs', versions: ['>=1.4'] }, (obj) => {
19
- const Kafka = obj.Kafka
19
+ class Kafka extends obj.Kafka {
20
+ constructor (options) {
21
+ super(options)
22
+ this._brokers = (options.brokers && typeof options.brokers !== 'function')
23
+ ? options.brokers.join(',') : undefined
24
+ }
25
+ }
26
+ obj.Kafka = Kafka
27
+
20
28
  shimmer.wrap(Kafka.prototype, 'producer', createProducer => function () {
21
29
  const producer = createProducer.apply(this, arguments)
22
30
  const send = producer.send
31
+ const bootstrapServers = this._brokers
23
32
 
24
33
  producer.send = function () {
25
34
  const innerAsyncResource = new AsyncResource('bound-anonymous-fn')
@@ -36,7 +45,7 @@ addHook({ name: 'kafkajs', versions: ['>=1.4'] }, (obj) => {
36
45
  message.headers = message.headers || {}
37
46
  }
38
47
  }
39
- producerStartCh.publish({ topic, messages })
48
+ producerStartCh.publish({ topic, messages, bootstrapServers })
40
49
 
41
50
  const result = send.apply(this, arguments)
42
51
 
@@ -46,6 +46,7 @@ const originalCoverageMap = createCoverageMap()
46
46
 
47
47
  let suitesToSkip = []
48
48
  let frameworkVersion
49
+ let isSuitesSkipped = false
49
50
 
50
51
  function getSuitesByTestFile (root) {
51
52
  const suitesByTestFile = {}
@@ -125,8 +126,6 @@ function mochaHook (Runner) {
125
126
  }
126
127
  testFileToSuiteAr.clear()
127
128
 
128
- const isSuitesSkipped = !!suitesToSkip.length
129
-
130
129
  let testCodeCoverageLinesTotal
131
130
  if (global.__coverage__) {
132
131
  try {
@@ -360,7 +359,10 @@ addHook({
360
359
  suitesToSkip = skippableSuites
361
360
  }
362
361
  // We remove the suites that we skip through ITR
363
- runner.suite.suites = getSuitesToRun(runner.suite.suites)
362
+ const newSuites = getSuitesToRun(runner.suite.suites)
363
+ isSuitesSkipped = newSuites.length !== runner.suite.suites.length
364
+ runner.suite.suites = newSuites
365
+
364
366
  global.run()
365
367
  }
366
368
 
@@ -11,6 +11,8 @@ const startCh = channel('apm:redis:command:start')
11
11
  const finishCh = channel('apm:redis:command:finish')
12
12
  const errorCh = channel('apm:redis:command:error')
13
13
 
14
+ let createClientUrl
15
+
14
16
  function wrapAddCommand (addCommand) {
15
17
  return function (command) {
16
18
  if (!startCh.hasSubscribers) {
@@ -22,7 +24,7 @@ function wrapAddCommand (addCommand) {
22
24
 
23
25
  const asyncResource = new AsyncResource('bound-anonymous-fn')
24
26
  return asyncResource.runInAsyncScope(() => {
25
- start(this, name, args)
27
+ start(this, name, args, this._url)
26
28
 
27
29
  const res = addCommand.apply(this, arguments)
28
30
  const onResolve = asyncResource.bind(() => finish(finishCh, errorCh))
@@ -35,12 +37,53 @@ function wrapAddCommand (addCommand) {
35
37
  }
36
38
  }
37
39
 
38
- addHook({ name: '@redis/client', file: 'dist/lib/client/commands-queue.js', versions: ['>=1.1'] }, redis => {
40
+ function wrapCommandQueueClass (cls) {
41
+ const ret = class RedisCommandQueue extends cls {
42
+ constructor () {
43
+ super(arguments)
44
+ if (createClientUrl) {
45
+ try {
46
+ const parsed = new URL(createClientUrl)
47
+ if (parsed) {
48
+ this._url = { host: parsed.hostname, port: +parsed.port || 6379 }
49
+ }
50
+ } catch (error) {
51
+ // ignore
52
+ }
53
+ }
54
+ this._url = this._url || { host: 'localhost', port: 6379 }
55
+ }
56
+ }
57
+ return ret
58
+ }
59
+
60
+ function wrapCreateClient (request) {
61
+ return function (opts) {
62
+ createClientUrl = opts && opts.url
63
+ const ret = request.apply(this, arguments)
64
+ createClientUrl = undefined
65
+ return ret
66
+ }
67
+ }
68
+
69
+ addHook({ name: '@node-redis/client', file: 'dist/lib/client/commands-queue.js', versions: ['>=1'] }, redis => {
70
+ redis.default = wrapCommandQueueClass(redis.default)
39
71
  shimmer.wrap(redis.default.prototype, 'addCommand', wrapAddCommand)
40
72
  return redis
41
73
  })
42
74
 
43
- addHook({ name: '@node-redis/client', file: 'dist/lib/client/commands-queue.js', versions: ['>=1'] }, redis => {
75
+ addHook({ name: '@node-redis/client', file: 'dist/lib/client/index.js', versions: ['>=1'] }, redis => {
76
+ shimmer.wrap(redis.default, 'create', wrapCreateClient)
77
+ return redis
78
+ })
79
+
80
+ addHook({ name: '@redis/client', file: 'dist/lib/client/index.js', versions: ['>=1.1'] }, redis => {
81
+ shimmer.wrap(redis.default, 'create', wrapCreateClient)
82
+ return redis
83
+ })
84
+
85
+ addHook({ name: '@redis/client', file: 'dist/lib/client/commands-queue.js', versions: ['>=1.1'] }, redis => {
86
+ redis.default = wrapCommandQueueClass(redis.default)
44
87
  shimmer.wrap(redis.default.prototype, 'addCommand', wrapAddCommand)
45
88
  return redis
46
89
  })
@@ -106,9 +149,9 @@ addHook({ name: 'redis', versions: ['>=0.12 <2.6'] }, redis => {
106
149
  return redis
107
150
  })
108
151
 
109
- function start (client, command, args) {
152
+ function start (client, command, args, url = {}) {
110
153
  const db = client.selected_db
111
- const connectionOptions = client.connection_options || client.connection_option || client.connectionOption || {}
154
+ const connectionOptions = client.connection_options || client.connection_option || client.connectionOption || url
112
155
  startCh.publish({ db, command, args, connectionOptions })
113
156
  }
114
157
 
@@ -37,7 +37,7 @@ const CYPRESS_STATUS_TO_TEST_STATUS = {
37
37
  function getTestSpanMetadata (tracer, testName, testSuite, cypressConfig) {
38
38
  const childOf = getTestParentSpan(tracer)
39
39
 
40
- const commonTags = getTestCommonTags(testName, testSuite, cypressConfig.version)
40
+ const commonTags = getTestCommonTags(testName, testSuite, cypressConfig.version, TEST_FRAMEWORK_NAME)
41
41
 
42
42
  return {
43
43
  childOf,
@@ -119,6 +119,7 @@ function getSkippableTests (isSuitesSkippingEnabled, tracer, testConfiguration)
119
119
  }
120
120
 
121
121
  module.exports = (on, config) => {
122
+ let isTestsSkipped = false
122
123
  const tracer = require('../../dd-trace')
123
124
  const testEnvironmentMetadata = getTestEnvironmentMetadata(TEST_FRAMEWORK_NAME)
124
125
 
@@ -306,7 +307,7 @@ module.exports = (on, config) => {
306
307
  testSessionSpan,
307
308
  testModuleSpan,
308
309
  {
309
- isSuitesSkipped: !!testsToSkip.length,
310
+ isSuitesSkipped: isTestsSkipped,
310
311
  isSuitesSkippingEnabled,
311
312
  isCodeCoverageEnabled
312
313
  }
@@ -352,6 +353,7 @@ module.exports = (on, config) => {
352
353
  if (testsToSkip.find(test => {
353
354
  return testName === test.name && testSuite === test.suite
354
355
  })) {
356
+ isTestsSkipped = true
355
357
  return { shouldSkip: true }
356
358
  }
357
359