dd-trace 6.6.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 (209) hide show
  1. package/ci/diagnose.js +162 -21
  2. package/ci/init.js +0 -1
  3. package/ci/runbook.md +187 -180
  4. package/ci/test-optimization-validation/approval-artifacts.js +3 -1
  5. package/ci/test-optimization-validation/approval.js +52 -15
  6. package/ci/test-optimization-validation/ci-command-candidate.js +26 -32
  7. package/ci/test-optimization-validation/ci-discovery.js +1 -1
  8. package/ci/test-optimization-validation/ci-package-scripts.js +141 -0
  9. package/ci/test-optimization-validation/ci-remediation.js +112 -39
  10. package/ci/test-optimization-validation/cli.js +516 -681
  11. package/ci/test-optimization-validation/command-blocker.js +188 -33
  12. package/ci/test-optimization-validation/command-output-policy.js +8 -31
  13. package/ci/test-optimization-validation/command-runner.js +189 -245
  14. package/ci/test-optimization-validation/environment.js +90 -0
  15. package/ci/test-optimization-validation/executable.js +159 -388
  16. package/ci/test-optimization-validation/framework-adapters/cucumber.js +119 -0
  17. package/ci/test-optimization-validation/framework-adapters/cypress.js +107 -0
  18. package/ci/test-optimization-validation/framework-adapters/playwright.js +181 -0
  19. package/ci/test-optimization-validation/generated-files.js +84 -22
  20. package/ci/test-optimization-validation/generated-test-contract.js +281 -0
  21. package/ci/test-optimization-validation/generated-verifier.js +49 -16
  22. package/ci/test-optimization-validation/literal-environment.js +57 -0
  23. package/ci/test-optimization-validation/manifest-loader.js +2 -22
  24. package/ci/test-optimization-validation/manifest-scaffold.js +815 -515
  25. package/ci/test-optimization-validation/manifest-schema.js +494 -702
  26. package/ci/test-optimization-validation/offline-fixtures.js +4 -1
  27. package/ci/test-optimization-validation/offline-output.js +6 -6
  28. package/ci/test-optimization-validation/plan-writer.js +243 -984
  29. package/ci/test-optimization-validation/preflight-runner.js +49 -55
  30. package/ci/test-optimization-validation/redaction.js +2 -1
  31. package/ci/test-optimization-validation/report-writer.js +391 -1357
  32. package/ci/test-optimization-validation/result-semantics.js +86 -0
  33. package/ci/test-optimization-validation/runner-command.js +249 -0
  34. package/ci/test-optimization-validation/runner-contract.js +664 -0
  35. package/ci/test-optimization-validation/safe-files.js +4 -4
  36. package/ci/test-optimization-validation/scenarios/auto-test-retries.js +29 -3
  37. package/ci/test-optimization-validation/scenarios/basic-reporting.js +240 -543
  38. package/ci/test-optimization-validation/scenarios/ci-wiring.js +450 -670
  39. package/ci/test-optimization-validation/scenarios/early-flake-detection.js +4 -3
  40. package/ci/test-optimization-validation/scenarios/helpers.js +67 -9
  41. package/ci/test-optimization-validation/scenarios/test-management.js +6 -5
  42. package/ci/test-optimization-validation/source-text.js +87 -0
  43. package/ci/test-optimization-validation/test-output.js +12 -22
  44. package/ci/vitest-no-worker-init-setup.mjs +348 -51
  45. package/ext/tags.d.ts +1 -0
  46. package/index.d.ts +84 -13
  47. package/package.json +10 -4
  48. package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
  49. package/packages/datadog-esbuild/index.js +4 -2
  50. package/packages/datadog-esbuild/src/utils.js +1 -1
  51. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +4 -4
  52. package/packages/datadog-instrumentations/src/cucumber.js +9 -6
  53. package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
  54. package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
  55. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
  56. package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
  57. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +1 -0
  58. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
  59. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/openai-agents.js +31 -0
  60. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +57 -0
  61. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
  62. package/packages/datadog-instrumentations/src/helpers/router-helper.js +1 -1
  63. package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
  64. package/packages/datadog-instrumentations/src/http/client.js +1 -3
  65. package/packages/datadog-instrumentations/src/jest.js +8 -14
  66. package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
  67. package/packages/datadog-instrumentations/src/mocha/main.js +2 -42
  68. package/packages/datadog-instrumentations/src/mocha/utils.js +68 -2
  69. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +19 -0
  70. package/packages/datadog-instrumentations/src/mocha/worker.js +446 -42
  71. package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
  72. package/packages/datadog-instrumentations/src/openai-agents.js +159 -0
  73. package/packages/datadog-instrumentations/src/playwright.js +3 -2
  74. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  75. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +525 -56
  76. package/packages/datadog-instrumentations/src/vitest-main.js +90 -10
  77. package/packages/datadog-instrumentations/src/webdriverio.js +914 -0
  78. package/packages/datadog-plugin-aerospike/src/index.js +1 -3
  79. package/packages/datadog-plugin-amqplib/src/client.js +1 -1
  80. package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
  81. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  82. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
  83. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
  84. package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
  85. package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
  86. package/packages/datadog-plugin-child_process/src/index.js +3 -3
  87. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +5 -8
  88. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
  89. package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
  90. package/packages/datadog-plugin-fs/src/index.js +0 -4
  91. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
  92. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
  93. package/packages/datadog-plugin-graphql/src/execute.js +1 -0
  94. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
  95. package/packages/datadog-plugin-http/src/client.js +2 -1
  96. package/packages/datadog-plugin-jest/src/index.js +2 -3
  97. package/packages/datadog-plugin-jest/src/util.js +2 -1
  98. package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
  99. package/packages/datadog-plugin-mocha/src/index.js +25 -6
  100. package/packages/datadog-plugin-openai-agents/src/index.js +74 -0
  101. package/packages/datadog-plugin-openai-agents/src/integration.js +503 -0
  102. package/packages/datadog-plugin-openai-agents/src/processor.js +108 -0
  103. package/packages/datadog-plugin-openai-agents/src/util.js +60 -0
  104. package/packages/datadog-plugin-prisma/src/index.js +5 -1
  105. package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
  106. package/packages/datadog-plugin-rhea/src/producer.js +1 -1
  107. package/packages/datadog-plugin-undici/src/index.js +2 -1
  108. package/packages/datadog-plugin-vitest/src/index.js +84 -11
  109. package/packages/datadog-webpack/index.js +2 -2
  110. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
  111. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
  112. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
  113. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  114. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
  115. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  116. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
  117. package/packages/dd-trace/src/appsec/sdk/track_event.js +1 -1
  118. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  119. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
  120. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +50 -51
  121. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -1
  122. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -0
  123. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
  124. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
  125. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +161 -33
  126. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
  127. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +7 -5
  128. package/packages/dd-trace/src/config/defaults.js +14 -6
  129. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
  130. package/packages/dd-trace/src/config/index.js +15 -0
  131. package/packages/dd-trace/src/config/parsers.js +19 -1
  132. package/packages/dd-trace/src/config/supported-configurations.json +12 -6
  133. package/packages/dd-trace/src/datastreams/encoding.js +3 -4
  134. package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
  135. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
  136. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
  137. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
  138. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
  139. package/packages/dd-trace/src/encode/span-stats.js +7 -1
  140. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  141. package/packages/dd-trace/src/exporter.js +16 -9
  142. package/packages/dd-trace/src/exporters/common/url.js +3 -5
  143. package/packages/dd-trace/src/exporters/electron/index.js +4 -1
  144. package/packages/dd-trace/src/external-logger/src/index.js +1 -2
  145. package/packages/dd-trace/src/flare/index.js +2 -2
  146. package/packages/dd-trace/src/id.js +1 -1
  147. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
  148. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
  149. package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
  150. package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
  151. package/packages/dd-trace/src/llmobs/experiments/index.js +51 -12
  152. package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
  153. package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
  154. package/packages/dd-trace/src/llmobs/experiments/util.js +218 -0
  155. package/packages/dd-trace/src/llmobs/index.js +9 -1
  156. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +104 -22
  157. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
  158. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
  159. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
  160. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
  161. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +5 -9
  162. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +20 -0
  163. package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +321 -0
  164. package/packages/dd-trace/src/llmobs/sdk.js +6 -12
  165. package/packages/dd-trace/src/llmobs/span_processor.js +14 -7
  166. package/packages/dd-trace/src/llmobs/tagger.js +24 -5
  167. package/packages/dd-trace/src/llmobs/util.js +56 -3
  168. package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
  169. package/packages/dd-trace/src/noop/proxy.js +2 -2
  170. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +3 -6
  171. package/packages/dd-trace/src/openfeature/configuration_source.js +5 -8
  172. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +5 -1
  173. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  174. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
  175. package/packages/dd-trace/src/opentracing/span.js +1 -1
  176. package/packages/dd-trace/src/opentracing/span_context.js +1 -1
  177. package/packages/dd-trace/src/plugins/ci_plugin.js +114 -23
  178. package/packages/dd-trace/src/plugins/index.js +2 -0
  179. package/packages/dd-trace/src/plugins/outbound.js +4 -1
  180. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  181. package/packages/dd-trace/src/plugins/tracing.js +1 -0
  182. package/packages/dd-trace/src/plugins/util/ci.js +7 -6
  183. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  184. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +1 -1
  185. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  186. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  187. package/packages/dd-trace/src/plugins/util/test.js +38 -12
  188. package/packages/dd-trace/src/plugins/util/url.js +5 -5
  189. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  190. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  191. package/packages/dd-trace/src/priority_sampler.js +6 -3
  192. package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
  193. package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
  194. package/packages/dd-trace/src/ritm.js +5 -20
  195. package/packages/dd-trace/src/span_processor.js +1 -1
  196. package/packages/dd-trace/src/span_stats.js +22 -4
  197. package/packages/dd-trace/src/startup-log.js +3 -0
  198. package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
  199. package/packages/dd-trace/src/util.js +16 -0
  200. package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
  201. package/vendor/dist/pprof-format/index.js +1 -1
  202. package/vendor/dist/source-map/index.js +1 -1
  203. package/ci/test-optimization-validation/command-suitability.js +0 -471
  204. package/ci/test-optimization-validation/init-probe-preload.js +0 -163
  205. package/ci/test-optimization-validation/init-probe.js +0 -246
  206. package/ci/test-optimization-validation/late-initialization.js +0 -63
  207. package/ci/test-optimization-validation/local-command.js +0 -163
  208. package/ci/test-optimization-validation/setup-runner.js +0 -97
  209. package/ci/test-optimization-validation-manifest.schema.json +0 -1
