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
@@ -67,9 +67,7 @@ function getMeta (resourceName, commandArgs) {
67
67
  const [ns, set, bin, exp, index] = commandArgs
68
68
 
69
69
  // The `ext` argument was added to IndexCreate in 6.3.0
70
- meta = commandArgs.length > 8
71
- ? getMetaForIndex(ns, set, bin, index)
72
- : getMetaForIndex(ns, set, bin, exp)
70
+ meta = getMetaForIndex(ns, set, bin, commandArgs.length > 8 ? index : exp)
73
71
  } else if (resourceName === 'Query') {
74
72
  const { ns, set } = commandArgs[2]
75
73
  meta = getMetaForQuery({ ns, set })
@@ -33,7 +33,7 @@ class AmqplibClientPlugin extends ClientPlugin {
33
33
  },
34
34
  }, ctx)
35
35
 
36
- fields.headers = fields.headers || {}
36
+ fields.headers ||= {}
37
37
 
38
38
  this.tracer.inject(span, TEXT_MAP, fields.headers)
39
39
 
@@ -52,7 +52,7 @@ class AmqplibProducerPlugin extends ProducerPlugin {
52
52
  },
53
53
  }, ctx)
54
54
 
55
- fields.headers = fields.headers || {}
55
+ fields.headers ||= {}
56
56
 
57
57
  this.tracer.inject(span, TEXT_MAP, fields.headers)
58
58
 
@@ -39,9 +39,9 @@ class EventBridge extends BaseAwsSdkPlugin {
39
39
  const rulename = params.Name ?? ''
40
40
  return {
41
41
  'resource.name': operation ? `${operation} ${params.source}` : params.source,
42
- 'aws.eventbridge.source': `${params.source}`,
42
+ 'aws.eventbridge.source': params.source,
43
43
  'messaging.system': 'aws_eventbridge',
44
- rulename: `${rulename}`,
44
+ rulename,
45
45
  }
46
46
  }
47
47
 
@@ -29,9 +29,9 @@ class Stepfunctions extends BaseAwsSdkPlugin {
29
29
 
30
30
  generateTags (params, operation, response) {
31
31
  if (!params) return
32
- const tags = { 'resource.name': params.name ? `${operation} ${params.name}` : `${operation}` }
32
+ const tags = { 'resource.name': params.name ? `${operation} ${params.name}` : operation }
33
33
  if (operation === 'startExecution' || operation === 'startSyncExecution') {
34
- tags.statemachinearn = `${params.stateMachineArn}`
34
+ tags.statemachinearn = params.stateMachineArn
35
35
  }
36
36
  return tags
37
37
  }
@@ -46,9 +46,7 @@ class AzureEventHubsProducerPlugin extends ProducerPlugin {
46
46
  }
47
47
  injectTraceContext(this.tracer, span, ctx.eventData)
48
48
  }
49
- }
50
-
51
- if (ctx.functionName === 'sendBatch') {
49
+ } else if (ctx.functionName === 'sendBatch') {
52
50
  const eventData = ctx.eventData
53
51
  const eventDataLength = eventData.length || eventData._context.connection._eventsCount
54
52
  span.setTag('messaging.operation', 'send')
@@ -45,9 +45,11 @@ class AzureServiceBusProducerPlugin extends ProducerPlugin {
45
45
  }
46
46
  injectTraceContext(this.tracer, span, ctx.msg)
47
47
  }
