dd-trace 5.51.0 → 5.52.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 (67) hide show
  1. package/LICENSE-3rdparty.csv +0 -6
  2. package/index.d.ts +35 -1
  3. package/package.json +3 -9
  4. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +391 -0
  5. package/packages/datadog-instrumentations/src/cucumber.js +3 -0
  6. package/packages/datadog-instrumentations/src/dns.js +16 -14
  7. package/packages/datadog-instrumentations/src/fs.js +37 -46
  8. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  9. package/packages/datadog-instrumentations/src/jest.js +5 -0
  10. package/packages/datadog-instrumentations/src/mocha/utils.js +5 -0
  11. package/packages/datadog-instrumentations/src/net.js +24 -28
  12. package/packages/datadog-instrumentations/src/pg.js +19 -5
  13. package/packages/datadog-instrumentations/src/playwright.js +6 -0
  14. package/packages/datadog-instrumentations/src/vitest.js +18 -4
  15. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +11 -0
  16. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +11 -0
  17. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +19 -0
  18. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +11 -0
  19. package/packages/datadog-plugin-cucumber/src/index.js +3 -0
  20. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +3 -0
  21. package/packages/datadog-plugin-dns/src/lookup.js +10 -5
  22. package/packages/datadog-plugin-dns/src/lookup_service.js +6 -2
  23. package/packages/datadog-plugin-dns/src/resolve.js +5 -2
  24. package/packages/datadog-plugin-dns/src/reverse.js +6 -2
  25. package/packages/datadog-plugin-fs/src/index.js +9 -2
  26. package/packages/datadog-plugin-jest/src/index.js +3 -0
  27. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -1
  28. package/packages/datadog-plugin-kafkajs/src/consumer.js +12 -21
  29. package/packages/datadog-plugin-kafkajs/src/producer.js +6 -2
  30. package/packages/datadog-plugin-kafkajs/src/utils.js +27 -0
  31. package/packages/datadog-plugin-langchain/src/index.js +0 -1
  32. package/packages/datadog-plugin-mocha/src/index.js +3 -0
  33. package/packages/datadog-plugin-net/src/ipc.js +6 -4
  34. package/packages/datadog-plugin-net/src/tcp.js +15 -9
  35. package/packages/datadog-plugin-pg/src/index.js +5 -1
  36. package/packages/datadog-plugin-playwright/src/index.js +3 -0
  37. package/packages/datadog-plugin-vitest/src/index.js +15 -3
  38. package/packages/dd-trace/src/appsec/api_security_sampler.js +20 -12
  39. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +14 -9
  40. package/packages/dd-trace/src/appsec/index.js +1 -1
  41. package/packages/dd-trace/src/baggage.js +36 -0
  42. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
  43. package/packages/dd-trace/src/config.js +13 -1
  44. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -0
  45. package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -1
  46. package/packages/dd-trace/src/exporters/common/docker.js +13 -31
  47. package/packages/dd-trace/src/guardrails/telemetry.js +2 -5
  48. package/packages/dd-trace/src/llmobs/writers/base.js +33 -12
  49. package/packages/dd-trace/src/noop/proxy.js +5 -0
  50. package/packages/dd-trace/src/opentelemetry/context_manager.js +2 -0
  51. package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -9
  52. package/packages/dd-trace/src/plugin_manager.js +2 -0
  53. package/packages/dd-trace/src/plugins/index.js +3 -0
  54. package/packages/dd-trace/src/plugins/log_plugin.js +9 -20
  55. package/packages/dd-trace/src/plugins/outbound.js +11 -3
  56. package/packages/dd-trace/src/plugins/tracing.js +8 -4
  57. package/packages/dd-trace/src/plugins/util/test.js +1 -1
  58. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -1
  59. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -1
  60. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -1
  61. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +2 -2
  62. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -1
  63. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +15 -14
  64. package/packages/dd-trace/src/proxy.js +12 -0
  65. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +8 -0
  66. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
  67. package/packages/dd-trace/src/standalone/product.js +3 -5
