dd-trace 6.7.0 → 6.8.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 (147) hide show
  1. package/ci/test-optimization-validation/command-output-policy.js +5 -5
  2. package/ci/test-optimization-validation/framework-adapters/playwright.js +5 -5
  3. package/ci/test-optimization-validation/generated-files.js +9 -9
  4. package/ci/test-optimization-validation/generated-test-contract.js +1 -3
  5. package/ci/test-optimization-validation/manifest-scaffold.js +1 -2
  6. package/ci/test-optimization-validation/offline-output.js +6 -6
  7. package/ci/test-optimization-validation/runner-command.js +1 -1
  8. package/ci/test-optimization-validation/safe-files.js +4 -4
  9. package/ci/test-optimization-validation/scenarios/basic-reporting.js +1 -1
  10. package/ci/test-optimization-validation/scenarios/test-management.js +2 -2
  11. package/ci/vitest-no-worker-init-setup.mjs +348 -51
  12. package/index.d.ts +77 -13
  13. package/package.json +9 -3
  14. package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
  15. package/packages/datadog-esbuild/index.js +4 -2
  16. package/packages/datadog-esbuild/src/utils.js +1 -1
  17. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +4 -4
  18. package/packages/datadog-instrumentations/src/cucumber.js +9 -6
  19. package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
  20. package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
  21. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  22. package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
  23. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +1 -0
  24. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  25. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +57 -0
  26. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
  27. package/packages/datadog-instrumentations/src/helpers/router-helper.js +1 -1
  28. package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
  29. package/packages/datadog-instrumentations/src/http/client.js +1 -3
  30. package/packages/datadog-instrumentations/src/jest.js +8 -14
  31. package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
  32. package/packages/datadog-instrumentations/src/mocha/main.js +2 -42
  33. package/packages/datadog-instrumentations/src/mocha/utils.js +68 -2
  34. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +19 -0
  35. package/packages/datadog-instrumentations/src/mocha/worker.js +446 -42
  36. package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
  37. package/packages/datadog-instrumentations/src/playwright.js +3 -2
  38. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  39. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +525 -56
  40. package/packages/datadog-instrumentations/src/vitest-main.js +90 -10
  41. package/packages/datadog-instrumentations/src/webdriverio.js +914 -0
  42. package/packages/datadog-plugin-aerospike/src/index.js +1 -3
  43. package/packages/datadog-plugin-amqplib/src/client.js +1 -1
  44. package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
  45. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  46. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
  47. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
  48. package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
  49. package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
  50. package/packages/datadog-plugin-child_process/src/index.js +3 -3
  51. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +5 -8
  52. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
  53. package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
  54. package/packages/datadog-plugin-fs/src/index.js +0 -4
  55. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
  56. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
  57. package/packages/datadog-plugin-graphql/src/execute.js +1 -0
  58. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
  59. package/packages/datadog-plugin-http/src/client.js +2 -1
  60. package/packages/datadog-plugin-jest/src/index.js +2 -3
  61. package/packages/datadog-plugin-jest/src/util.js +2 -1
  62. package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
  63. package/packages/datadog-plugin-mocha/src/index.js +25 -6
  64. package/packages/datadog-plugin-prisma/src/index.js +5 -1
  65. package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
  66. package/packages/datadog-plugin-rhea/src/producer.js +1 -1
  67. package/packages/datadog-plugin-undici/src/index.js +2 -1
  68. package/packages/datadog-plugin-vitest/src/index.js +84 -11
  69. package/packages/datadog-webpack/index.js +2 -2
  70. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
  71. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
  72. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
  73. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  74. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
  75. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  76. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
  77. package/packages/dd-trace/src/appsec/sdk/track_event.js +1 -1
  78. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  79. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
  80. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -2
  81. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -1
  82. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -0
  83. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
  84. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
  85. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
  86. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +1 -1
  87. package/packages/dd-trace/src/config/defaults.js +14 -6
  88. package/packages/dd-trace/src/config/generated-config-types.d.ts +2 -2
  89. package/packages/dd-trace/src/config/index.js +15 -0
  90. package/packages/dd-trace/src/config/parsers.js +19 -1
  91. package/packages/dd-trace/src/config/supported-configurations.json +5 -6
  92. package/packages/dd-trace/src/datastreams/encoding.js +3 -4
  93. package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
  94. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
  95. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
  96. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
  97. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
  98. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  99. package/packages/dd-trace/src/exporters/common/url.js +3 -5
  100. package/packages/dd-trace/src/exporters/electron/index.js +4 -1
  101. package/packages/dd-trace/src/external-logger/src/index.js +1 -2
  102. package/packages/dd-trace/src/flare/index.js +2 -2
  103. package/packages/dd-trace/src/id.js +1 -1
  104. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
  105. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
  106. package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
  107. package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
  108. package/packages/dd-trace/src/llmobs/experiments/index.js +51 -12
  109. package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
  110. package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
  111. package/packages/dd-trace/src/llmobs/experiments/util.js +218 -0
  112. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
  113. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
  114. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
  115. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
  116. package/packages/dd-trace/src/llmobs/sdk.js +4 -11
  117. package/packages/dd-trace/src/llmobs/span_processor.js +9 -7
  118. package/packages/dd-trace/src/llmobs/tagger.js +1 -2
  119. package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
  120. package/packages/dd-trace/src/noop/proxy.js +2 -2
  121. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  122. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
  123. package/packages/dd-trace/src/opentracing/span.js +1 -1
  124. package/packages/dd-trace/src/opentracing/span_context.js +1 -1
  125. package/packages/dd-trace/src/plugins/ci_plugin.js +105 -20
  126. package/packages/dd-trace/src/plugins/index.js +1 -0
  127. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  128. package/packages/dd-trace/src/plugins/tracing.js +1 -0
  129. package/packages/dd-trace/src/plugins/util/ci.js +7 -6
  130. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  131. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +1 -1
  132. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  133. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  134. package/packages/dd-trace/src/plugins/util/test.js +38 -12
  135. package/packages/dd-trace/src/plugins/util/url.js +5 -5
  136. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  137. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  138. package/packages/dd-trace/src/priority_sampler.js +6 -3
  139. package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
  140. package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
  141. package/packages/dd-trace/src/ritm.js +5 -20
  142. package/packages/dd-trace/src/startup-log.js +3 -0
  143. package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
  144. package/packages/dd-trace/src/util.js +16 -0
  145. package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
  146. package/vendor/dist/pprof-format/index.js +1 -1
  147. package/vendor/dist/source-map/index.js +1 -1
