dd-trace 6.3.0 → 6.5.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 (207) hide show
  1. package/README.electron.md +7 -0
  2. package/README.md +17 -0
  3. package/ci/diagnose.js +2100 -0
  4. package/ci/init.js +23 -2
  5. package/ci/runbook.md +198 -0
  6. package/ci/test-optimization-validation/approval-artifacts.js +143 -0
  7. package/ci/test-optimization-validation/approval.js +299 -0
  8. package/ci/test-optimization-validation/artifact-id.js +20 -0
  9. package/ci/test-optimization-validation/bounded-json.js +121 -0
  10. package/ci/test-optimization-validation/ci-command-candidate.js +83 -0
  11. package/ci/test-optimization-validation/ci-discovery.js +181 -0
  12. package/ci/test-optimization-validation/ci-remediation.js +210 -0
  13. package/ci/test-optimization-validation/cli.js +903 -0
  14. package/ci/test-optimization-validation/command-blocker.js +81 -0
  15. package/ci/test-optimization-validation/command-output-policy.js +206 -0
  16. package/ci/test-optimization-validation/command-runner.js +707 -0
  17. package/ci/test-optimization-validation/command-suitability.js +471 -0
  18. package/ci/test-optimization-validation/executable-approval.js +48 -0
  19. package/ci/test-optimization-validation/executable.js +480 -0
  20. package/ci/test-optimization-validation/generated-file-policy.js +63 -0
  21. package/ci/test-optimization-validation/generated-files.js +351 -0
  22. package/ci/test-optimization-validation/generated-verifier.js +196 -0
  23. package/ci/test-optimization-validation/init-probe-preload.js +163 -0
  24. package/ci/test-optimization-validation/init-probe.js +246 -0
  25. package/ci/test-optimization-validation/late-initialization.js +63 -0
  26. package/ci/test-optimization-validation/local-command.js +163 -0
  27. package/ci/test-optimization-validation/manifest-loader.js +133 -0
  28. package/ci/test-optimization-validation/manifest-scaffold.js +738 -0
  29. package/ci/test-optimization-validation/manifest-schema.js +862 -0
  30. package/ci/test-optimization-validation/offline-fixtures.js +327 -0
  31. package/ci/test-optimization-validation/offline-output.js +406 -0
  32. package/ci/test-optimization-validation/payload-normalizer.js +72 -0
  33. package/ci/test-optimization-validation/plan-writer.js +1120 -0
  34. package/ci/test-optimization-validation/preflight-runner.js +114 -0
  35. package/ci/test-optimization-validation/redaction.js +331 -0
  36. package/ci/test-optimization-validation/report-writer.js +1508 -0
  37. package/ci/test-optimization-validation/safe-files.js +203 -0
  38. package/ci/test-optimization-validation/scenarios/auto-test-retries.js +159 -0
  39. package/ci/test-optimization-validation/scenarios/basic-reporting.js +657 -0
  40. package/ci/test-optimization-validation/scenarios/ci-wiring.js +780 -0
  41. package/ci/test-optimization-validation/scenarios/early-flake-detection.js +141 -0
  42. package/ci/test-optimization-validation/scenarios/helpers.js +539 -0
  43. package/ci/test-optimization-validation/scenarios/test-management.js +218 -0
  44. package/ci/test-optimization-validation/setup-runner.js +97 -0
  45. package/ci/test-optimization-validation/static-diagnosis.js +159 -0
  46. package/ci/test-optimization-validation/test-output.js +129 -0
  47. package/ci/test-optimization-validation-manifest.schema.json +1 -0
  48. package/ci/validate-test-optimization.js +3 -0
  49. package/ext/exporters.js +1 -0
  50. package/index.d.ts +121 -8
  51. package/index.electron.js +3 -0
  52. package/init.js +18 -0
  53. package/initialize.mjs +1 -1
  54. package/loader-hook.mjs +28 -18
  55. package/openfeature.d.ts +1 -0
  56. package/openfeature.js +4 -0
  57. package/package.json +15 -8
  58. package/packages/datadog-instrumentations/src/ai.js +37 -26
  59. package/packages/datadog-instrumentations/src/child_process.js +1 -1
  60. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -1
  61. package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +9 -3
  62. package/packages/datadog-instrumentations/src/cucumber.js +24 -10
  63. package/packages/datadog-instrumentations/src/cypress-config.js +398 -52
  64. package/packages/datadog-instrumentations/src/express.js +20 -2
  65. package/packages/datadog-instrumentations/src/fastify.js +7 -11
  66. package/packages/datadog-instrumentations/src/grpc/server.js +18 -0
  67. package/packages/datadog-instrumentations/src/helpers/hook.js +27 -6
  68. package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +8 -8
  69. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +28 -2
  70. package/packages/datadog-instrumentations/src/helpers/router-helper.js +8 -8
  71. package/packages/datadog-instrumentations/src/http2/server.js +143 -17
  72. package/packages/datadog-instrumentations/src/jest.js +36 -4
  73. package/packages/datadog-instrumentations/src/mariadb.js +1 -1
  74. package/packages/datadog-instrumentations/src/mocha/main.js +0 -2
  75. package/packages/datadog-instrumentations/src/mocha/utils.js +0 -4
  76. package/packages/datadog-instrumentations/src/mongodb.js +3 -3
  77. package/packages/datadog-instrumentations/src/mongoose.js +3 -3
  78. package/packages/datadog-instrumentations/src/mquery.js +2 -2
  79. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  80. package/packages/datadog-instrumentations/src/next.js +24 -0
  81. package/packages/datadog-instrumentations/src/nyc.js +0 -2
  82. package/packages/datadog-instrumentations/src/oracledb.js +2 -2
  83. package/packages/datadog-instrumentations/src/pg.js +2 -2
  84. package/packages/datadog-instrumentations/src/playwright.js +159 -22
  85. package/packages/datadog-instrumentations/src/process.js +3 -0
  86. package/packages/datadog-instrumentations/src/router.js +191 -106
  87. package/packages/datadog-instrumentations/src/selenium.js +52 -26
  88. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +2 -2
  89. package/packages/datadog-instrumentations/src/vitest-main.js +0 -2
  90. package/packages/datadog-instrumentations/src/ws.js +2 -1
  91. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +2 -2
  92. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +2 -1
  93. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +41 -16
  94. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +21 -21
  95. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +14 -8
  96. package/packages/datadog-plugin-aws-sdk/src/util.js +2 -24
  97. package/packages/datadog-plugin-cucumber/src/index.js +1 -1
  98. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +24 -62
  99. package/packages/datadog-plugin-cypress/src/index.js +6 -1
  100. package/packages/datadog-plugin-cypress/src/support.js +92 -26
  101. package/packages/datadog-plugin-electron/src/ipc.js +1 -1
  102. package/packages/datadog-plugin-graphql/src/execute.js +177 -59
  103. package/packages/datadog-plugin-graphql/src/parse.js +22 -1
  104. package/packages/datadog-plugin-graphql/src/request.js +32 -1
  105. package/packages/datadog-plugin-graphql/src/utils.js +42 -0
  106. package/packages/datadog-plugin-graphql/src/validate.js +15 -3
  107. package/packages/datadog-plugin-http2/src/client.js +1 -1
  108. package/packages/datadog-plugin-http2/src/server.js +38 -6
  109. package/packages/datadog-plugin-jest/src/util.js +21 -6
  110. package/packages/datadog-plugin-langchain/src/handlers/embedding.js +2 -1
  111. package/packages/datadog-plugin-langchain/src/handlers/language_models.js +2 -1
  112. package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
  113. package/packages/datadog-plugin-playwright/src/index.js +177 -64
  114. package/packages/datadog-plugin-router/src/index.js +11 -2
  115. package/packages/datadog-plugin-selenium/src/index.js +5 -36
  116. package/packages/datadog-plugin-vitest/src/index.js +4 -2
  117. package/packages/datadog-plugin-ws/src/close.js +2 -1
  118. package/packages/datadog-plugin-ws/src/producer.js +2 -1
  119. package/packages/datadog-plugin-ws/src/receiver.js +2 -1
  120. package/packages/datadog-plugin-ws/src/server.js +2 -1
  121. package/packages/dd-trace/index.electron.js +3 -0
  122. package/packages/dd-trace/index.js +2 -37
  123. package/packages/dd-trace/src/aiguard/sdk.js +1 -1
  124. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -2
  125. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +3 -1
  126. package/packages/dd-trace/src/azure_metadata.js +2 -1
  127. package/packages/dd-trace/src/bootstrap.js +39 -0
  128. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +93 -28
  129. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
  130. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +160 -0
  131. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +288 -0
  132. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/payload-projection.js +84 -0
  133. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +369 -0
  134. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +60 -0
  135. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +55 -5
  136. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +22 -6
  137. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +5 -0
  138. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +62 -7
  139. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -2
  140. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +6 -2
  141. package/packages/dd-trace/src/ci-visibility/rum.js +7 -0
  142. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
  143. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
  144. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +137 -9
  145. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +173 -9
  146. package/packages/dd-trace/src/ci-visibility/test-screenshot.js +90 -0
  147. package/packages/dd-trace/src/config/generated-config-types.d.ts +20 -0
  148. package/packages/dd-trace/src/config/helper.js +1 -0
  149. package/packages/dd-trace/src/config/index.js +10 -0
  150. package/packages/dd-trace/src/config/supported-configurations.json +83 -0
  151. package/packages/dd-trace/src/constants.js +7 -0
  152. package/packages/dd-trace/src/datastreams/pathway.js +6 -4
  153. package/packages/dd-trace/src/exporter.js +2 -0
  154. package/packages/dd-trace/src/exporters/common/client-library-headers.js +21 -0
  155. package/packages/dd-trace/src/exporters/common/request.js +59 -30
  156. package/packages/dd-trace/src/exporters/common/url.js +15 -1
  157. package/packages/dd-trace/src/feature-registry.js +29 -0
  158. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
  159. package/packages/dd-trace/src/llmobs/experiments/client.js +113 -0
  160. package/packages/dd-trace/src/llmobs/experiments/dataset.js +154 -0
  161. package/packages/dd-trace/src/llmobs/experiments/experiment.js +283 -0
  162. package/packages/dd-trace/src/llmobs/experiments/index.js +152 -0
  163. package/packages/dd-trace/src/llmobs/experiments/noop.js +30 -0
  164. package/packages/dd-trace/src/llmobs/experiments/result.js +34 -0
  165. package/packages/dd-trace/src/llmobs/index.js +10 -2
  166. package/packages/dd-trace/src/llmobs/noop.js +6 -0
  167. package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +20 -3
  168. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +2 -2
  169. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
  170. package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +8 -0
  171. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +48 -14
  172. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +43 -0
  173. package/packages/dd-trace/src/llmobs/sdk.js +17 -0
  174. package/packages/dd-trace/src/llmobs/tagger.js +79 -7
  175. package/packages/dd-trace/src/llmobs/telemetry.js +2 -1
  176. package/packages/dd-trace/src/llmobs/util.js +32 -0
  177. package/packages/dd-trace/src/noop/proxy.js +5 -4
  178. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +322 -0
  179. package/packages/dd-trace/src/openfeature/configuration_source.js +90 -0
  180. package/packages/dd-trace/src/openfeature/flagging_provider.js +14 -23
  181. package/packages/dd-trace/src/openfeature/index.js +0 -2
  182. package/packages/dd-trace/src/openfeature/noop.js +1 -28
  183. package/packages/dd-trace/src/openfeature/register.js +35 -0
  184. package/packages/dd-trace/src/openfeature/remote_config.js +15 -18
  185. package/packages/dd-trace/src/openfeature/require-provider.js +18 -0
  186. package/packages/dd-trace/src/opentelemetry/span-ending-hook.js +10 -0
  187. package/packages/dd-trace/src/opentelemetry/span.js +5 -0
  188. package/packages/dd-trace/src/opentracing/propagation/log.js +11 -2
  189. package/packages/dd-trace/src/opentracing/propagation/text_map.js +80 -14
  190. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +10 -1
  191. package/packages/dd-trace/src/opentracing/tracer.js +7 -1
  192. package/packages/dd-trace/src/plugins/ci_plugin.js +20 -6
  193. package/packages/dd-trace/src/plugins/util/git.js +3 -2
  194. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +29 -5
  195. package/packages/dd-trace/src/plugins/util/test.js +65 -8
  196. package/packages/dd-trace/src/plugins/util/web.js +12 -0
  197. package/packages/dd-trace/src/proxy.js +99 -10
  198. package/packages/dd-trace/src/span_processor.js +5 -0
  199. package/packages/dd-trace/src/standalone/index.js +0 -36
  200. package/packages/dd-trace/src/telemetry/send-data.js +2 -2
  201. package/packages/dd-trace/src/util.js +26 -0
  202. package/vendor/dist/@apm-js-collab/code-transformer/index.js +1 -1
  203. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  204. package/vendor/dist/protobufjs/index.js +1 -1
  205. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  206. package/vendor/dist/shell-quote/index.js +1 -1
  207. package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +0 -17
