dd-trace 5.41.1 → 5.43.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 (70) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/index.d.ts +8 -1
  3. package/package.json +7 -4
  4. package/packages/datadog-esbuild/index.js +3 -1
  5. package/packages/datadog-instrumentations/src/cucumber.js +37 -29
  6. package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +102 -0
  7. package/packages/datadog-instrumentations/src/{check_require_cache.js → helpers/check-require-cache.js} +2 -2
  8. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -2
  9. package/packages/datadog-instrumentations/src/helpers/register.js +4 -1
  10. package/packages/datadog-instrumentations/src/jest.js +72 -49
  11. package/packages/datadog-instrumentations/src/langchain.js +29 -10
  12. package/packages/datadog-instrumentations/src/mocha/main.js +53 -34
  13. package/packages/datadog-instrumentations/src/mocha/utils.js +34 -24
  14. package/packages/datadog-instrumentations/src/mocha/worker.js +7 -8
  15. package/packages/datadog-instrumentations/src/openai.js +1 -1
  16. package/packages/datadog-instrumentations/src/playwright.js +37 -30
  17. package/packages/datadog-instrumentations/src/vitest.js +83 -33
  18. package/packages/datadog-plugin-cucumber/src/index.js +13 -4
  19. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +41 -35
  20. package/packages/datadog-plugin-cypress/src/plugin.js +10 -0
  21. package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +195 -0
  22. package/packages/datadog-plugin-jest/src/index.js +18 -6
  23. package/packages/datadog-plugin-langchain/src/handlers/embedding.js +4 -1
  24. package/packages/datadog-plugin-mocha/src/index.js +13 -4
  25. package/packages/datadog-plugin-playwright/src/index.js +19 -5
  26. package/packages/datadog-plugin-vitest/src/index.js +41 -17
  27. package/packages/dd-trace/src/appsec/api_security_sampler.js +7 -3
  28. package/packages/dd-trace/src/appsec/blocking.js +23 -16
  29. package/packages/dd-trace/src/appsec/graphql.js +13 -6
  30. package/packages/dd-trace/src/appsec/rasp/utils.js +0 -1
  31. package/packages/dd-trace/src/appsec/reporter.js +35 -0
  32. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -3
  33. package/packages/dd-trace/src/appsec/telemetry/common.js +2 -1
  34. package/packages/dd-trace/src/appsec/telemetry/index.js +5 -1
  35. package/packages/dd-trace/src/appsec/telemetry/rasp.js +16 -1
  36. package/packages/dd-trace/src/appsec/telemetry/waf.js +62 -1
  37. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +43 -13
  38. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  39. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +15 -14
  40. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +1 -2
  41. package/packages/dd-trace/src/ci-visibility/telemetry.js +2 -1
  42. package/packages/dd-trace/src/ci-visibility/{quarantined-tests/get-quarantined-tests.js → test-management/get-test-management-tests.js} +5 -5
  43. package/packages/dd-trace/src/config.js +15 -1
  44. package/packages/dd-trace/src/dogstatsd.js +3 -3
  45. package/packages/dd-trace/src/encode/0.4.js +108 -12
  46. package/packages/dd-trace/src/encode/0.5.js +7 -1
  47. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -2
  48. package/packages/dd-trace/src/exporters/agent/index.js +2 -1
  49. package/packages/dd-trace/src/exporters/agent/writer.js +3 -2
  50. package/packages/dd-trace/src/format.js +34 -32
  51. package/packages/dd-trace/src/lambda/runtime/patch.js +5 -3
  52. package/packages/dd-trace/src/lambda/runtime/ritm.js +13 -18
  53. package/packages/dd-trace/src/llmobs/plugins/openai.js +27 -2
  54. package/packages/dd-trace/src/llmobs/sdk.js +3 -3
  55. package/packages/dd-trace/src/log/index.js +1 -13
  56. package/packages/dd-trace/src/log/utils.js +16 -0
  57. package/packages/dd-trace/src/opentracing/span.js +3 -0
  58. package/packages/dd-trace/src/plugins/ci_plugin.js +38 -10
  59. package/packages/dd-trace/src/plugins/index.js +1 -0
  60. package/packages/dd-trace/src/plugins/util/git.js +7 -3
  61. package/packages/dd-trace/src/plugins/util/test.js +10 -0
  62. package/packages/dd-trace/src/plugins/util/web.js +5 -2
  63. package/packages/dd-trace/src/priority_sampler.js +116 -15
  64. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +13 -14
  65. package/packages/dd-trace/src/sampler.js +9 -0
  66. package/packages/dd-trace/src/standalone/product.js +6 -2
  67. package/packages/dd-trace/src/startup-log.js +2 -1
  68. package/packages/dd-trace/src/telemetry/metrics.js +0 -8
  69. package/packages/dd-trace/src/tracer.js +1 -1
  70. /package/packages/datadog-instrumentations/src/{utils/src → helpers}/extract-package-and-module-path.js +0 -0