48
- }
49
-
50
- if (ctx.functionName === 'send' || ctx.functionName === 'sendBatch' || ctx.functionName === 'scheduleMessages') {
48
+ } else if (
49
+ ctx.functionName === 'send' ||
50
+ ctx.functionName === 'sendBatch' ||
51
+ ctx.functionName === 'scheduleMessages'
52
+ ) {
51
53
  const messages = ctx.msg
52
54
  const isBatch = messages.constructor?.name === 'ServiceBusMessageBatchImpl'
53
55
  if (isBatch) {
@@ -222,7 +222,7 @@ class QueueAddBulkPlugin extends BaseBullmqProducerPlugin {
222
222
  for (let i = 0; i < jobs.length; i++) {
223
223
  const job = jobs[i]
224
224
  if (!job) continue
225
- job.opts = job.opts || {}
225
+ job.opts ||= {}
226
226
  cache[i] = this._injectIntoOpts(span, job.opts)
227
227
  }
228
228
  ctx._ddMetadata = cache
@@ -274,7 +274,7 @@ class FlowProducerAddPlugin extends BaseBullmqProducerPlugin {
274
274
  injectTraceContext (span, ctx) {
275
275
  const flow = ctx.arguments?.[0]
276
276
  if (!flow) return
277
- flow.opts = flow.opts || {}
277
+ flow.opts ||= {}
278
278
  ctx._ddMetadata = this._injectIntoOpts(span, flow.opts)
279
279
  }
280
280
 
@@ -283,7 +283,7 @@ class FlowProducerAddPlugin extends BaseBullmqProducerPlugin {
283
283
  if (!flow) {
284
284
  return { queueName: 'bullmq', payloadSize: 0, optsTarget: undefined }
285
285
  }
286
- flow.opts = flow.opts || {}
286
+ flow.opts ||= {}
287
287
  return {
288
288
  queueName: flow.queueName || 'bullmq',
289
289
  payloadSize: flow.data ? getMessageSize(flow.data) : 0,
@@ -52,7 +52,7 @@ class ChildProcessPlugin extends TracingPlugin {
52
52
  }
53
53
 
54
54
  if (truncated) {
55
- meta['cmd.truncated'] = `${truncated}`
55
+ meta['cmd.truncated'] = 'true'
56
56
  }
57
57
 
58
58
  this.startSpan('command_execution', {
@@ -81,7 +81,7 @@ class ChildProcessPlugin extends TracingPlugin {
81
81
 
82
82
  const span = ctx.currentStore?.span || this.activeSpan
83
83
 
84
- span?.setTag('cmd.exit_code', `${exitCode}`)
84
+ span?.setTag('cmd.exit_code', String(exitCode))
85
85
  span?.finish()
86
86
 
87
87
  return ctx.parentStore
@@ -112,7 +112,7 @@ class ChildProcessPlugin extends TracingPlugin {
112
112
 
113
113
  const span = ctx.currentStore?.span || this.activeSpan
114
114
 
115
- span?.setTag('cmd.exit_code', `${exitCode}`)
115
+ span?.setTag('cmd.exit_code', String(exitCode))
116
116
  span?.finish()
117
117
 
118
118
  return ctx.parentStore
@@ -5,7 +5,7 @@ const shellParser = require('../../../vendor/dist/shell-quote').parse
5
5
  const ALLOWED_ENV_VARIABLES = new Set(['LD_PRELOAD', 'LD_LIBRARY_PATH', 'PATH'])
6
6
  const PROCESS_DENYLIST = new Set(['md5'])
7
7
 
8
- const VARNAMES_REGEX = /\$(\w*)(?:[^\w]|$)/gmi
8
+ const VARNAMES_REGEX = /\$(\w*)(?:[^\w]|$)/gm
9
9
  // eslint-disable-next-line @stylistic/max-len
10
10
  const PARAM_PATTERN = '^-{0,2}(?:p(?:ass(?:w(?:or)?d)?)?|address|api[-_]?key|e?mail|secret(?:[-_]?key)?|a(?:ccess|uth)[-_]?token|mysql_pwd|credentials|(?:stripe)?token)$'
11
11
  const regexParam = new RegExp(PARAM_PATTERN, 'i')
@@ -14,18 +14,15 @@ const envVarRegex = new RegExp(ENV_PATTERN)
14
14
  const REDACTED = '?'
15
15
 
16
16
  function extractVarNames (expression) {
17
- const varNames = new Set()
17
+ const varNames = {}
18
18
  let match
19
19
 
20
20
  while ((match = VARNAMES_REGEX.exec(expression))) {
21
- varNames.add(match[1])
21
+ const name = match[1]
22
+ varNames[name] = `$${name}`
22
23
  }
23
24
 
24
- const varNamesObject = {}
25
- for (const varName of varNames.keys()) {
26
- varNamesObject[varName] = `$${varName}`
27
- }
28
- return varNamesObject
25
+ return varNames
29
26
  }
30
27
 
31
28
  function getTokensByExpression (expressionTokens) {
@@ -61,7 +61,7 @@ function decodeVLQ (str, cursor) {
61
61
  * @returns {string | null}
62
62
  */
63
63
  function resolveSourcePath (mapDir, sourceRoot, sourcePath) {
64
- const cleanSourcePath = sourcePath.replace(/[?#].*$/, '')
64
+ const cleanSourcePath = sourcePath.split(/[?#]/)[0]
65
65
  if (/^[A-Za-z][A-Za-z\d+.-]*:\/\//.test(cleanSourcePath)) {
66
66
  // Virtual sources may use URL-like schemes (e.g. file://, webpack://, vite://).
67
67
  // If they encode an absolute local path in the URL pathname, use it.
@@ -27,7 +27,7 @@ class FastifyTracingPlugin extends RouterPlugin {
27
27
  }
28
28
 
29
29
  function getParentStore (ctx) {
30
- ctx.parentStore = ctx.parentStore ?? storage('legacy').getStore()
30
+ ctx.parentStore ??= storage('legacy').getStore()
31
31
  return ctx.parentStore
32
32
  }
33
33
 
@@ -7,10 +7,6 @@ class FsPlugin extends TracingPlugin {
7
7
  static operation = 'operation'
8
8
  static experimental = true
9
9
 
10
- configure (...args) {
11
- return super.configure(...args)
12
- }
13
-
14
10
  bindStart (ctx) {
15
11
  if (!this.activeSpan) return { noop: true }
16
12
 
@@ -96,6 +96,20 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
96
96
  })
97
97
  }
98
98
 
99
+ start (ctx) {
100
+ if (!this.config.dsmEnabled) return
101
+ const { message } = ctx
102
+ if (!message?.attributes) return
103
+
104
+ const { span } = ctx.currentStore
105
+ const subscription = message._subscriber._subscription
106
+ const topic = subscription?.metadata?.topic || message.attributes?.['pubsub.topic']
107
+ const payloadSize = getMessageSize(message)
108
+ this.tracer.decodeDataStreamsContext(message.attributes)
109
+ this.tracer
110
+ .setCheckpoint(['direction:in', `topic:${topic}`, 'type:google-pubsub'], span, payloadSize)
111
+ }
112
+
99
113
  bindStart (ctx) {
100
114
  const { message } = ctx
101
115
  const subscription = message._subscriber._subscription
@@ -181,13 +195,6 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
181
195
  }
182
196
  }
183
197
 
184
- if (this.config.dsmEnabled && message?.attributes) {
185
- const payloadSize = getMessageSize(message)
186
- this.tracer.decodeDataStreamsContext(message.attributes)
187
- this.tracer
188
- .setCheckpoint(['direction:in', `topic:${topic}`, 'type:google-pubsub'], span, payloadSize)
189
- }
190
-
191
198
  return ctx.currentStore
192
199
  }
193
200
 
@@ -36,6 +36,25 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
36
36
  if (topicName) attributes['pubsub.topic'] = topicName
37
37
  }
38
38
 
39
+ start (ctx) {
40
+ if (!this.config.dsmEnabled) return
41
+ if (ctx.api !== 'publish' || !ctx.currentStore) return
42
+ const { request } = ctx
43
+ const messages = request.messages || []
44
+ const topic = request.topic
45
+ const { span } = ctx.currentStore
46
+
47
+ for (const msg of messages) {
48
+ const attributes = msg.attributes ??= {}
49
+ const dataStreamsContext = this.tracer.setCheckpoint(
50
+ ['direction:out', `topic:${topic}`, 'type:google-pubsub'],
51
+ span,
52
+ getHeadersSize(msg)
53
+ )
54
+ DsmPathwayCodec.encode(dataStreamsContext, attributes)
55
+ }
56
+ }
57
+
39
58
  bindStart (ctx) {
40
59
  const { request, api, projectId } = ctx
41
60
  if (api !== 'publish') return
@@ -113,7 +132,6 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
113
132
 
114
133
  const messageCountStr = String(messageCount)
115
134
  const startTimeStr = String(Math.floor(batchSpan._startTime))
116
- const dsmEnabled = this.config.dsmEnabled
117
135
 
118
136
  for (let i = 0; i < messageCount; i++) {
119
137
  const msg = messages[i]
@@ -137,15 +155,6 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
137
155
  if (batchTraceIdUpper) {
138
156
  attributes['_dd.pubsub_request.p.tid'] = batchTraceIdUpper
139
157
  }
140
-
141
- if (dsmEnabled) {
142
- const dataStreamsContext = this.tracer.setCheckpoint(
143
- ['direction:out', `topic:${topic}`, 'type:google-pubsub'],
144
- batchSpan,
145
- getHeadersSize(msg)
146
- )
147
- DsmPathwayCodec.encode(dataStreamsContext, attributes)
148
- }
149
158
  }
150
159
 
151
160
  ctx.batchSpan = batchSpan
@@ -495,6 +495,7 @@ function wrapResolve (resolve) {
495
495
  // run in the parent store, not field.currentStore: the first sibling's
496
496
  // synchronous resolver already finished the shared graphql.resolve span, so
497
497
  // re-entering its store would parent user spans to a closed span.
498
+ // eslint-disable-next-line unicorn/prefer-else-if -- Keep sibling early return outside first-field setup.
498
499
  if (!isFirst) {
499
500
  return callInAsyncScope(resolve, this, arguments, rootCtx.abortController, field.parentStore, (err) => {
500
501
  if (updateFieldCh.hasSubscribers) {
@@ -11,7 +11,7 @@ const transforms = require('./transforms')
11
11
  const cache = new WeakMap()
12
12
 
13
13
  function defaultEngineReportingSignature (ast, operationName) {
14
- const key = operationName == null ? '' : operationName
14
+ const key = operationName ?? ''
15
15
  let inner = cache.get(ast)
16
16
  if (inner !== undefined) {
17
17
  const cached = inner.get(key)
@@ -10,6 +10,7 @@ const HTTP_HEADERS = formats.HTTP_HEADERS
10
10
  const urlFilter = require('../../dd-trace/src/plugins/util/urlfilter')
11
11
  const { buildClientHttpUrl } = require('../../dd-trace/src/plugins/util/url')
12
12
  const log = require('../../dd-trace/src/log')
13
+ const { stripQueryAndFragment } = require('../../dd-trace/src/util')
13
14
  const { CLIENT_PORT_KEY, COMPONENT, ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
14
15
 
15
16
  const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
@@ -32,7 +33,7 @@ class HttpClientPlugin extends ClientPlugin {
32
33
  // A URL object (e.g. from the fetch integration) carries the query in
33
34
  // `options.search`, not `options.path`; keep it so url.full retains the query.
34
35
  const pathname = options.path || `${options.pathname || ''}${options.search || ''}`
35
- const path = pathname ? pathname.split(/[?#]/)[0] : '/'
36
+ const path = pathname ? stripQueryAndFragment(pathname) : '/'
36
37
  const uri = `${base}${path}`
37
38
 
38
39
  const allowed = this.config.filter(uri)
@@ -237,9 +237,8 @@ class JestPlugin extends CiPlugin {
237
237
 
238
238
  const testSuiteMetadata = {
239
239
  ...getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, 'jest'),
240
- // requestErrorTags from test env options may be undefined
241
- ...(requestErrorTags !== undefined && requestErrorTags !== null ? requestErrorTags : {}),
242
- ...(itrSkippingEnabledTags !== undefined && itrSkippingEnabledTags !== null ? itrSkippingEnabledTags : {}),
240
+ ...requestErrorTags,
241
+ ...itrSkippingEnabledTags,
243
242
  }
244
243
 
245
244
  if (_ddUnskippable) {
@@ -43,7 +43,8 @@ function getFormattedJestTestParameters (testParameters) {
43
43
 
44
44
  // @fast-check/jest appends a random seed to the reported test name. A test name that keeps changing
45
45
  // breaks some Test Optimization features, so normalize this narrow suffix regardless of import style.
46
- const SEED_SUFFIX_RE = /\s*\(with seed=-?\d+\)\s*$/i
46
+ // fast-check emits exactly one space before the suffix.
47
+ const SEED_SUFFIX_RE = / ?\(with seed=-?\d+\) ?$/i
47
48
 
48
49
  function removeSeedSuffixFromTestName (testName) {
49
50
  return testName.replace(SEED_SUFFIX_RE, '')
@@ -9,7 +9,7 @@ function getTokensFromLlmOutput (result) {
9
9
  const { llmOutput } = result
10
10
  if (!llmOutput) return tokens
11
11
 
12
- const tokenUsage = llmOutput.tokenUsage || llmOutput.usage_metadata || llmOutput.usage_metadata
12
+ const tokenUsage = llmOutput.tokenUsage || llmOutput.usage_metadata
13
13
  if (!tokenUsage) return tokens
14
14
 
15
15
  for (const tokenNames of [['input', 'prompt'], ['output', 'completion'], ['total']]) {
@@ -25,7 +25,7 @@ function getTokensFromLlmOutput (result) {
25
25
  }
26
26
 
27
27
  // assign total_tokens again in case it was improperly set the first time, or was not on tokenUsage
28
- tokens.total = tokens.total || tokens.input + tokens.output
28
+ tokens.total ||= tokens.input + tokens.output
29
29
 
30
30
  return tokens
31
31
  }
@@ -34,6 +34,8 @@ const {
34
34
  TEST_IS_MODIFIED,
35
35
  TEST_FINAL_STATUS,
36
36
  TEST_HAS_DYNAMIC_NAME,
37
+ TEST_FRAMEWORK_ADAPTER,
38
+ getTestSuiteExecutionKey,
37
39
  isModifiedTest,
38
40
  } = require('../../dd-trace/src/plugins/util/test')
39
41
  const { COMPONENT } = require('../../dd-trace/src/constants')
@@ -58,6 +60,12 @@ class MochaPlugin extends CiPlugin {
58
60
  this._testTitleToParams = {}
59
61
  this.sourceRoot = process.cwd()
60
62
 
63
+ this.addSub('ci:mocha:worker:configuration', ({ libraryConfig, repositoryRoot, testFramework }) => {
64
+ this.libraryConfig = libraryConfig
65
+ this.testFramework = testFramework
66
+ this._setRepositoryRoot(repositoryRoot)
67
+ })
68
+
61
69
  this.addSub('ci:mocha:test-suite:code-coverage', ({ coverageFiles, suiteFile }) => {
62
70
  if (!this.libraryConfig?.isCodeCoverageEnabled) {
63
71
  return
@@ -88,23 +96,33 @@ class MochaPlugin extends CiPlugin {
88
96
  })
89
97
 
90
98
  this.addBind('ci:mocha:test-suite:start', (ctx) => {
91
- const { testSuiteAbsolutePath, isUnskippable, isForcedToRun, itrCorrelationId } = ctx
99
+ const {
100
+ testSuiteAbsolutePath,
101
+ testSuiteExecutionId,
102
+ isUnskippable,
103
+ isForcedToRun,
104
+ itrCorrelationId,
105
+ } = ctx
92
106
 
93
107
  // If the test module span is undefined, the plugin has not been initialized correctly and we bail out
94
108
  if (!this.testModuleSpan) {
95
109
  return
96
110
  }
97
111
  const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.sourceRoot)
112
+ const testFramework = this.testFramework || this.constructor.id
98
113
  const testSuiteMetadata = {
99
114
  ...getTestSuiteCommonTags(
100
115
  this.command,
101
116
  this.frameworkVersion,
102
117
  testSuite,
103
- 'mocha'
118
+ testFramework
104
119
  ),
105
120
  ...this.getSessionRequestErrorTags(),
106
121
  ...this.getSessionItrSkippingEnabledTags(),
107
122
  }
123
+ if (this.testFrameworkAdapter) {
124
+ testSuiteMetadata[TEST_FRAMEWORK_ADAPTER] = this.testFrameworkAdapter
125
+ }
108
126
  if (isUnskippable) {
109
127
  testSuiteMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
110
128
  this.telemetry.count(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
@@ -144,8 +162,9 @@ class MochaPlugin extends CiPlugin {
144
162
  const store = storage('legacy').getStore()
145
163
  ctx.parentStore = store
146
164
  ctx.currentStore = { ...store, testSuiteSpan }
147
- this._testSuiteSpansByTestSuite.set(testSuite, testSuiteSpan)
148
- this._exportPendingWorkerTracesForTestSuite(testSuite)
165
+ const testSuiteKey = getTestSuiteExecutionKey(testSuite, testSuiteExecutionId)
166
+ this._testSuiteSpansByTestSuite.set(testSuiteKey, testSuiteSpan)
167
+ this._exportPendingWorkerTracesForTestSuite(testSuiteKey)
149
168
  })
150
169
 
151
170
  this.addSub('ci:mocha:test-suite:finish', ({ testSuiteSpan, status }) => {
@@ -203,8 +222,8 @@ class MochaPlugin extends CiPlugin {
203
222
  return ctx.currentStore
204
223
  })
205
224
 
206
- this.addSub('ci:mocha:worker:finish', () => {
207
- this.tracer._exporter.flush()
225
+ this.addSub('ci:mocha:worker:finish', ({ onDone } = {}) => {
226
+ this.tracer._exporter.flush(onDone)
208
227
  })
209
228
 
210
229
  this.addSub('ci:mocha:test:finish', ({
@@ -0,0 +1,74 @@
1
+ 'use strict'
2
+
3
+ const { storage } = require('../../datadog-core')
4
+ const Plugin = require('../../dd-trace/src/plugins/plugin')
5
+ const { MODEL_BASE_URL_STORE_KEY, OpenAIAgentsIntegration } = require('./integration')
6
+ const { DDOpenAIAgentsProcessor } = require('./processor')
7
+
8
+ const legacyStorage = storage('legacy')
9
+
10
+ /**
11
+ * Drives the openai-agents integration through agents-core's
12
+ * `TracingProcessor` interface. The instrumentation hook publishes the
13
+ * loaded `@openai/agents` module on a channel; this plugin subscribes
14
+ * during its constructor (which runs synchronously between `loadChannel`'s
15
+ * publish and the addHook callback) and registers the processor.
16
+ *
17
+ * The integration's `enabled` flag follows this plugin's configure()
18
+ * lifecycle. Each loaded version of the agents package replaces all processors
19
+ * via setTraceProcessors() on module load, so the plugin re-registers a
20
+ * fresh DDOpenAIAgentsProcessor for each module version that fires the channel.
21
+ */
22
+ class OpenaiAgentsPlugin extends Plugin {
23
+ static id = 'openai-agents'
24
+
25
+ #integration
26
+
27
+ constructor (tracer, tracerConfig) {
28
+ super(tracer, tracerConfig)
29
+ this.#integration = new OpenAIAgentsIntegration({
30
+ tracer: this.tracer,
31
+ config: tracerConfig,
32
+ })
33
+
34
+ // Register a new processor each time @openai/agents fires the channel.
35
+ // Each module version calls setTraceProcessors() on load (which replaces
36
+ // all processors), so we must re-register after every new version loads.
37
+ // The instrumentation's patchedMods WeakSet ensures each module instance
38
+ // fires the channel exactly once, so no duplicates accumulate.
39
+ this.addSub('apm:openai-agents:agents-core:loaded', ({ mod }) => {
40
+ const processor = new DDOpenAIAgentsProcessor(() => this.#integration)
41
+ if (typeof mod?.addTraceProcessor === 'function') {
42
+ mod.addTraceProcessor(processor)
43
+ } else {
44
+ mod.getGlobalTraceProvider().registerProcessor(processor)
45
+ }
46
+ })
47
+
48
+ // Activate the current agent's dd-trace span in legacyStorage for the
49
+ // duration of model response calls and stream iterator advancement. This
50
+ // makes the openai plugin's shimmer see the correct parent when it creates its
51
+ // openai.request span, so all spans land in the same trace.
52
+ this.addBind('apm:openai-agents:model:start', ({ agentsCoreSpanId, baseURL }) => {
53
+ const store = legacyStorage.getStore()
54
+ if (!this.#integration.enabled || !agentsCoreSpanId) return store
55
+ const ddSpan = this.#integration.getDDSpan(agentsCoreSpanId)
56
+ if (!ddSpan) return store
57
+ return { ...store, [MODEL_BASE_URL_STORE_KEY]: baseURL, span: ddSpan }
58
+ })
59
+
60
+ this.addBind('apm:openai-agents:tool:start', ({ agentsCoreSpan }) => {
61
+ const store = legacyStorage.getStore()
62
+ if (!this.#integration.enabled || !agentsCoreSpan) return store
63
+ const ddSpan = this.#integration.getOrStartToolSpan(agentsCoreSpan)
64
+ return ddSpan ? { ...store, span: ddSpan } : store
65
+ })
66
+ }
67
+
68
+ configure (config) {
69
+ super.configure(config)
70
+ this.#integration.configure(config)
71
+ }
72
+ }
73
+
74
+ module.exports = OpenaiAgentsPlugin