@@ -1,5 +1,7 @@
1
1
  'use strict'
2
2
 
3
+ const { getSegment } = require('../../../util')
4
+
3
5
  function addMetricsToSpan (rootSpan, metrics, tagPrefix) {
4
6
  if (!rootSpan?.addTags || !metrics) return
5
7
 
@@ -44,7 +46,7 @@ function filterTags (tags) {
44
46
  }
45
47
 
46
48
  function processTagValue (tags) {
47
- return tags.map(tag => tag.includes(':') ? tag.split(':')[1] : tag)
49
+ return tags.map(tag => tag.includes(':') ? getSegment(tag, ':', 1) : tag)
48
50
  .join('_').replaceAll('.', '_')
49
51
  }
50
52
 
@@ -6,10 +6,11 @@ const os = require('os')
6
6
  const getConfig = require('./config')
7
7
  const { getEnvironmentVariable } = require('./config/helper')
8
8
  const { getIsAzureFunction } = require('./serverless')
9
+ const { getSegment } = require('./util')
9
10
 
10
11
  function extractSubscriptionID (ownerName) {
11
12
  if (ownerName !== undefined) {
12
- const subId = ownerName.split('+')[0].trim()
13
+ const subId = getSegment(ownerName, '+', 0).trim()
13
14
  if (subId.length > 0) {
14
15
  return subId
15
16
  }
@@ -0,0 +1,39 @@
1
+ 'use strict'
2
+
3
+ if (!global._ddtrace) {
4
+ const ddTraceSymbol = Symbol.for('dd-trace')
5
+
6
+ // Set up beforeExitHandlers before loading the tracer so that modules loaded
7
+ // during require('./src') can register handlers.
8
+ Object.defineProperty(globalThis, ddTraceSymbol, {
9
+ value: {
10
+ beforeExitHandlers: new Set(),
11
+ },
12
+ enumerable: false,
13
+ configurable: true,
14
+ writable: false,
15
+ })
16
+
17
+ process.once('beforeExit', function mainBeforeExit () {
18
+ if (globalThis[ddTraceSymbol]?.beforeExitHandlers) {
19
+ for (const handler of globalThis[ddTraceSymbol].beforeExitHandlers) {
20
+ handler()
21
+ }
22
+ }
23
+ })
24
+
25
+ const TracerProxy = require('.')
26
+
27
+ Object.defineProperty(global, '_ddtrace', {
28
+ value: new TracerProxy(),
29
+ enumerable: false,
30
+ configurable: true,
31
+ writable: true,
32
+ })
33
+ }
34
+
35
+ module.exports = global._ddtrace
36
+ // Static aliases so cjs-module-lexer surfaces them as ESM named exports
37
+ // (`import { tracer } from 'dd-trace'`).
38
+ module.exports.tracer = global._ddtrace
39
+ module.exports.default = global._ddtrace
@@ -7,11 +7,25 @@ const log = require('../../log')
7
7
  const { getEnvironmentVariables } = require('../../config/helper')
8
8
  const getDebuggerConfig = require('../../debugger/config')
9
9
 
10
- const probeIdToResolveBreakpointSet = new Map()
11
- const probeIdToResolveBreakpointRemove = new Map()
12
10
  const drainRequestIdToResolveBreakpointHit = new Map()
13
11
 
12
+ /**
13
+ * @typedef {object} ProbeState
14
+ * @property {string} locationKey
15
+ * @property {(breakpoint: object) => void} onHitBreakpoint
16
+ * @property {Promise<void>|undefined} removePromise
17
+ * @property {(() => void)|undefined} resolveRemove
18
+ * @property {(() => void)|undefined} resolveSet
19
+ * @property {Promise<void>} setPromise
20
+ * @property {boolean} setPosted
21
+ */
22
+
14
23
  class TestVisDynamicInstrumentation {
24
+ /** @type {Map<string, Promise<void>>} */
25
+ #pendingProbeRemovalByLocation = new Map()
26
+ /** @type {Map<string, ProbeState>} */
27
+ #probeStateById = new Map()
28
+
15
29
  /**
16
30
  * @param {import('../../config/config-base')} config - Tracer configuration
17
31
  */
@@ -24,37 +38,88 @@ class TestVisDynamicInstrumentation {
24
38
  this.breakpointSetChannel = new MessageChannel()
25
39
  this.breakpointHitChannel = new MessageChannel()
26
40
  this.breakpointRemoveChannel = new MessageChannel()
27
- this.onHitBreakpointByProbeId = new Map()
28
41
  }
29
42
 
43
+ /**
44
+ * @param {string|undefined} probeId
45
+ */
30
46
  removeProbe (probeId) {
31
- return new Promise(resolve => {
32
- this.breakpointRemoveChannel.port2.postMessage(probeId)
47
+ const probeState = probeId === undefined ? undefined : this.#probeStateById.get(probeId)
48
+ if (!probeState) return Promise.resolve()
49
+ if (probeState.removePromise) return probeState.removePromise
50
+
51
+ if (!probeState.setPosted) {
52
+ this.#probeStateById.delete(probeId)
53
+ probeState.resolveSet?.()
54
+ probeState.resolveSet = undefined
55
+ return Promise.resolve()
56
+ }
33
57
 
34
- probeIdToResolveBreakpointRemove.set(probeId, resolve)
58
+ const postRemoval = () => new Promise(resolve => {
59
+ probeState.resolveRemove = resolve
60
+ this.breakpointRemoveChannel.port2.postMessage(probeId)
61
+ })
62
+ const removeAcknowledgedPromise = probeState.setPromise.then(postRemoval)
63
+ const removePromise = removeAcknowledgedPromise.then(() => this.waitForInFlightBreakpointHits())
64
+ probeState.removePromise = removePromise
65
+ this.#pendingProbeRemovalByLocation.set(probeState.locationKey, removeAcknowledgedPromise)
66
+ removeAcknowledgedPromise.then(() => {
67
+ if (this.#pendingProbeRemovalByLocation.get(probeState.locationKey) === removeAcknowledgedPromise) {
68
+ this.#pendingProbeRemovalByLocation.delete(probeState.locationKey)
69
+ }
35
70
  })
71
+ removePromise.then(() => {
72
+ if (this.#probeStateById.get(probeId) === probeState) {
73
+ this.#probeStateById.delete(probeId)
74
+ }
75
+ })
76
+ return removePromise
36
77
  }
37
78
 
38
- // Return 2 elements:
39
- // 1. Probe ID
40
- // 2. Promise that's resolved when the breakpoint is set
79
+ /**
80
+ * @param {{ file: string, line: number }} location
81
+ * @param {(breakpoint: object) => void} onHitBreakpoint
82
+ */
41
83
  addLineProbe ({ file, line }, onHitBreakpoint) {
42
84
  if (!this.worker) { // not init yet
43
85
  this.start()
44
86
  }
45
87
  const probeId = randomUUID()
88
+ const locationKey = `${file}:${line}`
89
+ const pendingRemoval = this.#pendingProbeRemovalByLocation.get(locationKey)
46
90
 
47
- this.breakpointSetChannel.port2.postMessage(
48
- { id: probeId, file, line }
49
- )
50
-
51
- this.onHitBreakpointByProbeId.set(probeId, onHitBreakpoint)
91
+ let resolveSet
92
+ const setProbePromise = new Promise(resolve => {
93
+ resolveSet = resolve
94
+ })
95
+ const probeState = {
96
+ locationKey,
97
+ onHitBreakpoint,
98
+ removePromise: undefined,
99
+ resolveRemove: undefined,
100
+ resolveSet,
101
+ setPromise: setProbePromise,
102
+ setPosted: false,
103
+ }
104
+ this.#probeStateById.set(probeId, probeState)
105
+
106
+ const setProbe = () => {
107
+ if (this.#probeStateById.get(probeId) === probeState) {
108
+ probeState.setPosted = true
109
+ this.breakpointSetChannel.port2.postMessage(
110
+ { id: probeId, file, line }
111
+ )
112
+ }
113
+ }
114
+ if (pendingRemoval) {
115
+ pendingRemoval.then(setProbe)
116
+ } else {
117
+ setProbe()
118
+ }
52
119
 
53
120
  return [
54
121
  probeId,
55
- new Promise(resolve => {
56
- probeIdToResolveBreakpointSet.set(probeId, resolve)
57
- }),
122
+ setProbePromise,
58
123
  ]
59
124
  }
60
125
 
@@ -139,10 +204,10 @@ class TestVisDynamicInstrumentation {
139
204
  this.worker.unref?.()
140
205
 
141
206
  this.breakpointSetChannel.port2.on('message', (probeId) => {
142
- const resolve = probeIdToResolveBreakpointSet.get(probeId)
143
- if (resolve) {
144
- resolve()
145
- probeIdToResolveBreakpointSet.delete(probeId)
207
+ const probeState = this.#probeStateById.get(probeId)
208
+ if (probeState?.resolveSet) {
209
+ probeState.resolveSet()
210
+ probeState.resolveSet = undefined
146
211
  }
147
212
  }).unref?.()
148
213
 
@@ -157,19 +222,19 @@ class TestVisDynamicInstrumentation {
157
222
  }
158
223
 
159
224
  const { probe: { id: probeId } } = snapshot
160
- const onHit = this.onHitBreakpointByProbeId.get(probeId)
161
- if (onHit) {
162
- onHit({ snapshot })
225
+ const probeState = this.#probeStateById.get(probeId)
226
+ if (probeState) {
227
+ probeState.onHitBreakpoint({ snapshot })
163
228
  } else {
164
229
  log.warn('Received a breakpoint hit for an unknown probe')
165
230
  }
166
231
  }).unref?.()
167
232
 
168
233
  this.breakpointRemoveChannel.port2.on('message', (probeId) => {
169
- const resolve = probeIdToResolveBreakpointRemove.get(probeId)
170
- if (resolve) {
171
- resolve()
172
- probeIdToResolveBreakpointRemove.delete(probeId)
234
+ const probeState = this.#probeStateById.get(probeId)
235
+ if (probeState?.resolveRemove) {
236
+ probeState.resolveRemove()
237
+ probeState.resolveRemove = undefined
173
238
  }
174
239
  }).unref?.()
175
240
  }
@@ -60,7 +60,7 @@ function parseJsonResponse (rawJson) {
60
60
  function parseKnownTestsResponse (rawJson, options = {}) {
61
61
  const parsedResponse = parseJsonResponse(rawJson)
62
62
  if (options.validateRequiredFields) {
63
- validateKnownTestsResponse(parsedResponse)
63
+ validateKnownTestsResponse(parsedResponse, options)
64
64
  }
65
65
  const { data: { attributes: { tests } } } = parsedResponse
66
66
  return tests
@@ -0,0 +1,160 @@
1
+ 'use strict'
2
+
3
+ /* eslint-disable eslint-rules/eslint-process-env */
4
+
5
+ const TestOptimizationHttpCache = require('../../test-optimization-http-cache').TestOptimizationHttpCache
6
+ const CiVisibilityExporter = require('../ci-visibility-exporter')
7
+ const { CiValidationSink } = require('./sink')
8
+ const CiValidationWriter = require('./writer')
9
+
10
+ const VALIDATION_MANIFEST_ENV = '_DD_TEST_OPTIMIZATION_VALIDATION_MANIFEST_FILE'
11
+ const VALIDATION_OUTPUT_ENV = '_DD_TEST_OPTIMIZATION_VALIDATION_OUTPUT_DIR'
12
+ const VALIDATION_CAPTURE_MODE_ENV = '_DD_TEST_OPTIMIZATION_VALIDATION_CAPTURE_MODE'
13
+
14
+ class CiValidationExporter extends CiVisibilityExporter {
15
+ /**
16
+ * Creates an immediately available cache-only Test Optimization exporter.
17
+ *
18
+ * @param {object} config tracer configuration
19
+ */
20
+ constructor (config) {
21
+ const validationManifestPath = process.env[VALIDATION_MANIFEST_ENV]
22
+ const validationOutputRoot = process.env[VALIDATION_OUTPUT_ENV]
23
+ if (!validationManifestPath) {
24
+ throw new Error('Offline Test Optimization validation requires an explicit private manifest path.')
25
+ }
26
+ if (!validationOutputRoot) {
27
+ throw new Error('Offline Test Optimization validation requires an explicit private output root.')
28
+ }
29
+ const cache = new TestOptimizationHttpCache({
30
+ validationManifestPath,
31
+ })
32
+ super(config, { cacheOnly: true, testOptimizationHttpCache: cache })
33
+
34
+ this._sink = new CiValidationSink(validationOutputRoot, {
35
+ captureMode: process.env[VALIDATION_CAPTURE_MODE_ENV] || 'strict',
36
+ })
37
+ this._writer = new CiValidationWriter({ sink: this._sink, tags: config.tags })
38
+ this._isInitialized = true
39
+ this._isGzipCompatible = false
40
+ this._resolveCanUseCiVisProtocol(true)
41
+ this._resolveGit()
42
+ this.exportUncodedTraces()
43
+
44
+ this._finalizeValidation = () => this.flush(() => this._sink.writeSummary())
45
+ globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(this._finalizeValidation)
46
+ process.once('exit', this._finalizeValidation)
47
+ }
48
+
49
+ /**
50
+ * Loads library settings from the validator-controlled cache.
51
+ *
52
+ * @param {object} testConfiguration test configuration identity
53
+ * @param {Function} callback completion callback
54
+ */
55
+ getLibraryConfiguration (testConfiguration, callback) {
56
+ super.getLibraryConfiguration(testConfiguration, (err, configuration) => {
57
+ this._sink.writeInputResult('settings', err)
58
+ if (err) process.exitCode = 1
59
+ callback(err, configuration)
60
+ })
61
+ }
62
+
63
+ /**
64
+ * Loads known tests from the validator-controlled cache.
65
+ *
66
+ * @param {object} testConfiguration test configuration identity
67
+ * @param {Function} callback completion callback
68
+ */
69
+ getKnownTests (testConfiguration, callback) {
70
+ super.getKnownTests(testConfiguration, (err, tests) => {
71
+ this._sink.writeInputResult('known_tests', err)
72
+ if (err) process.exitCode = 1
73
+ callback(err, tests)
74
+ })
75
+ }
76
+
77
+ /**
78
+ * Loads skippable suites from the validator-controlled cache.
79
+ *
80
+ * @param {object} testConfiguration test configuration identity
81
+ * @param {Function} callback completion callback
82
+ */
83
+ getSkippableSuites (testConfiguration, callback) {
84
+ super.getSkippableSuites(testConfiguration, (err, suites, correlationId, coverage) => {
85
+ this._sink.writeInputResult('skippable_tests', err)
86
+ if (err) process.exitCode = 1
87
+ callback(err, suites, correlationId, coverage)
88
+ })
89
+ }
90
+
91
+ /**
92
+ * Loads managed tests from the validator-controlled cache.
93
+ *
94
+ * @param {object} testConfiguration test configuration identity
95
+ * @param {Function} callback completion callback
96
+ */
97
+ getTestManagementTests (testConfiguration, callback) {
98
+ super.getTestManagementTests(testConfiguration, (err, tests) => {
99
+ this._sink.writeInputResult('test_management', err)
100
+ if (err) process.exitCode = 1
101
+ callback(err, tests)
102
+ })
103
+ }
104
+
105
+ /**
106
+ * Resolves the inherited git-upload gate without performing an upload.
107
+ *
108
+ * @returns {void}
109
+ */
110
+ sendGitMetadata () {
111
+ this._resolveGit()
112
+ }
113
+
114
+ /**
115
+ * Drops debugger logs in offline validation mode.
116
+ *
117
+ * @returns {void}
118
+ */
119
+ exportDiLogs () {}
120
+
121
+ /**
122
+ * Reports that code coverage is outside the offline validator's scope.
123
+ *
124
+ * @returns {boolean} always false
125
+ */
126
+ canReportCodeCoverage () {
127
+ return false
128
+ }
129
+
130
+ /**
131
+ * Rejects coverage report upload in offline validation mode.
132
+ *
133
+ * @param {object} options ignored upload options
134
+ * @param {Function} callback completion callback
135
+ */
136
+ uploadCoverageReport (options, callback) {
137
+ callback(new Error('Coverage report upload is disabled during offline Test Optimization validation.'))
138
+ }
139
+
140
+ /**
141
+ * Reports that screenshot upload is unavailable.
142
+ *
143
+ * @returns {boolean} always false
144
+ */
145
+ canUploadTestScreenshots () {
146
+ return false
147
+ }
148
+
149
+ /**
150
+ * Rejects screenshot upload in offline validation mode.
151
+ *
152
+ * @param {object} options ignored upload options
153
+ * @param {Function} callback completion callback
154
+ */
155
+ uploadTestScreenshot (options, callback) {
156
+ callback(new Error('Screenshot upload is disabled during offline Test Optimization validation.'))
157
+ }
158
+ }
159
+
160
+ module.exports = CiValidationExporter