@@ -13,7 +13,7 @@ const testSessionFinishCh = channel('ci:playwright:session:finish')
13
13
 
14
14
  const libraryConfigurationCh = channel('ci:playwright:library-configuration')
15
15
  const knownTestsCh = channel('ci:playwright:known-tests')
16
- const quarantinedTestsCh = channel('ci:playwright:quarantined-tests')
16
+ const testManagementTestsCh = channel('ci:playwright:test-management-tests')
17
17
 
18
18
  const testSuiteStartCh = channel('ci:playwright:test-suite:start')
19
19
  const testSuiteFinishCh = channel('ci:playwright:test-suite:finish')
@@ -42,23 +42,19 @@ let earlyFlakeDetectionNumRetries = 0
42
42
  let isFlakyTestRetriesEnabled = false
43
43
  let flakyTestRetriesCount = 0
44
44
  let knownTests = {}
45
- let isQuarantinedTestsEnabled = false
46
- let quarantinedTests = {}
45
+ let isTestManagementTestsEnabled = false
46
+ let testManagementTests = {}
47
47
  let rootDir = ''
48
48
  const MINIMUM_SUPPORTED_VERSION_RANGE_EFD = '>=1.38.0'
49
49
 
50
- function isQuarantineTest (test) {
50
+ function getTestProperties (test) {
51
51
  const testName = getTestFullname(test)
52
52
  const testSuite = getTestSuitePath(test._requireFile, rootDir)
53
53
 
54
- return quarantinedTests
55
- ?.playwright
56
- ?.suites
57
- ?.[testSuite]
58
- ?.tests
59
- ?.[testName]
60
- ?.properties
61
- ?.quarantined
54
+ const { disabled, quarantined } =
55
+ testManagementTests?.playwright?.suites?.[testSuite]?.tests?.[testName]?.properties || {}
56
+
57
+ return { disabled, quarantined }
62
58
  }
63
59
 
64
60
  function isNewTest (test) {
@@ -283,7 +279,13 @@ function testBeginHandler (test, browserName) {
283
279
  const testAsyncResource = new AsyncResource('bound-anonymous-fn')
284
280
  testToAr.set(test, testAsyncResource)
285
281
  testAsyncResource.runInAsyncScope(() => {
286
- testStartCh.publish({ testName, testSuiteAbsolutePath, testSourceLine, browserName })
282
+ testStartCh.publish({
283
+ testName,
284
+ testSuiteAbsolutePath,
285
+ testSourceLine,
286
+ browserName,
287
+ isDisabled: test._ddIsDisabled
288
+ })
287
289
  })
288
290
  }
289
291
 
@@ -442,12 +444,12 @@ function runnerHook (runnerExport, playwrightVersion) {
442
444
  earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
443
445
  isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
444
446
  flakyTestRetriesCount = libraryConfig.flakyTestRetriesCount
445
- isQuarantinedTestsEnabled = libraryConfig.isQuarantinedTestsEnabled
447
+ isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
446
448
  }
447
449
  } catch (e) {
448
450
  isEarlyFlakeDetectionEnabled = false
449
451
  isKnownTestsEnabled = false
450
- isQuarantinedTestsEnabled = false
452
+ isTestManagementTestsEnabled = false
451
453
  log.error('Playwright session start error', e)
452
454
  }
453
455
 
@@ -467,17 +469,17 @@ function runnerHook (runnerExport, playwrightVersion) {
467
469
  }
468
470
  }
469
471
 
470
- if (isQuarantinedTestsEnabled && satisfies(playwrightVersion, MINIMUM_SUPPORTED_VERSION_RANGE_EFD)) {
472
+ if (isTestManagementTestsEnabled && satisfies(playwrightVersion, MINIMUM_SUPPORTED_VERSION_RANGE_EFD)) {
471
473
  try {
472
- const { err, quarantinedTests: receivedQuarantinedTests } = await getChannelPromise(quarantinedTestsCh)
474
+ const { err, testManagementTests: receivedTestManagementTests } = await getChannelPromise(testManagementTestsCh)
473
475
  if (!err) {
474
- quarantinedTests = receivedQuarantinedTests
476
+ testManagementTests = receivedTestManagementTests
475
477
  } else {
476
- isQuarantinedTestsEnabled = false
478
+ isTestManagementTestsEnabled = false
477
479
  }
478
480
  } catch (err) {
479
- isQuarantinedTestsEnabled = false
480
- log.error('Playwright quarantined tests error', err)
481
+ isTestManagementTestsEnabled = false
482
+ log.error('Playwright test management tests error', err)
481
483
  }
482
484
  }
483
485
 
@@ -513,7 +515,7 @@ function runnerHook (runnerExport, playwrightVersion) {
513
515
  testSessionFinishCh.publish({
514
516
  status: STATUS_TO_TEST_STATUS[sessionStatus],
515
517
  isEarlyFlakeDetectionEnabled,
516
- isQuarantinedTestsEnabled,
518
+ isTestManagementTestsEnabled,
517
519
  onDone
518
520
  })
519
521
  })