@@ -1,10 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const {
4
- channel,
5
- addHook,
6
- AsyncResource
7
- } = require('./helpers/instrument')
3
+ const { channel, addHook } = require('./helpers/instrument')
8
4
  const shimmer = require('../../datadog-shimmer')
9
5
 
10
6
  const startChannel = channel('apm:fs:operation:start')
@@ -191,25 +187,23 @@ function wrapCreateStream (original) {
191
187
  return function (path, options) {
192
188
  if (!startChannel.hasSubscribers) return original.apply(this, arguments)
193
189
 
194
- const innerResource = new AsyncResource('bound-anonymous-fn')
195
- const message = getMessage(name, ['path', 'options'], arguments)
196
-
197
- return innerResource.runInAsyncScope(() => {
198
- startChannel.publish(message)
190
+ const ctx = getMessage(name, ['path', 'options'], arguments)
199
191
 
192
+ return startChannel.runStores(ctx, () => {
200
193
  try {
201
194
  const stream = original.apply(this, arguments)
202
- const onError = innerResource.bind(error => {
203
- errorChannel.publish(error)
195
+ const onError = error => {
196
+ ctx.error = error
197
+ errorChannel.publish(ctx)
204
198
  onFinish()
205
- })
206
- const onFinish = innerResource.bind(() => {
207
- finishChannel.publish()
199
+ }
200
+ const onFinish = () => {
201
+ finishChannel.runStores(ctx, () => {})
208
202
  stream.off('close', onFinish)
209
203
  stream.off('end', onFinish)
210
204
  stream.off('finish', onFinish)
211
205
  stream.off('error', onError)
212
- })
206
+ }
213
207
 
214
208
  stream.once('close', onFinish)
215
209
  stream.once('end', onFinish)
@@ -218,8 +212,9 @@ function wrapCreateStream (original) {
218
212
 
219
213
  return stream
220
214
  } catch (error) {
221
- errorChannel.publish(error)
222
- finishChannel.publish()
215
+ ctx.error = error
216
+ errorChannel.publish(ctx)
217
+ finishChannel.runStores(ctx, () => {})
223
218
  }
224
219
  })
225
220
  }
@@ -239,17 +234,16 @@ function createWatchWrapFunction (override = '') {
239
234
  const operation = name
240
235
  return function () {
241
236
  if (!startChannel.hasSubscribers) return original.apply(this, arguments)
242
- const message = getMessage(method, watchMethods[operation], arguments, this)
243
- const innerResource = new AsyncResource('bound-anonymous-fn')
244
- return innerResource.runInAsyncScope(() => {
245
- startChannel.publish(message)
237
+ const ctx = getMessage(method, watchMethods[operation], arguments, this)
238
+ return startChannel.runStores(ctx, () => {
246
239
  try {
247
240
  const result = original.apply(this, arguments)
248
- finishChannel.publish()
241
+ finishChannel.runStores(ctx, () => {})
249
242
  return result
250
243
  } catch (error) {
251
- errorChannel.publish(error)
252
- finishChannel.publish()
244
+ ctx.error = error
245
+ errorChannel.publish(ctx)
246
+ finishChannel.runStores(ctx, () => {})
253
247
  throw error
254
248
  }
255
249
  })
@@ -268,30 +262,25 @@ function createWrapFunction (prefix = '', override = '') {
268
262
 
269
263
  const lastIndex = arguments.length - 1
270
264
  const cb = typeof arguments[lastIndex] === 'function' && arguments[lastIndex]
271
- const innerResource = new AsyncResource('bound-anonymous-fn')
272
265
  const params = getMethodParamsRelationByPrefix(prefix)[operation]
273
266
  const abortController = new AbortController()
274
- const message = { ...getMessage(method, params, arguments, this), abortController }
267
+ const ctx = { ...getMessage(method, params, arguments, this), abortController }
275
268
 
276
- const finish = innerResource.bind(function (error) {
269
+ const finish = function (error, cb = () => {}) {
277
270
  if (error !== null && typeof error === 'object') { // fs.exists receives a boolean
278
- errorChannel.publish(error)
271
+ ctx.error = error
272
+ errorChannel.publish(ctx)
279
273
  }
280
- finishChannel.publish()
281
- })
274
+ return finishChannel.runStores(ctx, cb)
275
+ }
282
276
 
283
277
  if (cb) {
284
- const outerResource = new AsyncResource('bound-anonymous-fn')
285
-
286
- arguments[lastIndex] = shimmer.wrapFunction(cb, cb => innerResource.bind(function (e) {
287
- finish(e)
288
- return outerResource.runInAsyncScope(() => cb.apply(this, arguments))
289
- }))
278
+ arguments[lastIndex] = shimmer.wrapFunction(cb, cb => function (e) {
279
+ return finish(e, () => cb.apply(this, arguments))
280
+ })
290
281
  }
291
282
 
292
- return innerResource.runInAsyncScope(() => {
293
- startChannel.publish(message)
294
-
283
+ return startChannel.runStores(ctx, () => {
295
284
  if (abortController.signal.aborted) {
296
285
  const error = abortController.signal.reason || new Error('Aborted')
297
286
 
@@ -318,23 +307,25 @@ function createWrapFunction (prefix = '', override = '') {
318
307
  if (isFirstMethodReturningFileHandle(original)) {
319
308
  wrapFileHandle(value)
320
309
  }
321
- finishChannel.publish()
310
+ finishChannel.runStores(ctx, () => {})
322
311
  return value
323
312
  },
324
313
  error => {
325
- errorChannel.publish(error)
326
- finishChannel.publish()
314
+ ctx.error = error
315
+ errorChannel.publish(ctx)
316
+ finishChannel.runStores(ctx, () => {})
327
317
  throw error
328
318
  }
329
319
  )
330
320
  }
331
321
 
332
- finishChannel.publish()
322
+ finishChannel.runStores(ctx, () => {})
333
323
 
334
324
  return result
335
325
  } catch (error) {
336
- errorChannel.publish(error)
337
- finishChannel.publish()
326
+ ctx.error = error
327
+ errorChannel.publish(ctx)
328
+ finishChannel.runStores(ctx, () => {})
338
329
  throw error
339
330
  }
340
331
  })
@@ -70,6 +70,7 @@ module.exports = {
70
70
  knex: () => require('../knex'),
71
71
  koa: () => require('../koa'),
72
72
  'koa-router': () => require('../koa'),
73
+ '@confluentinc/kafka-javascript': () => require('../confluentinc-kafka-javascript'),
73
74
  kafkajs: () => require('../kafkajs'),
74
75
  langchain: () => require('../langchain'),
75
76
  ldapjs: () => require('../ldapjs'),
@@ -408,6 +408,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
408
408
  event.test.fn = originalTestFns.get(event.test)
409
409
 
410
410
  let attemptToFixPassed = false
411
+ let attemptToFixFailed = false
411
412
  let failedAllTests = false
412
413
  let isAttemptToFix = false
413
414
  if (this.isTestManagementTestsEnabled) {
@@ -425,6 +426,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
425
426
  // If it is, we'll set the failedAllTests flag to true if all the tests failed
426
427
  // If all tests passed, we'll set the attemptToFixPassed flag to true
427
428
  if (testStatuses.length === testManagementAttemptToFixRetries + 1) {
429
+ if (testStatuses.some(status => status === 'fail')) {
430
+ attemptToFixFailed = true
431
+ }
428
432
  if (testStatuses.every(status => status === 'fail')) {
429
433
  failedAllTests = true
430
434
  } else if (testStatuses.every(status => status === 'pass')) {
@@ -490,6 +494,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
490
494
  testStartLine: getTestLineStart(event.test.asyncError, this.testSuite),
491
495
  attemptToFixPassed,
492
496
  failedAllTests,
497
+ attemptToFixFailed,
493
498
  isAtrRetry
494
499
  })
495
500
  })
@@ -265,6 +265,7 @@ function getOnTestEndHandler (config) {
265
265
 
266
266
  let hasFailedAllRetries = false
267
267
  let attemptToFixPassed = false
268
+ let attemptToFixFailed = false
268
269
 
269
270
  const testName = getTestFullName(test)
270
271
 
@@ -278,6 +279,9 @@ function getOnTestEndHandler (config) {
278
279
  const isLastAttempt = testStatuses.length === config.testManagementAttemptToFixRetries + 1
279
280
 
280
281
  if (test._ddIsAttemptToFix && isLastAttempt) {
282
+ if (testStatuses.some(status => status === 'fail')) {
283
+ attemptToFixFailed = true
284
+ }
281
285
  if (testStatuses.every(status => status === 'fail')) {
282
286
  hasFailedAllRetries = true
283
287
  } else if (testStatuses.every(status => status === 'pass')) {
@@ -299,6 +303,7 @@ function getOnTestEndHandler (config) {
299
303
  isLastRetry: getIsLastRetry(test),
300
304
  hasFailedAllRetries,
301
305
  attemptToFixPassed,
306
+ attemptToFixFailed,
302
307
  isAttemptToFixRetry,
303
308
  isAtrRetry
304
309
  })
@@ -1,10 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const {
4
- channel,
5
- addHook,
6
- AsyncResource
7
- } = require('./helpers/instrument')
3
+ const { channel, addHook } = require('./helpers/instrument')
8
4
  const shimmer = require('../../datadog-shimmer')
9
5
 
10
6
  const startICPCh = channel('apm:net:ipc:start')
@@ -15,6 +11,7 @@ const startTCPCh = channel('apm:net:tcp:start')
15
11
  const finishTCPCh = channel('apm:net:tcp:finish')
16
12
  const errorTCPCh = channel('apm:net:tcp:error')
17
13
 
14
+ const readyCh = channel('apm:net:tcp:ready')
18
15
  const connectionCh = channel('apm:net:tcp:connection')
19
16
 
20
17
  const names = ['net', 'node:net']
@@ -39,30 +36,27 @@ addHook({ name: names }, (net, version, name) => {
39
36
 
40
37
  if (!options) return connect.apply(this, arguments)
41
38
 
42
- const callbackResource = new AsyncResource('bound-anonymous-fn')
43
- const asyncResource = new AsyncResource('bound-anonymous-fn')
39
+ const protocol = options.path ? 'ipc' : 'tcp'
40
+ const startCh = protocol === 'ipc' ? startICPCh : startTCPCh
41
+ const finishCh = protocol === 'ipc' ? finishICPCh : finishTCPCh
42
+ const errorCh = protocol === 'ipc' ? errorICPCh : errorTCPCh
43
+ const ctx = { options }
44
44
 
45
45
  if (typeof callback === 'function') {
46
- arguments[lastIndex] = callbackResource.bind(callback)
46
+ arguments[lastIndex] = function (...args) {
47
+ return finishCh.runStores(ctx, callback, this, ...args)
48
+ }
47
49
  }
48
50
 
49
- const protocol = options.path ? 'ipc' : 'tcp'
50
-
51
- return asyncResource.runInAsyncScope(() => {
52
- if (protocol === 'ipc') {
53
- startICPCh.publish({ options })
54
- setupListeners(this, 'ipc', asyncResource)
55
- } else {
56
- startTCPCh.publish({ options })
57
- setupListeners(this, 'tcp', asyncResource)
58
- }
51
+ return startCh.runStores(ctx, () => {
52
+ setupListeners(this, protocol, ctx, finishCh, errorCh)
59
53
 
60
54
  const emit = this.emit
61
55
  this.emit = shimmer.wrapFunction(emit, emit => function (eventName) {
62
56
  switch (eventName) {
63
57
  case 'ready':
64
58
  case 'connect':
65
- return callbackResource.runInAsyncScope(() => {
59
+ return readyCh.runStores(ctx, () => {
66
60
  return emit.apply(this, arguments)
67
61
  })
68
62
  default:
@@ -73,7 +67,7 @@ addHook({ name: names }, (net, version, name) => {
73
67
  try {
74
68
  return connect.apply(this, arguments)
75
69
  } catch (err) {
76
- protocol === 'ipc' ? errorICPCh.publish(err) : errorTCPCh.publish(err)
70
+ errorCh.publish(err)
77
71
 
78
72
  throw err
79
73
  }
@@ -104,19 +98,21 @@ function getOptions (args) {
104
98
  }
105
99
  }
106
100
 
107
- function setupListeners (socket, protocol, asyncResource) {
101
+ function setupListeners (socket, protocol, ctx, finishCh, errorCh) {
108
102
  const events = ['connect', 'error', 'close', 'timeout']
109
103
 
110
- const wrapListener = asyncResource.bind(function (error) {
104
+ const wrapListener = function (error) {
111
105
  if (error) {
112
- protocol === 'ipc' ? errorICPCh.publish(error) : errorTCPCh.publish(error)
106
+ ctx.error = error
107
+ errorCh.publish(ctx)
113
108
  }
114
- protocol === 'ipc' ? finishICPCh.publish(undefined) : finishTCPCh.publish(undefined)
115
- })
109
+ finishCh.runStores(ctx, () => {})
110
+ }
116
111
 
117
- const localListener = asyncResource.bind(function () {
118
- connectionCh.publish({ socket })
119
- })
112
+ const localListener = function () {
113
+ ctx.socket = socket
114
+ connectionCh.publish(ctx)
115
+ }
120
116
 
121
117
  const cleanupListener = function () {
122
118
  socket.removeListener('connect', localListener)
@@ -14,6 +14,8 @@ const errorCh = channel('apm:pg:query:error')
14
14
  const startPoolQueryCh = channel('datadog:pg:pool:query:start')
15
15
  const finishPoolQueryCh = channel('datadog:pg:pool:query:finish')
16
16
 
17
+ const { errorMonitor } = require('node:events')
18
+
17
19
  addHook({ name: 'pg', versions: ['>=8.0.3'] }, pg => {
18
20
  shimmer.wrap(pg.Client.prototype, 'query', query => wrapQuery(query))
19
21
  shimmer.wrap(pg.Pool.prototype, 'query', query => wrapPoolQuery(query))
@@ -39,13 +41,15 @@ function wrapQuery (query) {
39
41
  ? arguments[0]
40
42
  : { text: arguments[0] }
41
43
 
42
- const textProp = Object.getOwnPropertyDescriptor(pgQuery, 'text')
44
+ const textPropObj = pgQuery.cursor ?? pgQuery
45
+ const textProp = Object.getOwnPropertyDescriptor(textPropObj, 'text')
46
+ const stream = typeof textPropObj.read === 'function'
43
47
 
44
48
  // Only alter `text` property if safe to do so.
45
49
  if (!textProp || textProp.configurable) {
46
- const originalText = pgQuery.text
50
+ const originalText = textPropObj.text
47
51
 
48
- Object.defineProperty(pgQuery, 'text', {
52
+ Object.defineProperty(textPropObj, 'text', {
49
53
  get () {
50
54
  return this?.__ddInjectableQuery || originalText
51
55
  }
@@ -57,9 +61,10 @@ function wrapQuery (query) {
57
61
 
58
62
  startCh.publish({
59
63
  params: this.connectionParameters,
60
- query: pgQuery,
64
+ query: textPropObj,
61
65
  processId,
62
- abortController
66
+ abortController,
67
+ stream
63
68
  })
64
69
 
65
70
  const finish = asyncResource.bind(function (error, res) {
@@ -130,6 +135,15 @@ function wrapQuery (query) {
130
135
  newQuery.then((res) => finish(null, res), finish)
131
136
  }
132
137
 
138
+ if (stream) {
139
+ newQuery.on('end', () => {
140
+ finish(null, [])
141
+ })
142
+ newQuery.on(errorMonitor, (err) => {
143
+ finish(err)
144
+ })
145
+ }
146
+
133
147
  try {
134
148
  return retval
135
149
  } catch (err) {
@@ -337,6 +337,9 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
337
337
  }
338
338
 
339
339
  if (testStatuses.length === testManagementAttemptToFixRetries + 1) {
340
+ if (testStatuses.some(status => status === 'fail')) {
341
+ test._ddHasFailedAttemptToFixRetries = true
342
+ }
340
343
  if (testStatuses.every(status => status === 'fail')) {
341
344
  test._ddHasFailedAllRetries = true
342
345
  } else if (testStatuses.every(status => status === 'pass')) {
@@ -366,6 +369,7 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
366
369
  isEfdRetry: test._ddIsEfdRetry,
367
370
  hasFailedAllRetries: test._ddHasFailedAllRetries,
368
371
  hasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
372
+ hasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
369
373
  isAtrRetry
370
374
  })
371
375
  })
@@ -492,6 +496,7 @@ function dispatcherHookNew (dispatcherExport, runWrapper) {
492
496
  _ddIsEfdRetry: test._ddIsEfdRetry,
493
497
  _ddHasFailedAllRetries: test._ddHasFailedAllRetries,
494
498
  _ddHasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
499
+ _ddHasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
495
500
  _ddIsAtrRetry: isAtrRetry
496
501
  }
497
502
  })
@@ -986,6 +991,7 @@ addHook({
986
991
  isAttemptToFixRetry: test._ddIsAttemptToFixRetry,
987
992
  hasFailedAllRetries: test._ddHasFailedAllRetries,
988
993
  hasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
994
+ hasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
989
995
  isAtrRetry: test._ddIsAtrRetry,
990
996
  onDone
991
997
  })
@@ -614,17 +614,22 @@ addHook({
614
614
  }
615
615
 
616
616
  let attemptToFixPassed = false
617
+ let attemptToFixFailed = false
617
618
  if (attemptToFixTasks.has(task)) {
618
619
  const statuses = taskToStatuses.get(task)
619
- if (statuses.length === testManagementAttemptToFixRetries && statuses.every(status => status === 'pass')) {
620
- attemptToFixPassed = true
620
+ if (statuses.length === testManagementAttemptToFixRetries) {
621
+ if (statuses.every(status => status === 'pass')) {
622
+ attemptToFixPassed = true
623
+ } else if (statuses.some(status => status === 'fail')) {
624
+ attemptToFixFailed = true
625
+ }
621
626
  }
622
627
  }
623
628
 
624
629
  if (asyncResource) {
625
630
  // We don't finish here because the test might fail in a later hook (afterEach)
626
631
  asyncResource.runInAsyncScope(() => {
627
- testFinishTimeCh.publish({ status, task, attemptToFixPassed })
632
+ testFinishTimeCh.publish({ status, task, attemptToFixPassed, attemptToFixFailed })
628
633
  })
629
634
  }
630
635
 
@@ -776,8 +781,12 @@ addHook({
776
781
  }
777
782
 
778
783
  let hasFailedAllRetries = false
784
+ let attemptToFixFailed = false
779
785
  if (attemptToFixTasks.has(task)) {
780
786
  const statuses = taskToStatuses.get(task)
787
+ if (statuses.some(status => status === 'fail')) {
788
+ attemptToFixFailed = true
789
+ }
781
790
  if (statuses.every(status => status === 'fail')) {
782
791
  hasFailedAllRetries = true
783
792
  }
@@ -787,7 +796,12 @@ addHook({
787
796
  const isRetry = task.result?.retryCount > 0
788
797
  // `duration` is the duration of all the retries, so it can't be used if there are retries
789
798
  testAsyncResource.runInAsyncScope(() => {
790
- testErrorCh.publish({ duration: !isRetry ? duration : undefined, error: testError, hasFailedAllRetries })
799
+ testErrorCh.publish({
800
+ duration: !isRetry ? duration : undefined,
801
+ error: testError,
802
+ hasFailedAllRetries,
803
+ attemptToFixFailed
804
+ })
791
805
  })
792
806
  }
793
807
  if (errors?.length) {
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const KafkajsBatchConsumerPlugin = require('../../datadog-plugin-kafkajs/src/batch-consumer')
4
+
5
+ class ConfluentKafkaJsBatchConsumerPlugin extends KafkajsBatchConsumerPlugin {
6
+ static get id () {
7
+ return '@confluentinc/kafka-javascript'
8
+ }
9
+ }
10
+
11
+ module.exports = ConfluentKafkaJsBatchConsumerPlugin
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const KafkajsConsumerPlugin = require('../../datadog-plugin-kafkajs/src/consumer')
4
+
5
+ class ConfluentKafkaJsConsumerPlugin extends KafkajsConsumerPlugin {
6
+ static get id () {
7
+ return '@confluentinc/kafka-javascript'
8
+ }
9
+ }
10
+
11
+ module.exports = ConfluentKafkaJsConsumerPlugin
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ const ProducerPlugin = require('./producer')
4
+ const ConsumerPlugin = require('./consumer')
5
+ const BatchConsumerPlugin = require('./batch-consumer')
6
+ const KafkajsPlugin = require('../../datadog-plugin-kafkajs/src/index')
7
+
8
+ class ConfluentKafkaJsPlugin extends KafkajsPlugin {
9
+ static get id () { return '@confluentinc/kafka-javascript' }
10
+ static get plugins () {
11
+ return {
12
+ producer: ProducerPlugin,
13
+ consumer: ConsumerPlugin,
14
+ batchConsumer: BatchConsumerPlugin
15
+ }
16
+ }
17
+ }
18
+
19
+ module.exports = ConfluentKafkaJsPlugin
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const KafkajsProducerPlugin = require('../../datadog-plugin-kafkajs/src/producer')
4
+
5
+ class ConfluentKafkaJsProducerPlugin extends KafkajsProducerPlugin {
6
+ static get id () {
7
+ return '@confluentinc/kafka-javascript'
8
+ }
9
+ }
10
+
11
+ module.exports = ConfluentKafkaJsProducerPlugin
@@ -341,6 +341,7 @@ class CucumberPlugin extends CiPlugin {
341
341
  isAttemptToFixRetry,
342
342
  hasFailedAllRetries,
343
343
  hasPassedAllRetries,
344
+ hasFailedAttemptToFix,
344
345
  isDisabled,
345
346
  isQuarantined
346
347
  }) => {
@@ -385,6 +386,8 @@ class CucumberPlugin extends CiPlugin {
385
386
  span.setTag(TEST_RETRY_REASON, TEST_RETRY_REASON_TYPES.atf)
386
387
  if (hasPassedAllRetries) {
387
388
  span.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'true')
389
+ } else if (hasFailedAttemptToFix) {
390
+ span.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'false')
388
391
  }
389
392
  }
390
393
 
@@ -838,6 +838,9 @@ class CypressPlugin {
838
838
  }
839
839
  const isLastAttempt = testStatuses.length === this.testManagementAttemptToFixRetries + 1
840
840
  if (isLastAttempt) {
841
+ if (testStatuses.some(status => status === 'fail')) {
842
+ this.activeTestSpan.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'false')
843
+ }
841
844
  if (testStatuses.every(status => status === 'fail')) {
842
845
  this.activeTestSpan.setTag(TEST_HAS_FAILED_ALL_RETRIES, 'true')
843
846
  } else if (testStatuses.every(status => status === 'pass')) {
@@ -6,7 +6,9 @@ class DNSLookupPlugin extends ClientPlugin {
6
6
  static get id () { return 'dns' }
7
7
  static get operation () { return 'lookup' }
8
8
 
9
- start ([hostname]) {
9
+ bindStart (ctx) {
10
+ const [hostname] = ctx.args
11
+
10
12
  this.startSpan('dns.lookup', {
11
13
  service: this.config.service,
12
14
  resource: hostname,
@@ -16,11 +18,14 @@ class DNSLookupPlugin extends ClientPlugin {
16
18
  'dns.address': '',
17
19
  'dns.addresses': ''
18
20
  }
19
- })
21
+ }, ctx)
22
+
23
+ return ctx.currentStore
20
24
  }
21
25
 
22
- finish (result) {
23
- const span = this.activeSpan
26
+ bindFinish (ctx) {
27
+ const span = ctx.currentStore.span
28
+ const result = ctx.result
24
29
 
25
30
  if (Array.isArray(result)) {
26
31
  const addresses = Array.isArray(result)
@@ -33,7 +38,7 @@ class DNSLookupPlugin extends ClientPlugin {
33
38
  span.setTag('dns.address', result)
34
39
  }
35
40
 
36
- super.finish()
41
+ return ctx.parentStore
37
42
  }
38
43
  }
39
44
 
@@ -6,7 +6,9 @@ class DNSLookupServicePlugin extends ClientPlugin {
6
6
  static get id () { return 'dns' }
7
7
  static get operation () { return 'lookup_service' }
8
8
 
9
- start ([address, port]) {
9
+ bindStart (ctx) {
10
+ const [address, port] = ctx.args
11
+
10
12
  this.startSpan('dns.lookup_service', {
11
13
  service: this.config.service,
12
14
  resource: `${address}:${port}`,
@@ -17,7 +19,9 @@ class DNSLookupServicePlugin extends ClientPlugin {
17
19
  metrics: {
18
20
  'dns.port': port
19
21
  }
20
- })
22
+ }, ctx)
23
+
24
+ return ctx.currentStore
21
25
  }
22
26
  }
23
27
 
@@ -6,7 +6,8 @@ class DNSResolvePlugin extends ClientPlugin {
6
6
  static get id () { return 'dns' }
7
7
  static get operation () { return 'resolve' }
8
8
 
9
- start ([hostname, maybeType]) {
9
+ bindStart (ctx) {
10
+ const [hostname, maybeType] = ctx.args
10
11
  const rrtype = typeof maybeType === 'string' ? maybeType : 'A'
11
12
 
12
13
  this.startSpan('dns.resolve', {
@@ -17,7 +18,9 @@ class DNSResolvePlugin extends ClientPlugin {
17
18
  'dns.hostname': hostname,
18
19
  'dns.rrtype': rrtype
19
20
  }
20
- })
21
+ }, ctx)
22
+
23
+ return ctx.currentStore
21
24
  }
22
25
  }
23
26
 
@@ -6,7 +6,9 @@ class DNSReversePlugin extends ClientPlugin {
6
6
  static get id () { return 'dns' }
7
7
  static get operation () { return 'reverse' }
8
8
 
9
- start ([ip]) {
9
+ bindStart (ctx) {
10
+ const [ip] = ctx.args
11
+
10
12
  this.startSpan('dns.reverse', {
11
13
  service: this.config.service,
12
14
  resource: ip,
@@ -14,7 +16,9 @@ class DNSReversePlugin extends ClientPlugin {
14
16
  meta: {
15
17
  'dns.ip': ip
16
18
  }
17
- })
19
+ }, ctx)
20
+
21
+ return ctx.currentStore
18
22
  }
19
23
  }
20
24