@@ -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 }) {
@@ -17,8 +17,8 @@ function getThreadLabels () {
17
17
  const nativeThreadId = pprof.getNativeThreadId()
18
18
  return {
19
19
  [THREAD_NAME_LABEL]: eventLoopThreadName,
20
- [THREAD_ID_LABEL]: `${threadId}`,
21
- [OS_THREAD_ID_LABEL]: `${nativeThreadId}`,
20
+ [THREAD_ID_LABEL]: threadId.toString(),
21
+ [OS_THREAD_ID_LABEL]: nativeThreadId.toString(),
22
22
  }
23
23
  }
24
24
 
@@ -7,7 +7,11 @@ const Module = require('module')
7
7
  const dc = require('dc-polyfill')
8
8
 
9
9
  const parse = require('../../../vendor/dist/module-details-from-path')
10
- const { isRelativeRequire } = require('../../datadog-instrumentations/src/helpers/shared-utils')
10
+ const {
11
+ isBuiltinModuleName,
12
+ isRelativeRequire,
13
+ normalizeModuleName,
14
+ } = require('../../datadog-instrumentations/src/helpers/shared-utils')
11
15
  const { getConfiguredEnvName, getEnvironmentVariable } = require('./config/helper')
12
16
 
13
17
  const origRequire = Module.prototype.require
@@ -22,25 +26,6 @@ let patchedRequire = null
22
26
  const moduleLoadStartChannel = dc.channel('dd-trace:moduleLoadStart')
23
27
  const moduleLoadEndChannel = dc.channel('dd-trace:moduleLoadEnd')
24
28
 
25
- function stripNodePrefix (name) {
26
- if (typeof name !== 'string') return name
27
- return name.startsWith('node:') ? name.slice(5) : name
28
- }
29
-
30
- const builtinModules = new Set(Module.builtinModules.map(stripNodePrefix))
31
-
32
- function isBuiltinModuleName (name) {
33
- if (typeof name !== 'string') return false
34
- if (name === 'electron') return true
35
- return builtinModules.has(stripNodePrefix(name))
36
- }
37
-
38
- function normalizeModuleName (name) {
39
- if (typeof name !== 'string') return name
40
- const stripped = stripNodePrefix(name)
41
- return builtinModules.has(stripped) ? stripped : name
42
- }
43
-
44
29
  /**
45
30
  * @overload
46
31
  * @param {string[]} modules list of modules to hook into
@@ -62,7 +62,7 @@ class SpanProcessor {
62
62
  active.push(span)
63
63
  } else {
64
64
  const formattedSpan = spanFormat(span, isFirstSpanInChunk, this._processTags)
65
- if (isFirstSpanInChunk && stampApmDisabled) {
65
+ if (stampApmDisabled) {
66
66
  formattedSpan.metrics[APM_TRACING_ENABLED_KEY] = 0
67
67
  }
68
68
  isFirstSpanInChunk = false
@@ -14,6 +14,8 @@ const {
14
14
  GRPC_STATUS_CODE,
15
15
  } = require('../../../ext/tags')
16
16
  const { ORIGIN_KEY, TOP_LEVEL_KEY, SVC_SRC_KEY, GRPC_STATUS_NAMES } = require('./constants')
17
+
18
+ const GRPC_STATUS_CODE_MAP = Object.fromEntries(GRPC_STATUS_NAMES.map((name, i) => [name, String(i)]))
17
19
  const { version } = require('./pkg')
18
20
  const processTags = require('./process-tags')
19
21
 
@@ -108,10 +110,26 @@ class SpanAggKey {
108
110
  this.srvSrc = span.meta[SVC_SRC_KEY] || ''
109
111
  this.spanKind = span.meta[SPAN_KIND] || ''
110
112
  // dd gRPC plugin sets a numeric code via setTag; OTel/manual sets a string name via meta.
111
- const grpcCode = span.meta[GRPC_STATUS_CODE] ?? span.metrics?.[GRPC_STATUS_CODE]
112
- this.rpcStatusCode = typeof grpcCode === 'number'
113
- ? (GRPC_STATUS_NAMES[grpcCode] ?? String(grpcCode))
114
- : (grpcCode ?? '')
113
+ // Normalize to numeric string to match the Agent's parseGRPCStatusString convention.
114
+ // Also check OTel semantic aliases (rpc.grpc.status_code, rpc.response.status_code) as
115
+ // the OTel bridge stores attributes under their original key without remapping.
116
+ const grpcCode = span.meta[GRPC_STATUS_CODE] ?? span.metrics?.[GRPC_STATUS_CODE] ??
117
+ span.meta['rpc.grpc.status_code'] ?? span.metrics?.['rpc.grpc.status_code'] ??
118
+ span.meta['rpc.response.status_code'] ?? span.metrics?.['rpc.response.status_code']
119
+ if (typeof grpcCode === 'number') {
120
+ this.rpcStatusCode = String(grpcCode)
121
+ } else if (grpcCode) {
122
+ const upper = String(grpcCode).toUpperCase()
123
+ const numeric = GRPC_STATUS_CODE_MAP[upper]
124
+ if (numeric === undefined) {
125
+ const n = Number(grpcCode)
126
+ this.rpcStatusCode = Number.isInteger(n) && n >= 0 ? String(n) : ''
127
+ } else {
128
+ this.rpcStatusCode = numeric
129
+ }
130
+ } else {
131
+ this.rpcStatusCode = ''
132
+ }
115
133
  }
116
134
 
117
135
  toString () {
@@ -108,6 +108,9 @@ function configInfo () {
108
108
  profiling_enabled: profilingEnabled === 'true' || profilingEnabled === 'auto',
109
109
  appsec_enabled: config.appsec.enabled,
110
110
  data_streams_enabled: !!config.dsmEnabled,
111
+ otlp_traces_export_enabled: config.OTEL_TRACES_EXPORTER === 'otlp' && !config.isCiVisibility,
112
+ otlp_metrics_export_enabled: !!config.DD_METRICS_OTEL_ENABLED,
113
+ otlp_logs_export_enabled: !!config.DD_LOGS_OTEL_ENABLED,
111
114
  }
112
115
  }
113
116
 
@@ -31,7 +31,9 @@ function isValid (logEntry) {
31
31
  }
32
32
 
33
33
  const EOL = '\n'
34
- const STACK_FRAME_LINE_REGEX = /^\s*at\s/gm
34
+ // `[ \t]*` (horizontal whitespace) cannot span line terminators, so under `m` the `^`-anchored
35
+ // match runs once per line instead of rescanning across lines. Stack frames indent with spaces.
36
+ const STACK_FRAME_LINE_REGEX = /^[ \t]*at\s/gm
35
37
 
36
38
  function sanitize (logEntry) {
37
39
  const stack = logEntry.stack_trace
@@ -102,6 +102,21 @@ function getSegment (string, separator, index, fallback) {
102
102
  return end === -1 ? string.slice(start) : string.slice(start, end)
103
103
  }
104
104
 
105
+ /**
106
+ * Return the path portion of a request target, dropping any query string and fragment.
107
+ * The two scans avoid the array and substring a `split(/[?#]/)` allocates per call.
108
+ *
109
+ * @param {string} target
110
+ */
111
+ function stripQueryAndFragment (target) {
112
+ let cut = target.indexOf('?')
113
+ const fragment = target.indexOf('#')
114
+ if (cut === -1 || (fragment !== -1 && fragment < cut)) {
115
+ cut = fragment
116
+ }
117
+ return cut === -1 ? target : target.slice(0, cut)
118
+ }
119
+
105
120
  function calculateDDBasePath (dirname) {
106
121
  const dirSteps = dirname.split(path.sep)
107
122
  const packagesIndex = dirSteps.lastIndexOf('packages')
@@ -136,6 +151,7 @@ module.exports = {
136
151
  isError,
137
152
  globMatch,
138
153
  getSegment,
154
+ stripQueryAndFragment,
139
155
  ddBasePath: globalThis.__DD_ESBUILD_BASEPATH || calculateDDBasePath(__dirname),
140
156
  normalizePluginEnvName,
141
157
  formatKnuthRate,