@@ -523,7 +525,7 @@ function runnerHook (runnerExport, playwrightVersion) {
523
525
  remainingTestsByFile = {}
524
526
 
525
527
  // TODO: we can trick playwright into thinking the session passed by returning
526
- // 'passed' here. We might be able to use this for both EFD and Quarantined tests.
528
+ // 'passed' here. We might be able to use this for both EFD and Test Management tests.
527
529
  return runAllTestsReturn
528
530
  })
529
531
 
@@ -594,19 +596,24 @@ addHook({
594
596
  const oldCreateRootSuite = loadUtilsPackage.createRootSuite
595
597
 
596
598
  async function newCreateRootSuite () {
597
- if (!isKnownTestsEnabled && !isQuarantinedTestsEnabled) {
599
+ if (!isKnownTestsEnabled && !isTestManagementTestsEnabled) {
598
600
  return oldCreateRootSuite.apply(this, arguments)
599
601
  }
600
602
  const rootSuite = await oldCreateRootSuite.apply(this, arguments)
601
603
 
602
604
  const allTests = rootSuite.allTests()
603
605
 
604
- if (isQuarantinedTestsEnabled) {
605
- const testsToBeIgnored = allTests.filter(isQuarantineTest)
606
- testsToBeIgnored.forEach(test => {
607
- test._ddIsQuarantined = true
608
- test.expectedStatus = 'skipped'
609
- })
606
+ if (isTestManagementTestsEnabled) {
607
+ for (const test of allTests) {
608
+ const testProperties = getTestProperties(test)
609
+ if (testProperties.disabled) {
610
+ test._ddIsDisabled = true
611
+ test.expectedStatus = 'skipped'
612
+ } else if (testProperties.quarantined) {
613
+ test._ddIsQuarantined = true
614
+ test.expectedStatus = 'skipped'
615
+ }
616
+ }
610
617
  }
611
618
 
612
619
  if (isKnownTestsEnabled) {
@@ -9,6 +9,7 @@ const testPassCh = channel('ci:vitest:test:pass')
9
9
  const testErrorCh = channel('ci:vitest:test:error')
10
10
  const testSkipCh = channel('ci:vitest:test:skip')
11
11
  const isNewTestCh = channel('ci:vitest:test:is-new')
12
+ const isDisabledCh = channel('ci:vitest:test:is-disabled')
12
13
  const isQuarantinedCh = channel('ci:vitest:test:is-quarantined')
13
14
 
14
15
  // test suite hooks
@@ -22,11 +23,12 @@ const testSessionFinishCh = channel('ci:vitest:session:finish')
22
23
  const libraryConfigurationCh = channel('ci:vitest:library-configuration')
23
24
  const knownTestsCh = channel('ci:vitest:known-tests')
24
25
  const isEarlyFlakeDetectionFaultyCh = channel('ci:vitest:is-early-flake-detection-faulty')
25
- const quarantinedTestsCh = channel('ci:vitest:quarantined-tests')
26
+ const testManagementTestsCh = channel('ci:vitest:test-management-tests')
26
27
 
27
28
  const taskToAsync = new WeakMap()
28
29
  const taskToStatuses = new WeakMap()
29
30
  const newTasks = new WeakSet()
31
+ const disabledTasks = new WeakSet()
30
32
  const quarantinedTasks = new WeakSet()
31
33
  let isRetryReasonEfd = false
32
34
  const switchedStatuses = new WeakSet()
@@ -50,8 +52,9 @@ function getProvidedContext () {
50
52
  _ddKnownTests: knownTests,
51
53
  _ddEarlyFlakeDetectionNumRetries: numRepeats,
52
54
  _ddIsKnownTestsEnabled: isKnownTestsEnabled,
53
- _ddIsQuarantinedTestsEnabled: isQuarantinedTestsEnabled,
54
- _ddQuarantinedTests: quarantinedTests
55
+ _ddIsTestManagementTestsEnabled: isTestManagementTestsEnabled,
56
+ _ddTestManagementTests: testManagementTests,
57
+ _ddIsFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled
55
58
  } = globalThis.__vitest_worker__.providedContext
56
59
 
57
60
  return {
@@ -60,8 +63,9 @@ function getProvidedContext () {
60
63
  knownTests,
61
64
  numRepeats,
62
65
  isKnownTestsEnabled,
63
- isQuarantinedTestsEnabled,
64
- quarantinedTests
66
+ isTestManagementTestsEnabled,
67
+ testManagementTests,
68
+ isFlakyTestRetriesEnabled
65
69
  }
66
70
  } catch (e) {
67
71
  log.error('Vitest workers could not parse provided context, so some features will not work.')
@@ -71,8 +75,8 @@ function getProvidedContext () {
71
75
  knownTests: {},
72
76
  numRepeats: 0,
73
77
  isKnownTestsEnabled: false,
74
- isQuarantinedTestsEnabled: false,
75
- quarantinedTests: {}
78
+ isTestManagementTestsEnabled: false,
79
+ testManagementTests: {}
76
80
  }
77
81
  }
78
82
  }
@@ -90,6 +94,10 @@ function isReporterPackageNewest (vitestPackage) {
90
94
  return vitestPackage.h?.name === 'BaseSequencer'
91
95
  }
92
96
 
97
+ function isBaseSequencer (vitestPackage) {
98
+ return vitestPackage.b?.name === 'BaseSequencer'
99
+ }
100
+
93
101
  function getChannelPromise (channelToPublishTo) {
94
102
  return new Promise(resolve => {
95
103
  sessionAsyncResource.runInAsyncScope(() => {
@@ -167,10 +175,10 @@ function getSortWrapper (sort) {
167
175
  let earlyFlakeDetectionNumRetries = 0
168
176
  let isEarlyFlakeDetectionFaulty = false
169
177
  let isKnownTestsEnabled = false
170
- let isQuarantinedTestsEnabled = false
178
+ let isTestManagementTestsEnabled = false
171
179
  let isDiEnabled = false
172
180
  let knownTests = {}
173
- let quarantinedTests = {}
181
+ let testManagementTests = {}
174
182
 
175
183
  try {
176
184
  const { err, libraryConfig } = await getChannelPromise(libraryConfigurationCh)
@@ -181,7 +189,7 @@ function getSortWrapper (sort) {
181
189
  earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
182
190
  isDiEnabled = libraryConfig.isDiEnabled
183
191
  isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
184
- isQuarantinedTestsEnabled = libraryConfig.isQuarantinedTestsEnabled
192
+ isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
185
193
  }
186
194
  } catch (e) {
187
195
  isFlakyTestRetriesEnabled = false
@@ -192,6 +200,12 @@ function getSortWrapper (sort) {
192
200
 
193
201
  if (isFlakyTestRetriesEnabled && !this.ctx.config.retry && flakyTestRetriesCount > 0) {
194
202
  this.ctx.config.retry = flakyTestRetriesCount
203
+ try {
204
+ const workspaceProject = this.ctx.getCoreWorkspaceProject()
205
+ workspaceProject._provided._ddIsFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
206
+ } catch (e) {
207
+ log.warn('Could not send library configuration to workers.')
208
+ }
195
209
  }
196
210
 
197
211
  if (isKnownTestsEnabled) {
@@ -241,20 +255,20 @@ function getSortWrapper (sort) {
241
255
  }
242
256
  }
243
257
 
244
- if (isQuarantinedTestsEnabled) {
245
- const { err, quarantinedTests: receivedQuarantinedTests } = await getChannelPromise(quarantinedTestsCh)
258
+ if (isTestManagementTestsEnabled) {
259
+ const { err, testManagementTests: receivedTestManagementTests } = await getChannelPromise(testManagementTestsCh)
246
260
  if (!err) {
247
- quarantinedTests = receivedQuarantinedTests
261
+ testManagementTests = receivedTestManagementTests
248
262
  try {
249
263
  const workspaceProject = this.ctx.getCoreWorkspaceProject()
250
- workspaceProject._provided._ddIsQuarantinedTestsEnabled = isQuarantinedTestsEnabled
251
- workspaceProject._provided._ddQuarantinedTests = quarantinedTests
264
+ workspaceProject._provided._ddIsTestManagementTestsEnabled = isTestManagementTestsEnabled
265
+ workspaceProject._provided._ddTestManagementTests = testManagementTests
252
266
  } catch (e) {
253
- log.warn('Could not send quarantined tests to workers so Quarantine will not work.')
267
+ log.warn('Could not send test management tests to workers so Test Management will not work.')
254
268
  }
255
269
  } else {
256
- isQuarantinedTestsEnabled = false
257
- log.error('Could not get quarantined tests.')
270
+ isTestManagementTestsEnabled = false
271
+ log.error('Could not get test management tests.')
258
272
  }
259
273
  }
260
274
 
@@ -292,7 +306,7 @@ function getSortWrapper (sort) {
292
306
  error,
293
307
  isEarlyFlakeDetectionEnabled,
294
308
  isEarlyFlakeDetectionFaulty,
295
- isQuarantinedTestsEnabled,
309
+ isTestManagementTestsEnabled,
296
310
  onFinish
297
311
  })
298
312
  })
@@ -337,9 +351,25 @@ addHook({
337
351
  knownTests,
338
352
  isEarlyFlakeDetectionEnabled,
339
353
  isKnownTestsEnabled,
340
- numRepeats
354
+ numRepeats,
355
+ isTestManagementTestsEnabled,
356
+ testManagementTests
341
357
  } = getProvidedContext()
342
358
 
359
+ if (isTestManagementTestsEnabled) {
360
+ isDisabledCh.publish({
361
+ testManagementTests,
362
+ testSuiteAbsolutePath: task.file.filepath,
363
+ testName,
364
+ onDone: (isTestDisabled) => {
365
+ if (isTestDisabled) {
366
+ disabledTasks.add(task)
367
+ task.mode = 'skip'
368
+ }
369
+ }
370
+ })
371
+ }
372
+
343
373
  if (isKnownTestsEnabled) {
344
374
  isNewTestCh.publish({
345
375
  knownTests,
@@ -364,7 +394,7 @@ addHook({
364
394
  // `onAfterRunTask` is run after all repetitions or attempts are run
365
395
  // `onAfterRunTask` is an async function
366
396
  shimmer.wrap(VitestTestRunner.prototype, 'onAfterRunTask', onAfterRunTask => function (task) {
367
- const { isEarlyFlakeDetectionEnabled, isQuarantinedTestsEnabled } = getProvidedContext()
397
+ const { isEarlyFlakeDetectionEnabled, isTestManagementTestsEnabled } = getProvidedContext()
368
398
 
369
399
  if (isEarlyFlakeDetectionEnabled && taskToStatuses.has(task)) {
370
400
  const statuses = taskToStatuses.get(task)
@@ -377,7 +407,7 @@ addHook({
377
407
  }
378
408
  }
379
409
 
380
- if (isQuarantinedTestsEnabled) {
410
+ if (isTestManagementTestsEnabled) {
381
411
  if (quarantinedTasks.has(task)) {
382
412
  task.result.state = 'pass'
383
413
  }
@@ -400,17 +430,17 @@ addHook({
400
430
  isKnownTestsEnabled,
401
431
  isEarlyFlakeDetectionEnabled,
402
432
  isDiEnabled,
403
- isQuarantinedTestsEnabled,
404
- quarantinedTests
433
+ isTestManagementTestsEnabled,
434
+ testManagementTests
405
435
  } = getProvidedContext()
406
436
 
407
437
  if (isKnownTestsEnabled) {
408
438
  isNew = newTasks.has(task)
409
439
  }
410
440
 
411
- if (isQuarantinedTestsEnabled) {
441
+ if (isTestManagementTestsEnabled) {
412
442
  isQuarantinedCh.publish({
413
- quarantinedTests,
443
+ testManagementTests,
414
444
  testSuiteAbsolutePath: task.file.filepath,
415
445
  testName,
416
446
  onDone: (isTestQuarantined) => {
@@ -589,11 +619,22 @@ addHook({
589
619
 
590
620
  addHook({
591
621
  name: 'vitest',
592
- versions: ['>=3.0.0'],
622
+ versions: ['>=3.0.9'],
623
+ filePattern: 'dist/chunks/coverage.*'
624
+ }, (coveragePackage) => {
625
+ if (isBaseSequencer(coveragePackage)) {
626
+ shimmer.wrap(coveragePackage.b.prototype, 'sort', getSortWrapper)
627
+ }
628
+ return coveragePackage
629
+ })
630
+
631
+ addHook({
632
+ name: 'vitest',
633
+ versions: ['>=3.0.0 <3.0.9'],
593
634
  filePattern: 'dist/chunks/resolveConfig.*'
594
- }, (randomSequencerPackage) => {
595
- shimmer.wrap(randomSequencerPackage.B.prototype, 'sort', getSortWrapper)
596
- return randomSequencerPackage
635
+ }, (resolveConfigPackage) => {
636
+ shimmer.wrap(resolveConfigPackage.B.prototype, 'sort', getSortWrapper)
637
+ return resolveConfigPackage
597
638
  })
598
639
 
599
640
  // Can't specify file because compiled vitest includes hashes in their files
@@ -624,9 +665,16 @@ addHook({
624
665
  // From >=3.0.1, the first arguments changes from a string to an object containing the filepath
625
666
  const testSuiteAbsolutePath = testPaths[0]?.filepath || testPaths[0]
626
667
 
668
+ const { isEarlyFlakeDetectionEnabled, isFlakyTestRetriesEnabled } = getProvidedContext()
669
+
627
670
  const testSuiteAsyncResource = new AsyncResource('bound-anonymous-fn')
628
671
  testSuiteAsyncResource.runInAsyncScope(() => {
629
- testSuiteStartCh.publish({ testSuiteAbsolutePath, frameworkVersion })
672
+ testSuiteStartCh.publish({
673
+ testSuiteAbsolutePath,
674
+ frameworkVersion,
675
+ isFlakyTestRetriesEnabled,
676
+ isEarlyFlakeDetectionEnabled
677
+ })
630
678
  })
631
679
  const startTestsResponse = await startTests.apply(this, arguments)
632
680
 
@@ -651,7 +699,8 @@ addHook({
651
699
  testSkipCh.publish({
652
700
  testName: getTestName(task),
653
701
  testSuiteAbsolutePath: task.file.filepath,
654
- isNew: newTasks.has(task)
702
+ isNew: newTasks.has(task),
703
+ isDisabled: disabledTasks.has(task)
655
704
  })
656
705
  } else if (state === 'pass' && !isSwitchedStatus) {
657
706
  if (testAsyncResource) {
@@ -681,7 +730,8 @@ addHook({
681
730
  testSkipCh.publish({
682
731
  testName: getTestName(task),
683
732
  testSuiteAbsolutePath: task.file.filepath,
684
- isNew: newTasks.has(task)
733
+ isNew: newTasks.has(task),
734
+ isDisabled: disabledTasks.has(task)
685
735
  })
686
736
  }
687
737
  })
@@ -29,7 +29,8 @@ const {
29
29
  CUCUMBER_IS_PARALLEL,
30
30
  TEST_RETRY_REASON,
31
31
  TEST_MANAGEMENT_ENABLED,
32
- TEST_MANAGEMENT_IS_QUARANTINED
32
+ TEST_MANAGEMENT_IS_QUARANTINED,
33
+ TEST_MANAGEMENT_IS_DISABLED
33
34
  } = require('../../dd-trace/src/plugins/util/test')
34
35
  const { RESOURCE_NAME } = require('../../../ext/tags')
35
36
  const { COMPONENT, ERROR_MESSAGE } = require('../../dd-trace/src/constants')
@@ -86,7 +87,7 @@ class CucumberPlugin extends CiPlugin {
86
87
  hasForcedToRunSuites,
87
88
  isEarlyFlakeDetectionEnabled,
88
89
  isEarlyFlakeDetectionFaulty,
89
- isQuarantinedTestsEnabled,
90
+ isTestManagementTestsEnabled,
90
91
  isParallel
91
92
  }) => {
92
93
  const { isSuitesSkippingEnabled, isCodeCoverageEnabled } = this.libraryConfig || {}
@@ -113,7 +114,7 @@ class CucumberPlugin extends CiPlugin {
113
114
  if (isParallel) {
114
115
  this.testSessionSpan.setTag(CUCUMBER_IS_PARALLEL, 'true')
115
116
  }
116
- if (isQuarantinedTestsEnabled) {
117
+ if (isTestManagementTestsEnabled) {
117
118
  this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
118
119
  }
119
120
 
@@ -124,7 +125,10 @@ class CucumberPlugin extends CiPlugin {
124
125
  this.testSessionSpan.finish()
125
126
  this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
126
127
  finishAllTraceSpans(this.testSessionSpan)
127
- this.telemetry.count(TELEMETRY_TEST_SESSION, { provider: this.ciProviderName })
128
+ this.telemetry.count(TELEMETRY_TEST_SESSION, {
129
+ provider: this.ciProviderName,
130
+ autoInjected: !!process.env.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER
131
+ })
128
132
 
129
133
  this.libraryConfig = null
130
134
  this.tracer._exporter.flush()
@@ -324,6 +328,7 @@ class CucumberPlugin extends CiPlugin {
324
328
  isNew,
325
329
  isEfdRetry,
326
330
  isFlakyRetry,
331
+ isDisabled,
327
332
  isQuarantined
328
333
  }) => {
329
334
  const span = storage('legacy').getStore().span
@@ -353,6 +358,10 @@ class CucumberPlugin extends CiPlugin {
353
358
  span.setTag(TEST_IS_RETRY, 'true')
354
359
  }
355
360
 
361
+ if (isDisabled) {
362
+ span.setTag(TEST_MANAGEMENT_IS_DISABLED, 'true')
363
+ }
364
+
356
365
  if (isQuarantined) {
357
366
  span.setTag(TEST_MANAGEMENT_IS_QUARANTINED, 'true')
358
367
  }
@@ -35,7 +35,11 @@ const {
35
35
  TEST_RETRY_REASON,
36
36
  DD_TEST_IS_USER_PROVIDED_SERVICE,
37
37
  TEST_MANAGEMENT_IS_QUARANTINED,
38
- TEST_MANAGEMENT_ENABLED
38
+ TEST_MANAGEMENT_ENABLED,
39
+ TEST_MANAGEMENT_IS_DISABLED,
40
+ DD_CAPABILITIES_EARLY_FLAKE_DETECTION,
41
+ DD_CAPABILITIES_AUTO_TEST_RETRIES,
42
+ DD_CAPABILITIES_TEST_IMPACT_ANALYSIS
39
43
  } = require('../../dd-trace/src/plugins/util/test')
40
44
  const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
41
45
  const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
@@ -154,15 +158,15 @@ function getKnownTests (tracer, testConfiguration) {
154
158
  })
155
159
  }
156
160
 
157
- function getQuarantinedTests (tracer, testConfiguration) {
161
+ function getTestManagementTests (tracer, testConfiguration) {
158
162
  return new Promise(resolve => {
159
- if (!tracer._tracer._exporter?.getQuarantinedTests) {
163
+ if (!tracer._tracer._exporter?.getTestManagementTests) {
160
164
  return resolve({ err: new Error('Test Optimization was not initialized correctly') })
161
165
  }
162
- tracer._tracer._exporter.getQuarantinedTests(testConfiguration, (err, quarantinedTests) => {
166
+ tracer._tracer._exporter.getTestManagementTests(testConfiguration, (err, testManagementTests) => {
163
167
  resolve({
164
168
  err,
165
- quarantinedTests
169
+ testManagementTests
166
170
  })
167
171
  })
168
172
  })
@@ -257,7 +261,7 @@ class CypressPlugin {
257
261
  isFlakyTestRetriesEnabled,
258
262
  flakyTestRetriesCount,
259
263
  isKnownTestsEnabled,
260
- isQuarantinedTestsEnabled
264
+ isTestManagementEnabled
261
265
  }
262
266
  } = libraryConfigurationResponse
263
267
  this.isSuitesSkippingEnabled = isSuitesSkippingEnabled
@@ -268,22 +272,18 @@ class CypressPlugin {
268
272
  if (isFlakyTestRetriesEnabled) {
269
273
  this.cypressConfig.retries.runMode = flakyTestRetriesCount
270
274
  }
271
- this.isQuarantinedTestsEnabled = isQuarantinedTestsEnabled
275
+ this.isTestManagementTestsEnabled = isTestManagementEnabled
272
276
  }
273
277
  return this.cypressConfig
274
278
  })
275
279
  return this.libraryConfigurationPromise
276
280
  }
277
281
 
278
- getIsQuarantinedTest (testSuite, testName) {
279
- return this.quarantinedTests
280
- ?.cypress
281
- ?.suites
282
- ?.[testSuite]
283
- ?.tests
284
- ?.[testName]
285
- ?.properties
286
- ?.quarantined
282
+ getTestProperties (testSuite, testName) {
283
+ const { disabled: isDisabled, quarantined: isQuarantined } =
284
+ this.testManagementTests?.cypress?.suites?.[testSuite]?.tests?.[testName]?.properties || {}
285
+
286
+ return { isDisabled, isQuarantined }
287
287
  }
288
288
 
289
289
  getTestSuiteSpan ({ testSuite, testSuiteAbsolutePath }) {
@@ -418,16 +418,16 @@ class CypressPlugin {
418
418
  }
419
419
  }
420
420
 
421
- if (this.isQuarantinedTestsEnabled) {
422
- const quarantinedTestsResponse = await getQuarantinedTests(
421
+ if (this.isTestManagementTestsEnabled) {
422
+ const testManagementTestsResponse = await getTestManagementTests(
423
423
  this.tracer,
424
424
  this.testConfiguration
425
425
  )
426
- if (quarantinedTestsResponse.err) {
427
- log.error('Cypress quarantined tests response error', quarantinedTestsResponse.err)
428
- this.isQuarantinedTestsEnabled = false
426
+ if (testManagementTestsResponse.err) {
427
+ log.error('Cypress test management tests response error', testManagementTestsResponse.err)
428
+ this.isTestManagementTestsEnabled = false
429
429
  } else {
430
- this.quarantinedTests = quarantinedTestsResponse.quarantinedTests
430
+ this.testManagementTests = testManagementTestsResponse.testManagementTests
431
431
  }
432
432
  }
433
433
 
@@ -452,14 +452,21 @@ class CypressPlugin {
452
452
 
453
453
  const testSessionName = getTestSessionName(this.tracer._tracer._config, this.command, this.testEnvironmentMetadata)
454
454
 
455
- if (this.tracer._tracer._exporter?.setMetadataTags) {
455
+ if (this.tracer._tracer._exporter?.addMetadataTags) {
456
456
  const metadataTags = {}
457
457
  for (const testLevel of TEST_LEVEL_EVENT_TYPES) {
458
458
  metadataTags[testLevel] = {
459
459
  [TEST_SESSION_NAME]: testSessionName
460
460
  }
461
461
  }
462
- this.tracer._tracer._exporter.setMetadataTags(metadataTags)
462
+ metadataTags.test = {
463
+ ...metadataTags.test,
464
+ [DD_CAPABILITIES_TEST_IMPACT_ANALYSIS]: this.isSuitesSkippingEnabled ? 'true' : 'false',
465
+ [DD_CAPABILITIES_EARLY_FLAKE_DETECTION]: this.isEarlyFlakeDetectionEnabled ? 'true' : 'false',
466
+ [DD_CAPABILITIES_AUTO_TEST_RETRIES]: this.isFlakyTestRetriesEnabled ? 'true' : 'false'
467
+ }
468
+
469
+ this.tracer._tracer._exporter.addMetadataTags(metadataTags)
463
470
  }
464
471
 
465
472
  this.testSessionSpan = this.tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_session`, {
@@ -509,7 +516,7 @@ class CypressPlugin {
509
516
  }
510
517
  )
511
518
 
512
- if (this.isQuarantinedTestsEnabled) {
519
+ if (this.isTestManagementTestsEnabled) {
513
520
  this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
514
521
  }
515
522
 
@@ -518,7 +525,8 @@ class CypressPlugin {
518
525
  this.testSessionSpan.finish()
519
526
  this.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
520
527
  incrementCountMetric(TELEMETRY_TEST_SESSION, {
521
- provider: this.ciProviderName
528
+ provider: this.ciProviderName,
529
+ autoInjected: !!process.env.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER
522
530
  })
523
531
 
524
532
  finishAllTraceSpans(this.testSessionSpan)
@@ -588,9 +596,11 @@ class CypressPlugin {
588
596
  skippedTestSpan.setTag(ITR_CORRELATION_ID, this.itrCorrelationId)
589
597
  }
590
598
 
591
- const isQuarantined = this.getIsQuarantinedTest(spec.relative, cypressTestName)
599
+ const { isDisabled, isQuarantined } = this.getTestProperties(spec.relative, cypressTestName)
592
600
 
593
- if (isQuarantined) {
601
+ if (isDisabled) {
602
+ skippedTestSpan.setTag(TEST_MANAGEMENT_IS_DISABLED, 'true')
603
+ } else if (isQuarantined) {
594
604
  skippedTestSpan.setTag(TEST_MANAGEMENT_IS_QUARANTINED, 'true')
595
605
  }
596
606
 
@@ -697,7 +707,7 @@ class CypressPlugin {
697
707
  })
698
708
  const isUnskippable = this.unskippableSuites.includes(testSuite)
699
709
  const isForcedToRun = shouldSkip && isUnskippable
700
- const isQuarantined = this.getIsQuarantinedTest(testSuite, testName)
710
+ const { isDisabled, isQuarantined } = this.getTestProperties(testSuite, testName)
701
711
 
702
712
  // skip test
703
713
  if (shouldSkip && !isUnskippable) {
@@ -708,7 +718,7 @@ class CypressPlugin {
708
718
 
709
719
  // TODO: I haven't found a way to trick cypress into ignoring a test
710
720
  // The way we'll implement quarantine in cypress is by skipping the test altogether
711
- if (isQuarantined) {
721
+ if (isDisabled || isQuarantined) {
712
722
  return { shouldSkip: true }
713
723
  }
714
724
 
@@ -737,8 +747,7 @@ class CypressPlugin {
737
747
  testSuiteAbsolutePath,
738
748
  testName,
739
749
  isNew,
740
- isEfdRetry,
741
- isQuarantined
750
+ isEfdRetry
742
751
  } = test
743
752
  if (coverage && this.isCodeCoverageEnabled && this.tracer._tracer._exporter?.exportCoverage) {
744
753
  const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
@@ -777,9 +786,6 @@ class CypressPlugin {
777
786
  this.activeTestSpan.setTag(TEST_RETRY_REASON, 'efd')
778
787
  }
779
788
  }
780
- if (isQuarantined) {
781
- this.activeTestSpan.setTag(TEST_MANAGEMENT_IS_QUARANTINED, 'true')
782
- }
783
789
  const finishedTest = {
784
790
  testName,
785
791
  testStatus,
@@ -1,5 +1,6 @@
1
1
  const NoopTracer = require('../../dd-trace/src/noop/tracer')
2
2
  const cypressPlugin = require('./cypress-plugin')
3
+ const satisfies = require('semifies')
3
4
 
4
5
  const noopTask = {
5
6
  'dd:testSuiteStart': () => {
@@ -19,6 +20,15 @@ const noopTask = {
19
20
  module.exports = (on, config) => {
20
21
  const tracer = require('../../dd-trace')
21
22
 
23
+ if (satisfies(config.version, '<10.2.0')) {
24
+ // console.warn does not seem to work in cypress, so using console.log instead
25
+ // eslint-disable-next-line no-console
26
+ console.log(
27
+ 'WARNING: dd-trace support for Cypress<10.2.0 is deprecated' +
28
+ ' and will not be supported in future versions of dd-trace.'
29
+ )
30
+ }
31
+
22
32
  // The tracer was not init correctly for whatever reason (such as invalid DD_SITE)
23
33
  if (tracer._tracer instanceof NoopTracer) {
24
34
  // We still need to register these tasks or the support file will fail