@@ -48,12 +48,16 @@ const {
48
48
  CI_APP_ORIGIN,
49
49
  getTestSessionCommonTags,
50
50
  getTestModuleCommonTags,
51
+ TEST_FRAMEWORK,
52
+ TEST_FRAMEWORK_ADAPTER,
53
+ TEST_FRAMEWORK_VERSION,
51
54
  TEST_SUITE_ID,
52
55
  TEST_MODULE_ID,
53
56
  TEST_SESSION_ID,
54
57
  TEST_COMMAND,
55
58
  TEST_LEVELS_METADATA,
56
59
  TEST_MODULE,
60
+ TEST_TYPE,
57
61
  TEST_SESSION_NAME,
58
62
  getTestSuiteCommonTags,
59
63
  TEST_STATUS,
@@ -62,6 +66,8 @@ const {
62
66
  ITR_CORRELATION_ID,
63
67
  TEST_SOURCE_FILE,
64
68
  TEST_SUITE,
69
+ TEST_SUITE_EXECUTION_ID,
70
+ getTestSuiteExecutionKey,
65
71
  getFileAndLineNumberFromError,
66
72
  DI_ERROR_DEBUG_INFO_CAPTURED,
67
73
  DI_DEBUG_ERROR_PREFIX,
@@ -101,6 +107,7 @@ const FRAMEWORK_TO_TRIMMED_COMMAND = {
101
107
  cucumber: 'cucumber-js',
102
108
  playwright: 'playwright test',
103
109
  jest: 'jest',
110
+ webdriverio: 'wdio',
104
111
  }
105
112
 
106
113
  const WORKER_EXPORTER_TO_TEST_FRAMEWORK = {
@@ -131,7 +138,8 @@ function withTimeout (promise, timeoutMs) {
131
138
  }
132
139
 
133
140
  function setItrSkippingEnabledTagFromLibraryConfig (plugin, frameworkVersion) {
134
- const libraryCapabilitiesTags = getDefaultLibraryCapabilitiesTags(plugin.constructor.id, frameworkVersion)
141
+ const testFramework = plugin.testFramework || plugin.constructor.id
142
+ const libraryCapabilitiesTags = getDefaultLibraryCapabilitiesTags(testFramework, frameworkVersion)
135
143
 
136
144
  if (!libraryCapabilitiesTags[DD_CAPABILITIES_TEST_IMPACT_ANALYSIS] ||
137
145
  !plugin.libraryConfig ||
@@ -160,6 +168,22 @@ function getTestSuiteLevelVisibilityTags (testSuiteSpan, testFramework) {
160
168
  return suiteTags
161
169
  }
162
170
 
171
+ /**
172
+ * Keeps non-TIA settings while disabling suite skipping and coverage collection.
173
+ *
174
+ * @param {object} libraryConfig
175
+ * @returns {object}
176
+ */
177
+ function disableTestImpactAnalysis (libraryConfig) {
178
+ return Object.freeze({
179
+ ...libraryConfig,
180
+ isCodeCoverageEnabled: false,
181
+ isCoverageReportUploadEnabled: false,
182
+ isItrEnabled: false,
183
+ isSuitesSkippingEnabled: false,
184
+ })
185
+ }
186
+
163
187
  module.exports = class CiPlugin extends Plugin {
164
188
  constructor (...args) {
165
189
  super(...args)
@@ -170,16 +194,32 @@ module.exports = class CiPlugin extends Plugin {
170
194
  this.rootDir = process.cwd() // fallback in case :session:start events are not emitted
171
195
  this._testSuiteSpansByTestSuite = new Map()
172
196
  this._pendingWorkerTracesByTestSuite = new Map()
197
+ this._workerTraceExecutionIds = new WeakMap()
173
198
  this._pendingRequestErrorTags = []
174
199
 
175
200
  this.addSub(`ci:${this.constructor.id}:library-configuration`, (ctx) => {
176
- const { onDone, frameworkVersion } = ctx
201
+ const {
202
+ basicReportingOnly,
203
+ disableTestImpactAnalysis: shouldDisableTestImpactAnalysis,
204
+ onDone,
205
+ frameworkVersion,
206
+ } = ctx
177
207
  ctx.currentStore = legacyStorage.getStore()
178
208
 
179
209
  if (!this.tracer._exporter || !this.tracer._exporter.getLibraryConfiguration) {
180
210
  return onDone({ err: new Error('Test optimization was not initialized correctly') })
181
211
  }
182
212
  this.tracer._exporter.getLibraryConfiguration(this.testConfiguration, (err, libraryConfig) => {
213
+ let effectiveLibraryConfig
214
+ if (!err) {
215
+ if (basicReportingOnly) {
216
+ effectiveLibraryConfig = {}
217
+ } else if (shouldDisableTestImpactAnalysis) {
218
+ effectiveLibraryConfig = disableTestImpactAnalysis(libraryConfig)
219
+ } else {
220
+ effectiveLibraryConfig = libraryConfig
221
+ }
222
+ }
183
223
  if (err) {
184
224
  this.libraryConfig = undefined
185
225
  this.itrCorrelationId = undefined
@@ -187,7 +227,7 @@ module.exports = class CiPlugin extends Plugin {
187
227
  log.error('Library configuration could not be fetched. %s', err.message)
188
228
  this._addRequestErrorTag(DD_CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS, err)
189
229
  } else {
190
- this.libraryConfig = libraryConfig
230
+ this.libraryConfig = effectiveLibraryConfig
191
231
  setItrSkippingEnabledTagFromLibraryConfig(this, frameworkVersion)
192
232
  }
193
233
 
@@ -201,7 +241,7 @@ module.exports = class CiPlugin extends Plugin {
201
241
  onDone({
202
242
  err,
203
243
  isTestDynamicInstrumentationEnabled: this.config.isTestDynamicInstrumentationEnabled,
204
- libraryConfig,
244
+ libraryConfig: effectiveLibraryConfig,
205
245
  repositoryRoot: this.repositoryRoot,
206
246
  requestErrorTags: this._getCurrentRequestErrorTags(),
207
247
  })
@@ -234,19 +274,28 @@ module.exports = class CiPlugin extends Plugin {
234
274
  )
235
275
  })
236
276
 
237
- this.addSub(`ci:${this.constructor.id}:session:start`, ({ command, frameworkVersion, rootDir }) => {
277
+ this.addSub(`ci:${this.constructor.id}:session:start`, ({
278
+ command,
279
+ frameworkVersion,
280
+ rootDir,
281
+ testFramework,
282
+ testFrameworkAdapter,
283
+ }) => {
284
+ const effectiveTestFramework = testFramework || this.constructor.id
238
285
  const childOf = getTestParentSpan(this.tracer)
239
- const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion, this.constructor.id)
240
- const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion, this.constructor.id)
286
+ const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion, effectiveTestFramework)
287
+ const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion, effectiveTestFramework)
241
288
 
242
289
  this.command = command
243
290
  this.frameworkVersion = frameworkVersion
291
+ this.testFramework = effectiveTestFramework
292
+ this.testFrameworkAdapter = testFrameworkAdapter
244
293
  // only for playwright
245
294
  this.rootDir = rootDir
246
295
 
247
296
  const testSessionName = getTestSessionName(
248
297
  this.config,
249
- DD_MAJOR < 6 ? this.command : FRAMEWORK_TO_TRIMMED_COMMAND[this.constructor.id],
298
+ DD_MAJOR < 6 ? this.command : FRAMEWORK_TO_TRIMMED_COMMAND[effectiveTestFramework],
250
299
  this.testEnvironmentMetadata
251
300
  )
252
301
 
@@ -296,7 +345,7 @@ module.exports = class CiPlugin extends Plugin {
296
345
  const testCommand = this.command
297
346
  for (const testSuite of skippedSuites) {
298
347
  const testSuiteMetadata = {
299
- ...getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, this.constructor.id),
348
+ ...getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, this.testFramework),
300
349
  ...getSessionRequestErrorTags(this.testSessionSpan),
301
350
  ...getSessionItrSkippingEnabledTags(this.testSessionSpan),
302
351
  }
@@ -392,10 +441,16 @@ module.exports = class CiPlugin extends Plugin {
392
441
  return onDone({ err: new Error('No modified tests could have been retrieved') })
393
442
  })
394
443
 
395
- this.addSub(`ci:${this.constructor.id}:worker-report:trace`, traces => {
444
+ this.addSub(`ci:${this.constructor.id}:worker-report:trace`, payload => {
445
+ const { traces, [TEST_SUITE_EXECUTION_ID]: testSuiteExecutionId } = typeof payload === 'string'
446
+ ? { traces: payload }
447
+ : payload
396
448
  const formattedTraces = JSON.parse(traces)
397
449
 
398
450
  for (const trace of formattedTraces) {
451
+ if (testSuiteExecutionId) {
452
+ this._workerTraceExecutionIds.set(trace, testSuiteExecutionId)
453
+ }
399
454
  this._prepareWorkerTrace(trace)
400
455
  this._exportWorkerTraceOrBuffer(trace)
401
456
  }
@@ -409,7 +464,7 @@ module.exports = class CiPlugin extends Plugin {
409
464
  }
410
465
 
411
466
  get telemetry () {
412
- const testFramework = this.constructor.id
467
+ const testFramework = this.testFramework || this.constructor.id
413
468
  const exporter = this.tracer?._exporter
414
469
  // TODO: only jest worker supported yet
415
470
  const isSupportedWorker = exporter && typeof exporter.exportTelemetry === 'function'
@@ -469,10 +524,19 @@ module.exports = class CiPlugin extends Plugin {
469
524
  /**
470
525
  * Returns library capability metadata tags for this test framework.
471
526
  * @param {string} frameworkVersion - The test framework version.
527
+ * @param {object} [ctx] - Diagnostic channel context.
528
+ * @param {boolean} [ctx.basicReportingOnly] - Whether advanced capabilities must be omitted.
529
+ * @param {string} [ctx.testFramework] - Effective framework when one framework is hosted by another.
472
530
  * @returns {Record<string, string|undefined>}
473
531
  */
474
- getLibraryCapabilitiesTags (frameworkVersion) {
475
- return getDefaultLibraryCapabilitiesTags(this.constructor.id, frameworkVersion)
532
+ getLibraryCapabilitiesTags (frameworkVersion, ctx = {}) {
533
+ if (ctx.basicReportingOnly) {
534
+ return {}
535
+ }
536
+ return getDefaultLibraryCapabilitiesTags(
537
+ ctx.testFramework || this.testFramework || this.constructor.id,
538
+ frameworkVersion
539
+ )
476
540
  }
477
541
 
478
542
  /**
@@ -592,17 +656,34 @@ module.exports = class CiPlugin extends Plugin {
592
656
  // test session, test module and test suite ids. We have to update them in the main process.
593
657
  if (span.name !== 'cucumber.test' && span.name !== 'mocha.test') continue
594
658
 
659
+ const testFramework = this.testFramework || this.constructor.id
660
+ span.meta[TEST_FRAMEWORK] = testFramework
661
+ span.meta[TEST_MODULE] = testFramework
662
+ const testType = this.testSessionSpan?.context().getTag(TEST_TYPE)
663
+ if (testType) {
664
+ span.meta[TEST_TYPE] = testType
665
+ }
666
+ if (this.frameworkVersion) {
667
+ span.meta[TEST_FRAMEWORK_VERSION] = this.frameworkVersion
668
+ }
669
+ if (this.testFrameworkAdapter) {
670
+ span.meta[TEST_FRAMEWORK_ADAPTER] = this.testFrameworkAdapter
671
+ }
672
+
595
673
  const testSuite = span.meta[TEST_SUITE]
596
- const testSuiteSpan = this._testSuiteSpansByTestSuite.get(testSuite)
597
- if (!testSuiteSpan) return testSuite
674
+ const testSuiteExecutionId = this._workerTraceExecutionIds.get(trace)
675
+ const testSuiteKey = getTestSuiteExecutionKey(testSuite, testSuiteExecutionId)
676
+ const testSuiteSpan = this._testSuiteSpansByTestSuite.get(testSuiteKey)
677
+ if (!testSuiteSpan) return testSuiteKey
598
678
 
599
- const testSuiteTags = getTestSuiteLevelVisibilityTags(testSuiteSpan, this.constructor.id)
679
+ const testSuiteTags = getTestSuiteLevelVisibilityTags(testSuiteSpan, testFramework)
600
680
  span.meta = {
601
681
  ...span.meta,
602
682
  ...testSuiteTags,
603
683
  ...getSessionRequestErrorTags(this.testSessionSpan),
604
684
  }
605
685
  }
686
+ this._workerTraceExecutionIds.delete(trace)
606
687
  }
607
688
 
608
689
  /**
@@ -761,19 +842,22 @@ module.exports = class CiPlugin extends Plugin {
761
842
  return codeOwners
762
843
  }
763
844
 
764
- startTestSpan (testName, testSuite, testSuiteSpan, extraTags = {}) {
765
- const childOf = getTestParentSpan(this.tracer)
845
+ startTestSpan (testName, testSuite, testSuiteSpan, extraTags = {}, testExecutionId, startTime) {
846
+ const childOf = getTestParentSpan(this.tracer, testExecutionId)
766
847
 
767
848
  let testTags = {
768
849
  ...getTestCommonTags(
769
850
  testName,
770
851
  testSuite,
771
852
  this.frameworkVersion,
772
- this.constructor.id
853
+ this.testFramework || this.constructor.id
773
854
  ),
774
855
  [COMPONENT]: this.constructor.id,
775
856
  ...extraTags,
776
857
  }
858
+ if (this.testFrameworkAdapter) {
859
+ testTags[TEST_FRAMEWORK_ADAPTER] = this.testFrameworkAdapter
860
+ }
777
861
 
778
862
  const codeOwners = this.getCodeOwners(testTags)
779
863
  if (codeOwners) {
@@ -790,7 +874,7 @@ module.exports = class CiPlugin extends Plugin {
790
874
  [TEST_SUITE_ID]: testSuiteSpan.context().toSpanId(),
791
875
  [TEST_SESSION_ID]: testSuiteSpan.context().toTraceId(),
792
876
  [TEST_COMMAND]: testSuiteSpan.context().getTag(TEST_COMMAND),
793
- [TEST_MODULE]: this.constructor.id,
877
+ [TEST_MODULE]: this.testFramework || this.constructor.id,
794
878
  ...getSessionRequestErrorTags(this.testSessionSpan),
795
879
  }
796
880
  if (testSuiteSpan.context()._parentId) {
@@ -810,6 +894,7 @@ module.exports = class CiPlugin extends Plugin {
810
894
  const testSpan = this.tracer
811
895
  .startSpan(`${this.constructor.id}.test`, {
812
896
  childOf,
897
+ startTime,
813
898
  tags: {
814
899
  ...this.testEnvironmentMetadata,
815
900
  ...testTags,
@@ -36,6 +36,7 @@ const plugins = {
36
36
  get '@smithy/core' () { return require('../../../datadog-plugin-aws-sdk/src') },
37
37
  get '@smithy/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
38
38
  get '@vitest/runner' () { return require('../../../datadog-plugin-vitest/src') },
39
+ get '@wdio/local-runner' () { return require('../../../datadog-plugin-mocha/src') },
39
40
  get '@langchain/langgraph' () { return require('../../../datadog-plugin-langgraph/src') },
40
41
  get '@openai/agents' () { return require('../../../datadog-plugin-openai-agents/src') },
41
42
  get aerospike () { return require('../../../datadog-plugin-aerospike/src') },
@@ -103,7 +103,7 @@ module.exports = class Plugin {
103
103
  * @returns {void}
104
104
  */
105
105
  enter (span, store) {
106
- store = store || legacyStorage.getStore()
106
+ store ||= legacyStorage.getStore()
107
107
  legacyStorage.enterWith({ ...store, span })
108
108
  }
109
109
 
@@ -265,6 +265,7 @@ class TracingPlugin extends Plugin {
265
265
  analyticsSampler.sample(span, config.measured)
266
266
 
267
267
  // TODO: Remove this after migration to TracingChannel is done.
268
+ // eslint-disable-next-line unicorn/no-unnecessary-boolean-comparison -- Context objects use the other branch.
268
269
  if (enterOrCtx === true) {
269
270
  legacyStorage.enterWith({ ...store, span })
270
271
  } else if (enterOrCtx) {
@@ -18,6 +18,7 @@ const {
18
18
  GIT_REPOSITORY_URL,
19
19
  CI_PIPELINE_ID,
20
20
  CI_PIPELINE_NAME,
21
+ CI_PIPELINE_DISPLAY_NAME,
21
22
  CI_PIPELINE_NUMBER,
22
23
  CI_PIPELINE_URL,
23
24
  CI_PROVIDER_NAME,
@@ -75,7 +76,7 @@ function normalizeRef (ref) {
75
76
  if (!ref) {
76
77
  return ref
77
78
  }
78
- return ref.replaceAll(/origin\/|refs\/heads\/|tags\//gm, '')
79
+ return ref.replaceAll(/origin\/|refs\/heads\/|tags\//g, '')
79
80
  }
80
81
 
81
82
  function resolveTilde (filePath) {
@@ -215,7 +216,7 @@ const githubWellKnownDiagnosticDirPatternsUnix = [
215
216
  ]
216
217
  const githubWellKnownDiagnosticDirPatternsWin = ['C:/actions-runner/*/_diag', 'C:/actions-runner/*/*/_diag']
217
218
 
218
- const githubJobIDRegex = /"job":\s*{[\s\S]*?"v"\s*:\s*(\d+)(?:\.0)?/
219
+ const githubJobIDRegex = /"job":\s*\{[\s\S]*?"v"\s*:\s*(\d+)(?:\.0)?/
219
220
 
220
221
  function getJobIDFromDiagFile () {
221
222
  const runnerTemp = getEnvironmentVariable('RUNNER_TEMP')
@@ -316,10 +317,8 @@ module.exports = {
316
317
  }
317
318
 
318
319
  if (NODE_LABELS) {
319
- let nodeLabels
320
320
  try {
321
- nodeLabels = JSON.stringify(NODE_LABELS.split(' '))
322
- tags[CI_NODE_LABELS] = nodeLabels
321
+ tags[CI_NODE_LABELS] = JSON.stringify(NODE_LABELS.split(' '))
323
322
  } catch {
324
323
  // ignore errors
325
324
  }
@@ -651,7 +650,7 @@ module.exports = {
651
650
  [GIT_TAG]: BITBUCKET_TAG,
652
651
  [GIT_REPOSITORY_URL]: BITBUCKET_GIT_SSH_ORIGIN || BITBUCKET_GIT_HTTP_ORIGIN,
653
652
  [CI_WORKSPACE_PATH]: BITBUCKET_CLONE_DIR,
654
- [CI_PIPELINE_ID]: BITBUCKET_PIPELINE_UUID && BITBUCKET_PIPELINE_UUID.replaceAll(/[{}]/gm, ''),
653
+ [CI_PIPELINE_ID]: BITBUCKET_PIPELINE_UUID && BITBUCKET_PIPELINE_UUID.replaceAll(/[{}]/g, ''),
655
654
  [GIT_PULL_REQUEST_BASE_BRANCH]: BITBUCKET_PR_DESTINATION_BRANCH,
656
655
  [PR_NUMBER]: BITBUCKET_PR_ID,
657
656
  }
@@ -699,6 +698,7 @@ module.exports = {
699
698
  BUILDKITE_TAG,
700
699
  BUILDKITE_BUILD_ID,
701
700
  BUILDKITE_PIPELINE_SLUG,
701
+ BUILDKITE_PIPELINE_NAME,
702
702
  BUILDKITE_BUILD_NUMBER,
703
703
  BUILDKITE_BUILD_URL,
704
704
  BUILDKITE_JOB_ID,
@@ -722,6 +722,7 @@ module.exports = {
722
722
  [CI_PROVIDER_NAME]: 'buildkite',
723
723
  [CI_PIPELINE_ID]: BUILDKITE_BUILD_ID,
724
724
  [CI_PIPELINE_NAME]: BUILDKITE_PIPELINE_SLUG,
725
+ [CI_PIPELINE_DISPLAY_NAME]: BUILDKITE_PIPELINE_NAME,
725
726
  [CI_PIPELINE_NUMBER]: BUILDKITE_BUILD_NUMBER,
726
727
  [CI_PIPELINE_URL]: BUILDKITE_BUILD_URL,
727
728
  [CI_JOB_URL]: `${BUILDKITE_BUILD_URL}#${BUILDKITE_JOB_ID}`,
@@ -62,7 +62,7 @@ function sanitizedExec (
62
62
  let result = cachedExec(cmd, flags, { stdio: 'pipe' }).toString()
63
63
 
64
64
  if (shouldTrim) {
65
- result = result.replaceAll(/(\r\n|\n|\r)/gm, '')
65
+ result = result.replaceAll(/(\r\n|\n|\r)/g, '')
66
66
  }
67
67
 
68
68
  if (durationMetric) {
@@ -258,7 +258,7 @@ function applyHttpOtelSemantics (formattedSpan) {
258
258
  // type): server spans are errors on 5xx only (4xx MUST be left unset per the
259
259
  // spec); client spans on any status >= 400.
260
260
  if (status !== undefined && newMeta[ERROR_TYPE] === undefined) {
261
- const isError = kind === 'server' ? statusCode >= 500 : statusCode >= 400
261
+ const isError = statusCode >= (kind === 'server' ? 500 : 400)
262
262
  if (isError) {
263
263
  newMeta[ERROR_TYPE] = status
264
264
  formattedSpan.error = 1
@@ -28,7 +28,7 @@ function normalize (text, limit = 128) {
28
28
  * Determines whether a prompt completion should be sampled based on the configured sampling rate.
29
29
  *
30
30
  * @param {Sampler} sampler
31
- * @param {import('index').Span|import('index').SpanContext} span
31
+ * @param {import('../../../../..').Span|import('../../../../..').SpanContext} span
32
32
  * @returns {boolean} `true` if the prompt completion should be sampled, otherwise `false`.
33
33
  */
34
34
  function isPromptCompletionSampled (sampler, span) {
@@ -51,7 +51,7 @@ module.exports = function makeUtilities (integrationName, tracerConfig) {
51
51
  /**
52
52
  * Determines whether a prompt completion should be sampled based on the configured sampling rate.
53
53
  *
54
- * @param {import('index').Span|import('index').SpanContext} span
54
+ * @param {import('../../../../..').Span|import('../../../../..').SpanContext} span
55
55
  * @returns {boolean} `true` if the prompt completion should be sampled, otherwise `false`.
56
56
  */
57
57
  isPromptCompletionSampled: (span) => isPromptCompletionSampled(sampler, span),
@@ -26,6 +26,7 @@ const GIT_PULL_REQUEST_BASE_BRANCH = 'git.pull_request.base_branch'
26
26
 
27
27
  const CI_PIPELINE_ID = 'ci.pipeline.id'
28
28
  const CI_PIPELINE_NAME = 'ci.pipeline.name'
29
+ const CI_PIPELINE_DISPLAY_NAME = 'ci.pipeline.display_name'
29
30
  const CI_PIPELINE_NUMBER = 'ci.pipeline.number'
30
31
  const CI_PIPELINE_URL = 'ci.pipeline.url'
31
32
  const CI_PROVIDER_NAME = 'ci.provider.name'
@@ -66,6 +67,7 @@ module.exports = {
66
67
  GIT_PULL_REQUEST_BASE_BRANCH,
67
68
  CI_PIPELINE_ID,
68
69
  CI_PIPELINE_NAME,
70
+ CI_PIPELINE_DISPLAY_NAME,
69
71
  CI_PIPELINE_NUMBER,
70
72
  CI_PIPELINE_URL,
71
73
  CI_PROVIDER_NAME,
@@ -45,6 +45,7 @@ const {
45
45
  CI_WORKSPACE_PATH,
46
46
  CI_PIPELINE_ID,
47
47
  CI_PIPELINE_NAME,
48
+ CI_PIPELINE_DISPLAY_NAME,
48
49
  CI_PIPELINE_NUMBER,
49
50
  CI_PIPELINE_URL,
50
51
  CI_JOB_NAME,
@@ -89,10 +90,12 @@ const {
89
90
  const TEST_SESSION_NAME = 'test_session.name'
90
91
 
91
92
  const TEST_FRAMEWORK = 'test.framework'
93
+ const TEST_FRAMEWORK_ADAPTER = 'test.framework_adapter'
92
94
  const TEST_FRAMEWORK_VERSION = 'test.framework_version'
93
95
  const TEST_TYPE = 'test.type'
94
96
  const TEST_NAME = 'test.name'
95
97
  const TEST_SUITE = 'test.suite'
98
+ const TEST_SUITE_EXECUTION_ID = '_dd.test_suite_execution_id'
96
99
  const TEST_STATUS = 'test.status'
97
100
  const TEST_FINAL_STATUS = 'test.final_status'
98
101
  const TEST_PARAMETERS = 'test.parameters'
@@ -180,6 +183,7 @@ const CUCUMBER_WORKER_TRACE_PAYLOAD_CODE = 70
180
183
 
181
184
  // mocha worker variables
182
185
  const MOCHA_WORKER_TRACE_PAYLOAD_CODE = 80
186
+ const MOCHA_WORKER_LOGS_PAYLOAD_CODE = 81
183
187
 
184
188
  // playwright worker variables
185
189
  const PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE = 90
@@ -207,7 +211,7 @@ const DD_CI_LIBRARY_CONFIGURATION_ERROR_KNOWN_TESTS = '_dd.ci.library_configurat
207
211
  const DD_CI_LIBRARY_CONFIGURATION_ERROR_TEST_MANAGEMENT_TESTS =
208
212
  '_dd.ci.library_configuration_error.test_management_tests'
209
213
 
210
- const UNSUPPORTED_TIA_FRAMEWORKS = new Set(['playwright', 'vitest'])
214
+ const UNSUPPORTED_TIA_FRAMEWORKS = new Set(['playwright', 'vitest', 'webdriverio'])
211
215
  const MINIMUM_FRAMEWORK_VERSION_FOR_EFD = {
212
216
  playwright: '>=1.38.0',
213
217
  }
@@ -244,6 +248,7 @@ const TEST_LEVELS_METADATA_TAGS = [
244
248
  CI_NODE_NAME,
245
249
  CI_PIPELINE_ID,
246
250
  CI_PIPELINE_NAME,
251
+ CI_PIPELINE_DISPLAY_NAME,
247
252
  CI_PIPELINE_NUMBER,
248
253
  CI_PIPELINE_URL,
249
254
  CI_PROVIDER_NAME,
@@ -422,10 +427,22 @@ function addTestOptimizationRequest (requestPromises, responseNames, responseNam
422
427
  }
423
428
  }
424
429
 
430
+ /**
431
+ * Builds the internal key used to correlate a worker test with one suite execution.
432
+ *
433
+ * @param {string} testSuite
434
+ * @param {string|undefined} testSuiteExecutionId
435
+ * @returns {string}
436
+ */
437
+ function getTestSuiteExecutionKey (testSuite, testSuiteExecutionId) {
438
+ return testSuiteExecutionId ? `${testSuite}\0${testSuiteExecutionId}` : testSuite
439
+ }
440
+
425
441
  module.exports = {
426
442
  TEST_CODE_OWNERS,
427
443
  TEST_SESSION_NAME,
428
444
  TEST_FRAMEWORK,
445
+ TEST_FRAMEWORK_ADAPTER,
429
446
  TEST_FRAMEWORK_VERSION,
430
447
  JEST_TEST_RUNNER,
431
448
  JEST_DISPLAY_NAME,
@@ -435,6 +452,8 @@ module.exports = {
435
452
  TEST_TYPE,
436
453
  TEST_NAME,
437
454
  TEST_SUITE,
455
+ TEST_SUITE_EXECUTION_ID,
456
+ getTestSuiteExecutionKey,
438
457
  TEST_STATUS,
439
458
  TEST_FINAL_STATUS,
440
459
  TEST_PARAMETERS,
@@ -454,6 +473,7 @@ module.exports = {
454
473
  JEST_WORKER_QUARANTINE_PAYLOAD_CODE,
455
474
  CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
456
475
  MOCHA_WORKER_TRACE_PAYLOAD_CODE,
476
+ MOCHA_WORKER_LOGS_PAYLOAD_CODE,
457
477
  PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE,
458
478
  VITEST_WORKER_TRACE_PAYLOAD_CODE,
459
479
  VITEST_WORKER_LOGS_PAYLOAD_CODE,
@@ -800,7 +820,7 @@ function getTestLevelsMetadataTags (testEnvironmentMetadata) {
800
820
  }
801
821
 
802
822
  function getTestTypeFromFramework (testFramework) {
803
- if (testFramework === 'playwright' || testFramework === 'cypress') {
823
+ if (testFramework === 'playwright' || testFramework === 'cypress' || testFramework === 'webdriverio') {
804
824
  return 'browser'
805
825
  }
806
826
  return 'test'
@@ -860,9 +880,16 @@ function setRumTestCorrelation (context, activeSpan) {
860
880
  return testSpan
861
881
  }
862
882
 
863
- function getTestParentSpan (tracer) {
883
+ /**
884
+ * Returns the synthetic parent that makes a test event the root of its trace.
885
+ *
886
+ * @param {import('../../tracer')} tracer
887
+ * @param {string} [testExecutionId]
888
+ * @returns {import('../../opentracing/span_context')}
889
+ */
890
+ function getTestParentSpan (tracer, testExecutionId) {
864
891
  return tracer.extract('text_map', {
865
- 'x-datadog-trace-id': id().toString(10),
892
+ 'x-datadog-trace-id': testExecutionId || id().toString(10),
866
893
  'x-datadog-parent-id': '0000000000000000',
867
894
  })
868
895
  }
@@ -871,6 +898,7 @@ function getTestCommonTags (name, suite, version, testFramework) {
871
898
  return {
872
899
  [SPAN_TYPE]: 'test',
873
900
  [TEST_TYPE]: getTestTypeFromFramework(testFramework),
901
+ [TEST_FRAMEWORK]: testFramework,
874
902
  [SAMPLING_RULE_DECISION]: 1,
875
903
  [SAMPLING_PRIORITY]: AUTO_KEEP,
876
904
  [TEST_NAME]: name,
@@ -941,8 +969,7 @@ function getCodeOwnersFileEntries (rootDir) {
941
969
  const lines = codeOwnersContent.split('\n')
942
970
 
943
971
  for (const line of lines) {
944
- const [content] = line.split('#')
945
- const trimmed = content.trim()
972
+ const trimmed = getSegment(line, '#', 0).trim()
946
973
  if (trimmed === '') continue
947
974
  const [pattern, ...owners] = trimmed.split(/\s+/)
948
975
  entries.push(setCodeOwnersPatternRegex({ pattern, owners }))
@@ -988,9 +1015,7 @@ function codeOwnersPatternToRegexSource (pattern) {
988
1015
 
989
1016
  if (character === '\\') {
990
1017
  const escapedCharacter = pattern[i + 1]
991
- source += escapedCharacter === undefined
992
- ? escapeRegexCharacter(character)
993
- : escapeRegexCharacter(escapedCharacter)
1018
+ source += escapeRegexCharacter(escapedCharacter ?? character)
994
1019
  i++
995
1020
  } else if (character === '*') {
996
1021
  if (pattern[i + 1] === '*') {
@@ -1101,6 +1126,7 @@ function getCodeOwnersForFilename (filename, entries) {
1101
1126
 
1102
1127
  function getTestLevelCommonTags (command, testFrameworkVersion, testFramework) {
1103
1128
  return {
1129
+ [TEST_FRAMEWORK]: testFramework,
1104
1130
  [TEST_FRAMEWORK_VERSION]: testFrameworkVersion,
1105
1131
  [LIBRARY_VERSION]: ddTraceVersion,
1106
1132
  [TEST_TYPE]: getTestTypeFromFramework(testFramework),
@@ -1184,7 +1210,7 @@ function getCoveredFilenamesFromCoverage (coverage) {
1184
1210
  }
1185
1211
 
1186
1212
  function getCoverageMap (coverage) {
1187
- if (coverage?.files && coverage?.fileCoverageFor) {
1213
+ if (coverage?.files && coverage.fileCoverageFor) {
1188
1214
  return coverage
1189
1215
  }
1190
1216
  return istanbul.createCoverageMap(coverage)
@@ -1917,8 +1943,8 @@ function recordAttemptToFixExecution (attemptToFixExecutions, execution) {
1917
1943
  }
1918
1944
 
1919
1945
  result.executions++
1920
- result.isDisabled = result.isDisabled || !!isDisabled
1921
- result.isQuarantined = result.isQuarantined || !!isQuarantined
1946
+ result.isDisabled ||= !!isDisabled
1947
+ result.isQuarantined ||= !!isQuarantined
1922
1948
 
1923
1949
  if (status === 'fail') {
1924
1950
  result.failedCount++
@@ -8,13 +8,13 @@ const HTTP2_HEADER_AUTHORITY = ':authority'
8
8
  const HTTP2_HEADER_SCHEME = ':scheme'
9
9
  const HTTP2_HEADER_PATH = ':path'
10
10
 
11
- const PATH_REGEX = /^(?:[a-z]+:\/\/(?:[^?/]+))?(?<path>\/[^?]*)(?:(\?).*)?$/
11
+ const PATH_REGEX = /^(?:[a-z]+:\/\/[^?/]+)?(?<path>\/[^?]*)(?:(\?).*)?$/
12
12
 
13
13
  const INT_SEGMENT = /^[1-9][0-9]+$/ // Integer of size at least 2 (>=10)
14
- const INT_ID_SEGMENT = /^(?=.*[0-9].*)[0-9._-]{3,}$/ // Mixed string with digits and delimiters
15
- const HEX_SEGMENT = /^(?=.*[0-9].*)[A-Fa-f0-9]{6,}$/ // Hexadecimal digits of size at least 6 with at least one decimal digit
16
- const HEX_ID_SEGMENT = /^(?=.*[0-9].*)[A-Fa-f0-9._-]{6,}$/ // Mixed string with hex digits and delimiters
17
- const STRING_SEGMENT = /^.{20,}|.*[%&'()*+,:=@].*$/ // Long string or a string containing special characters
14
+ const INT_ID_SEGMENT = /^(?=.*[0-9])[0-9._-]{3,}$/ // Mixed string with digits and delimiters
15
+ const HEX_SEGMENT = /^(?=.*[0-9])[A-Fa-f0-9]{6,}$/ // Hexadecimal digits of size at least 6 with at least one decimal digit
16
+ const HEX_ID_SEGMENT = /^(?=.*[0-9])[A-Fa-f0-9._-]{6,}$/ // Mixed string with hex digits and delimiters
17
+ const STRING_SEGMENT = /^.{20,}|[%&'()*+,:=@]/ // Long string or a string containing special characters
18
18
 
19
19
  /**
20
20
  * Extract full URL from HTTP request
@@ -36,7 +36,7 @@ function removeEmptyValues (tagsAndValues) {
36
36
  // https://github.com/jonschlinkert/is-git-url/blob/396965ffabf2f46656c8af4c47bef1d69f09292e/index.js#L9C15-L9C87
37
37
  // The `.git` suffix is optional in this version
38
38
  function validateGitRepositoryUrl (repoUrl) {
39
- return /(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(\/?|#[-\w.]+?)$/.test(repoUrl)
39
+ return /(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(\/?|#[-\w.]+)$/.test(repoUrl)
40
40
  }
41
41
 
42
42
  function validateGitCommitSha (gitCommitSha) {
@@ -376,7 +376,7 @@ function isOriginAllowed (req, headers) {
376
376
  }
377
377
 
378
378
  function splitHeader (str) {
379
- return typeof str === 'string' ? str.split(/\s*,\s*/) : []
379
+ return typeof str === 'string' ? str.split(',').map((header) => header.trim()) : []
380
380
  }
381
381
 
382
382
  function addRequestTags (context, spanType) {
@@ -140,7 +140,7 @@ class PrioritySampler {
140
140
  samplers[key] = new Sampler(rates[key])
141
141
  }
142
142
 
143
- samplers[DEFAULT_KEY] = samplers[DEFAULT_KEY] || defaultSampler
143
+ samplers[DEFAULT_KEY] ||= defaultSampler
144
144
 
145
145
  this._samplers = samplers
146
146
 
@@ -257,8 +257,11 @@ class PrioritySampler {
257
257
  context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
258
258
  context._trace.tags[SAMPLING_KNUTH_RATE] = formatKnuthRate(rule.sampleRate)
259
259
  context._sampling.mechanism = SAMPLING_MECHANISM_RULE
260
- if (rule.provenance === 'customer') context._sampling.mechanism = SAMPLING_MECHANISM_REMOTE_USER
261
- if (rule.provenance === 'dynamic') context._sampling.mechanism = SAMPLING_MECHANISM_REMOTE_DYNAMIC
260
+ if (rule.provenance === 'customer') {
261
+ context._sampling.mechanism = SAMPLING_MECHANISM_REMOTE_USER
262
+ } else if (rule.provenance === 'dynamic') {
263
+ context._sampling.mechanism = SAMPLING_MECHANISM_REMOTE_DYNAMIC
264
+ }
262
265
 
263
266
  return rule.sample(context) && this._isSampledByRateLimit(context)
264
267
  ? USER_KEEP
@@ -6,7 +6,7 @@ class PoissonProcessSamplingFilter {
6
6
  #samplingInterval
7
7
  #resetInterval
8
8
  #now
9
- #lastNow = Number.NEGATIVE_INFINITY
9
+ #lastNow = -Infinity
10
10
  #samplingInstantCount = 0
11
11
 
12
12
  constructor ({ samplingInterval, now, resetInterval }) {