dd-trace 6.20.1 → 6.22.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 (225) hide show
  1. package/ci/diagnose.js +9 -14
  2. package/ci/init.js +1 -2
  3. package/ci/test-optimization-validation/ci-discovery.js +9 -4
  4. package/ci/test-optimization-validation/executable.js +1 -5
  5. package/ci/test-optimization-validation/framework-adapters/cypress.js +1 -4
  6. package/ci/test-optimization-validation/framework-adapters/vitest.js +1 -1
  7. package/ci/test-optimization-validation/generated-files.js +6 -4
  8. package/ci/test-optimization-validation/generated-test-contract.js +7 -3
  9. package/ci/test-optimization-validation/manifest-scaffold.js +7 -2
  10. package/ci/test-optimization-validation/manifest-schema.js +6 -7
  11. package/ci/test-optimization-validation/report-writer.js +6 -2
  12. package/ci/test-optimization-validation/runner-command.js +2 -4
  13. package/ci/test-optimization-validation/runner-contract.js +1 -2
  14. package/ci/test-optimization-validation/scenarios/auto-test-retries.js +1 -15
  15. package/ci/vitest-no-worker-init-setup.mjs +10 -7
  16. package/index.d.ts +116 -17
  17. package/initialize.mjs +1 -3
  18. package/openfeature/rules-based.d.ts +11 -0
  19. package/openfeature/rules-based.js +7 -0
  20. package/package.json +13 -11
  21. package/packages/datadog-core/src/storage.js +16 -0
  22. package/packages/datadog-esbuild/index.js +18 -12
  23. package/packages/datadog-instrumentations/src/aerospike.js +3 -3
  24. package/packages/datadog-instrumentations/src/ai.js +3 -3
  25. package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +0 -6
  26. package/packages/datadog-instrumentations/src/aws-sdk.js +21 -13
  27. package/packages/datadog-instrumentations/src/cassandra-driver.js +25 -20
  28. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +9 -23
  29. package/packages/datadog-instrumentations/src/cucumber.js +48 -33
  30. package/packages/datadog-instrumentations/src/elasticsearch.js +1 -5
  31. package/packages/datadog-instrumentations/src/electron.js +6 -6
  32. package/packages/datadog-instrumentations/src/fastify.js +13 -4
  33. package/packages/datadog-instrumentations/src/fs.js +2 -2
  34. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +9 -5
  35. package/packages/datadog-instrumentations/src/grpc/client.js +2 -0
  36. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +2 -2
  37. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +1 -2
  38. package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
  39. package/packages/datadog-instrumentations/src/helpers/register.js +36 -1
  40. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -0
  41. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +87 -6
  42. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +5 -6
  43. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +48 -31
  44. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +64 -11
  45. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
  46. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +42 -4
  47. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +7 -10
  48. package/packages/datadog-instrumentations/src/ioredis.js +7 -5
  49. package/packages/datadog-instrumentations/src/iovalkey.js +7 -5
  50. package/packages/datadog-instrumentations/src/jest.js +122 -11
  51. package/packages/datadog-instrumentations/src/knex.js +9 -5
  52. package/packages/datadog-instrumentations/src/mariadb-bundle.js +3 -3
  53. package/packages/datadog-instrumentations/src/mocha/common.js +20 -8
  54. package/packages/datadog-instrumentations/src/mocha/main.js +140 -43
  55. package/packages/datadog-instrumentations/src/mocha/utils.js +127 -38
  56. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +61 -34
  57. package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
  58. package/packages/datadog-instrumentations/src/mongodb-core.js +3 -3
  59. package/packages/datadog-instrumentations/src/mongoose.js +3 -3
  60. package/packages/datadog-instrumentations/src/nova-sonic/audio.js +173 -0
  61. package/packages/datadog-instrumentations/src/nova-sonic/index.js +209 -0
  62. package/packages/datadog-instrumentations/src/nova-sonic/session.js +483 -0
  63. package/packages/datadog-instrumentations/src/openai-realtime/index.js +18 -6
  64. package/packages/datadog-instrumentations/src/openai-realtime/session.js +1 -1
  65. package/packages/datadog-instrumentations/src/openai.js +7 -0
  66. package/packages/datadog-instrumentations/src/pino.js +5 -6
  67. package/packages/datadog-instrumentations/src/playwright.js +3 -0
  68. package/packages/datadog-instrumentations/src/redis.js +27 -13
  69. package/packages/datadog-instrumentations/src/router.js +30 -0
  70. package/packages/datadog-instrumentations/src/rum-browser-scripts.js +2 -6
  71. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +7 -5
  72. package/packages/datadog-instrumentations/src/vitest-main.js +9 -17
  73. package/packages/datadog-instrumentations/src/vitest-util.js +2 -2
  74. package/packages/datadog-instrumentations/src/vitest-worker.js +1 -2
  75. package/packages/datadog-instrumentations/src/vitest.js +2 -2
  76. package/packages/datadog-instrumentations/src/webdriverio.js +118 -21
  77. package/packages/datadog-instrumentations/src/ws.js +1 -4
  78. package/packages/datadog-plugin-amqplib/src/client.js +1 -2
  79. package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -5
  80. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/handler.js +1 -2
  81. package/packages/datadog-plugin-aws-sdk/src/base.js +5 -8
  82. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +18 -0
  83. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/sonic.js +45 -0
  84. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -3
  85. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -5
  86. package/packages/datadog-plugin-azure-durable-functions/src/index.js +5 -4
  87. package/packages/datadog-plugin-azure-functions/src/index.js +5 -3
  88. package/packages/datadog-plugin-claude-agent-sdk/src/index.js +0 -2
  89. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +18 -5
  90. package/packages/datadog-plugin-cypress/src/index.js +6 -6
  91. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -2
  92. package/packages/datadog-plugin-cypress/src/support.js +1 -4
  93. package/packages/datadog-plugin-express/src/code_origin.js +1 -2
  94. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
  95. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
  96. package/packages/datadog-plugin-graphql/src/execute.js +5 -5
  97. package/packages/datadog-plugin-grpc/src/util.js +1 -2
  98. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -2
  99. package/packages/datadog-plugin-mocha/src/index.js +223 -39
  100. package/packages/datadog-plugin-mocha/src/webdriverio-video.js +453 -0
  101. package/packages/datadog-plugin-mongodb-core/src/query.js +8 -5
  102. package/packages/datadog-plugin-next/src/index.js +1 -2
  103. package/packages/datadog-plugin-openai/src/tracing.js +5 -2
  104. package/packages/datadog-plugin-openai-agents/src/integration.js +6 -2
  105. package/packages/datadog-plugin-openai-agents/src/processor.js +2 -4
  106. package/packages/datadog-plugin-postgres/src/index.js +24 -0
  107. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -5
  108. package/packages/datadog-plugin-rhea/src/consumer.js +1 -4
  109. package/packages/datadog-plugin-vitest/src/index.js +5 -2
  110. package/packages/datadog-shimmer/src/shimmer.js +5 -4
  111. package/packages/datadog-webpack/index.js +55 -43
  112. package/packages/datadog-webpack/src/loader.js +56 -8
  113. package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -4
  114. package/packages/dd-trace/src/aiguard/messages/utils.js +1 -2
  115. package/packages/dd-trace/src/aiguard/redaction.js +8 -2
  116. package/packages/dd-trace/src/appsec/api_security/normalized-route.js +3 -2
  117. package/packages/dd-trace/src/appsec/api_security/sampler.js +2 -6
  118. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -9
  119. package/packages/dd-trace/src/appsec/handlers/http-request.js +3 -9
  120. package/packages/dd-trace/src/appsec/handlers/http-response.js +7 -2
  121. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -3
  122. package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +1 -4
  123. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +7 -1
  124. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -3
  125. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -3
  126. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +1 -6
  127. package/packages/dd-trace/src/appsec/lambda.js +1 -3
  128. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +37 -27
  129. package/packages/dd-trace/src/appsec/rasp/lfi.js +9 -5
  130. package/packages/dd-trace/src/appsec/reporter.js +21 -1
  131. package/packages/dd-trace/src/appsec/stack_trace.js +1 -2
  132. package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +3 -6
  133. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +1 -1
  134. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +13 -7
  135. package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +1 -2
  136. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +2 -8
  137. package/packages/dd-trace/src/ci-visibility/resolve-runfile-path.js +54 -0
  138. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +5 -8
  139. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +2 -53
  140. package/packages/dd-trace/src/config/config-types.d.ts +2 -2
  141. package/packages/dd-trace/src/config/defaults.js +5 -5
  142. package/packages/dd-trace/src/config/generated-config-types.d.ts +8 -0
  143. package/packages/dd-trace/src/config/helper.js +34 -3
  144. package/packages/dd-trace/src/config/index.js +10 -9
  145. package/packages/dd-trace/src/config/normalize-service.js +1 -1
  146. package/packages/dd-trace/src/config/parsers.js +2 -2
  147. package/packages/dd-trace/src/config/supported-configurations.json +35 -0
  148. package/packages/dd-trace/src/datastreams/processor.js +3 -2
  149. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -4
  150. package/packages/dd-trace/src/debugger/constants.js +1 -0
  151. package/packages/dd-trace/src/debugger/devtools_client/index.js +5 -3
  152. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +17 -12
  153. package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -2
  154. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -0
  155. package/packages/dd-trace/src/debugger/devtools_client/worker-error.js +21 -0
  156. package/packages/dd-trace/src/debugger/guardrail-metrics.js +2 -2
  157. package/packages/dd-trace/src/debugger/index.js +24 -2
  158. package/packages/dd-trace/src/debugger/probe_sampler.js +108 -11
  159. package/packages/dd-trace/src/dogstatsd.js +1 -1
  160. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  161. package/packages/dd-trace/src/exporters/common/request.js +2 -5
  162. package/packages/dd-trace/src/exporters/common/url.js +1 -1
  163. package/packages/dd-trace/src/id.js +15 -5
  164. package/packages/dd-trace/src/lambda/handler.js +179 -19
  165. package/packages/dd-trace/src/lambda/index.js +15 -1
  166. package/packages/dd-trace/src/lambda/runtime/patch.js +34 -7
  167. package/packages/dd-trace/src/llmobs/agent-manifest.js +296 -0
  168. package/packages/dd-trace/src/llmobs/audio-utils.js +3 -2
  169. package/packages/dd-trace/src/llmobs/constants/tags.js +13 -0
  170. package/packages/dd-trace/src/llmobs/experiments/experiment.js +1 -1
  171. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +15 -0
  172. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +1 -2
  173. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -3
  174. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
  175. package/packages/dd-trace/src/llmobs/plugins/nova-sonic.js +92 -0
  176. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +56 -2
  177. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +38 -0
  178. package/packages/dd-trace/src/llmobs/prompts/manager.js +5 -7
  179. package/packages/dd-trace/src/llmobs/prompts/prompt.js +1 -1
  180. package/packages/dd-trace/src/llmobs/sdk.js +23 -6
  181. package/packages/dd-trace/src/llmobs/span_processor.js +18 -8
  182. package/packages/dd-trace/src/llmobs/tagger.js +56 -3
  183. package/packages/dd-trace/src/llmobs/util.js +1 -2
  184. package/packages/dd-trace/src/llmobs/writers/base.js +7 -6
  185. package/packages/dd-trace/src/llmobs/writers/util.js +3 -1
  186. package/packages/dd-trace/src/log/log.js +1 -5
  187. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +30 -1
  188. package/packages/dd-trace/src/openfeature/configuration_source.js +17 -2
  189. package/packages/dd-trace/src/openfeature/debug-logging-hook.js +25 -0
  190. package/packages/dd-trace/src/openfeature/evaluation-telemetry-opt-out-hook.js +51 -0
  191. package/packages/dd-trace/src/openfeature/flagging_provider.js +59 -3
  192. package/packages/dd-trace/src/openfeature/remote_config.js +9 -0
  193. package/packages/dd-trace/src/openfeature/writers/util.js +43 -4
  194. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +1 -1
  195. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  196. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -2
  197. package/packages/dd-trace/src/opentelemetry/otlp/common.proto +1 -1
  198. package/packages/dd-trace/src/opentelemetry/resource-attributes.js +1 -1
  199. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +6 -23
  200. package/packages/dd-trace/src/opentracing/propagation/text_map.js +53 -13
  201. package/packages/dd-trace/src/otel-sampling.js +4 -5
  202. package/packages/dd-trace/src/otel-thread-ctx.js +81 -15
  203. package/packages/dd-trace/src/plugins/database.js +7 -16
  204. package/packages/dd-trace/src/plugins/util/git.js +9 -25
  205. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -5
  206. package/packages/dd-trace/src/plugins/util/test.js +48 -4
  207. package/packages/dd-trace/src/priority_sampler.js +1 -2
  208. package/packages/dd-trace/src/profiling/profiler.js +4 -6
  209. package/packages/dd-trace/src/profiling/profilers/wall.js +4 -10
  210. package/packages/dd-trace/src/proxy.js +3 -2
  211. package/packages/dd-trace/src/ritm.js +4 -2
  212. package/packages/dd-trace/src/serverless.js +10 -0
  213. package/packages/dd-trace/src/span_processor.js +13 -17
  214. package/packages/dd-trace/src/storage-channels.js +112 -46
  215. package/packages/dd-trace/src/telemetry/endpoints.js +1 -3
  216. package/packages/dd-trace/src/util.js +29 -0
  217. package/packages/dd-trace/src/web-tags-cache.js +6 -2
  218. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
  219. package/vendor/dist/@datadog/openfeature-node-server/rules-based/LICENSE +201 -0
  220. package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.d.ts +925 -0
  221. package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.js +1 -0
  222. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  223. package/vendor/dist/protobufjs/index.js +1 -1
  224. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  225. package/vendor/dist/shell-quote/index.js +1 -1
@@ -11,11 +11,10 @@ const UINT64_MASK = 2n ** 64n - 1n
11
11
  /**
12
12
  * @param {unknown} value
13
13
  * @param {number} minLength
14
- * @param {number} maxLength
15
14
  * @returns {value is string}
16
15
  */
17
- function isLowerHex (value, minLength, maxLength) {
18
- if (typeof value !== 'string' || value.length < minLength || value.length > maxLength) return false
16
+ function isLowerHex (value, minLength) {
17
+ if (typeof value !== 'string' || value.length < minLength || value.length > 14) return false
19
18
 
20
19
  for (let index = 0; index < value.length; index++) {
21
20
  const code = value.charCodeAt(index)
@@ -112,11 +111,11 @@ function sanitizeFields (state) {
112
111
  let randomValue = state.get('rv')
113
112
  let threshold = state.get('th')
114
113
 
115
- if (!isLowerHex(randomValue, 14, 14)) {
114
+ if (!isLowerHex(randomValue, 14)) {
116
115
  state.delete('rv')
117
116
  randomValue = undefined
118
117
  }
119
- if (!isLowerHex(threshold, 1, 14)) {
118
+ if (!isLowerHex(threshold, 1)) {
120
119
  state.delete('th')
121
120
  threshold = undefined
122
121
  }
@@ -20,8 +20,9 @@
20
20
  // and the OTel ContextManager activates spans via
21
21
  // storage('legacy').run({ span: ddSpan }, ...), so the active span
22
22
  // our writer reads from legacy storage is the same DatadogSpan in
23
- // both cases. The OTel-visible trace/span IDs come from the same
24
- // _ddContext.toTraceId/toSpanId calls we use here.
23
+ // both cases. The record's trace/span IDs are read from the same
24
+ // Identifier bytes (and _dd.p.tid) behind _ddContext.toTraceId/toSpanId,
25
+ // and the spec pins them byte-for-byte to those methods.
25
26
 
26
27
  const { isMainThread, threadId } = require('worker_threads')
27
28
 
@@ -32,7 +33,7 @@ const {
32
33
  enterCh,
33
34
  spanFinishCh,
34
35
  getActiveSpan,
35
- ensureChannelsActivated,
36
+ acquireChannels,
36
37
  } = require('./storage-channels')
37
38
  const {
38
39
  finalEndpoint,
@@ -40,6 +41,10 @@ const {
40
41
  } = require('./profiling/webspan-utils')
41
42
  const webTagsCache = require('./web-tags-cache')
42
43
 
44
+ /** @typedef {import('./opentracing/span')} DatadogSpan */
45
+ /** @typedef {import('./opentracing/span_context')} DatadogSpanContext */
46
+ /** @typedef {InstanceType<typeof import('@datadog/pprof').otelThreadCtx.ThreadContext>} ThreadContext */
47
+
43
48
  // OTEP-4947 duplicates are last-wins, so appending a later endpoint value would
44
49
  // correctly overwrite an earlier one — but an out-of-process reader sampling the
45
50
  // record mid-request would still see the interim value (e.g. a bare `GET`) as
@@ -124,6 +129,7 @@ function traceFlagsOf (spanContext) {
124
129
  // waiting on; undefined while the span has no web-server ancestry.
125
130
  // Distinguishes a stale announcement from a live one when a nearer
126
131
  // web-server span takes over.
132
+ // awaitsOwnEndpoint: this is the request span, waiting on its own endpoint.
127
133
  const CachedSym = Symbol('OtelThreadCtx.cached')
128
134
 
129
135
  let started = false
@@ -131,12 +137,59 @@ let ThreadContext
131
137
  let getContext
132
138
  let clearContext
133
139
 
140
+ // Reusable: the ThreadContext constructor copies the ids into its own record.
141
+ const traceIdBytes = Buffer.alloc(16)
142
+ const spanIdBytes = new Uint8Array(8)
143
+
144
+ /**
145
+ * Same bytes as decoding toTraceId(true); unexpected shapes fall back to that.
146
+ *
147
+ * @param {DatadogSpanContext} spanContext
148
+ * @returns {Uint8Array}
149
+ */
150
+ function getTraceIdBytes (spanContext) {
151
+ const low = spanContext._traceId.toBuffer()
152
+ if (low.length === 16) {
153
+ for (let i = 0; i < 16; i++) traceIdBytes[i] = low[i]
154
+ return traceIdBytes
155
+ }
156
+ if (low.length !== 8) return Buffer.from(spanContext.toTraceId(true), 'hex')
157
+ const high = spanContext._trace.tags['_dd.p.tid']
158
+ if (high) {
159
+ // write() stops at the first non-hex character, so only a valid _dd.p.tid fills all 8 bytes.
160
+ if (typeof high !== 'string' || high.length !== 16 || traceIdBytes.write(high, 0, 8, 'hex') !== 8) {
161
+ return Buffer.from(spanContext.toTraceId(true), 'hex')
162
+ }
163
+ } else {
164
+ for (let i = 0; i < 8; i++) traceIdBytes[i] = 0
165
+ }
166
+ for (let i = 0; i < 8; i++) traceIdBytes[i + 8] = low[i]
167
+ return traceIdBytes
168
+ }
169
+
170
+ /**
171
+ * @param {DatadogSpanContext} spanContext
172
+ * @returns {Uint8Array}
173
+ */
174
+ function getSpanIdBytes (spanContext) {
175
+ const bytes = spanContext._spanId.toBuffer()
176
+ if (bytes.length !== 8) return Buffer.from(spanContext.toSpanId(true), 'hex')
177
+ for (let i = 0; i < 8; i++) spanIdBytes[i] = bytes[i]
178
+ return spanIdBytes
179
+ }
180
+
181
+ /**
182
+ * @param {DatadogSpan} span
183
+ * @returns {ThreadContext | undefined} The span's record, or undefined when the span's trace or span id is malformed.
184
+ */
134
185
  function getOrBuildContext (span) {
135
186
  let cached = span[CachedSym]
136
187
  if (cached !== undefined && cached.context !== undefined) return cached.context
137
188
  const spanContext = span.context()
138
- const traceId = Uint8Array.from(Buffer.from(spanContext.toTraceId(true), 'hex'))
139
- const spanId = Uint8Array.from(Buffer.from(spanContext.toSpanId(true), 'hex'))
189
+ const traceId = getTraceIdBytes(spanContext)
190
+ const spanId = getSpanIdBytes(spanContext)
191
+ // The native constructor throws on any other id length, and onEnter runs inside user code.
192
+ if (traceId.length !== 16 || spanId.length !== 8) return
140
193
  // Local root span: the first entry in the trace's started-spans list, or
141
194
  // this span itself when it IS the root. Encoded as 16-char lowercase hex
142
195
  // per the libdatadog convention.
@@ -152,7 +205,7 @@ function getOrBuildContext (span) {
152
205
  attrs[THREAD_NAME_IDX] = THREAD_NAME
153
206
  attrs[THREAD_ID_IDX] = THREAD_ID
154
207
  if (cached === undefined) {
155
- cached = {}
208
+ cached = { context: undefined, webTags: undefined, awaitsOwnEndpoint: false }
156
209
  span[CachedSym] = cached
157
210
  }
158
211
  // The flags are the one part of the record that can still change after
@@ -163,17 +216,22 @@ function getOrBuildContext (span) {
163
216
  // built before the decision keeps reading as not sampled.
164
217
  cached.context = new ThreadContext(traceId, spanId, traceFlagsOf(spanContext), attrs)
165
218
  cached.webTags = webTags
166
- if (endpoint === undefined) awaitEndpoint(webTags, cached)
219
+ if (endpoint === undefined) awaitEndpoint(span, webTags, cached)
167
220
  return cached.context
168
221
  }
169
222
 
170
223
  // Enlist a record built without an endpoint, so the resolution announcement for
171
224
  // its request fills it in.
172
- function awaitEndpoint (webTags, cached) {
225
+ function awaitEndpoint (span, webTags, cached) {
173
226
  // No web-server span in this span's ancestry, so no endpoint is coming. Should
174
227
  // one appear later, webTagsCache announces that separately — see
175
228
  // onWebTagsResolved.
176
229
  if (webTags === undefined) return
230
+ // The request span waits on its own announcement; only descendants need the shared list.
231
+ if (webTags === span.context().getTags()) {
232
+ cached.awaitsOwnEndpoint = true
233
+ return
234
+ }
177
235
  const waiting = pendingEndpoints.get(webTags)
178
236
  if (waiting === undefined) {
179
237
  pendingEndpoints.set(webTags, [cached])
@@ -193,12 +251,13 @@ function appendEndpoint (context, endpoint) {
193
251
 
194
252
  function onEnter () {
195
253
  if (!started) return
196
- const span = getActiveSpan()
197
- if (!span) {
198
- clearContext()
254
+ const span = /** @type {DatadogSpan | null | undefined} */ (getActiveSpan())
255
+ const context = span && getOrBuildContext(span)
256
+ if (!context) {
257
+ // Clearing an empty frame would still make pprof install a new AsyncContextFrame.
258
+ if (getContext() !== undefined) clearContext()
199
259
  return
200
260
  }
201
- const context = getOrBuildContext(span)
202
261
  // Skip if this CPED already holds the same context. Same allocation-churn
203
262
  // fix as the wall profiler in dd-trace-js#8638.
204
263
  if (getContext() === context) return
@@ -246,11 +305,18 @@ function onSpanFinished (span) {
246
305
  function onEndpointResolved (span) {
247
306
  if (!started) return
248
307
  const webTags = span.context().getTags()
308
+ const own = span[CachedSym]
309
+ const ownWaits = own !== undefined && own.awaitsOwnEndpoint
249
310
  const waiting = pendingEndpoints.get(webTags)
250
- if (waiting === undefined) return
311
+ if (!ownWaits && waiting === undefined) return
251
312
  const endpoint = finalEndpoint(webTags)
252
313
  // webTagsCache only announces settled endpoints, so this is belt and braces.
253
314
  if (endpoint === undefined) return
315
+ if (ownWaits) {
316
+ own.awaitsOwnEndpoint = false
317
+ if (own.context !== undefined && own.webTags === webTags) appendEndpoint(own.context, endpoint)
318
+ }
319
+ if (waiting === undefined) return
254
320
  pendingEndpoints.delete(webTags)
255
321
  for (const cached of waiting) {
256
322
  // A record whose span has since been attributed to a nearer web-server span
@@ -281,7 +347,7 @@ function onWebTagsResolved (span) {
281
347
  // ThreadContext would strand every async-context frame holding this one.
282
348
  // The work is still nested in the outer request, which makes that the least
283
349
  // wrong of the values available.
284
- awaitEndpoint(webTags, cached)
350
+ awaitEndpoint(span, webTags, cached)
285
351
  } else {
286
352
  appendEndpoint(cached.context, endpoint)
287
353
  }
@@ -371,7 +437,7 @@ function start () {
371
437
  getContext = ns.getContext
372
438
  clearContext = ns.clearContext
373
439
 
374
- ensureChannelsActivated(isACFActive)
440
+ acquireChannels(false)
375
441
  enterCh.subscribe(onEnter)
376
442
  spanFinishCh.subscribe(onSpanFinished)
377
443
  // Endpoint updates come from the shared web-tags cache's transition channels
@@ -25,7 +25,7 @@ class DatabasePlugin extends StoragePlugin {
25
25
  // trails ddh — so per-query work shrinks to encoding dddb / dddbs / ddh and concatenating.
26
26
  #dbmEnvFragment
27
27
  #dbmEndFragment
28
- // Cache the rendered prefix per `${db.name}\0${out.host}\0${dbmService}`. The triple is
28
+ // Cache the rendered prefix per `${db.name}\0${out.host}\0${serviceName}`. The triple is
29
29
  // connection-stable for a real workload, so the steady state is one `LRUCache.get` plus the
30
30
  // optional per-call `,ddprs='...'` suffix.
31
31
  #dbmPrefixCache = new LRUCache({ max: DBM_PREFIX_CACHE_MAX })
@@ -61,23 +61,15 @@ class DatabasePlugin extends StoragePlugin {
61
61
  this.#dbmPrefixCache.set(cacheKey, prefix)
62
62
  }
63
63
 
64
- if (peerData !== undefined && peerData[PEER_SERVICE_SOURCE_KEY] === PEER_SERVICE_KEY) {
65
- return `${prefix},ddprs='${encode(peerData[PEER_SERVICE_KEY])}'`
64
+ // `dddbs` never follows the peer service: it is always the configured database service, and the
65
+ // peer service is reported through `ddprs` only, and only when it was set explicitly.
66
+ const peerService = peerData?.[PEER_SERVICE_KEY]
67
+ if (peerService && peerData[PEER_SERVICE_SOURCE_KEY] === PEER_SERVICE_KEY) {
68
+ return `${prefix},ddprs='${encode(peerService)}'`
66
69
  }
67
70
  return prefix
68
71
  }
69
72
 
70
- /**
71
- * @param {string} tracerService
72
- * @param {object} peerData
73
- */
74
- #getDbmServiceName (tracerService, peerData) {
75
- if (this._tracerConfig.spanComputePeerService) {
76
- return this.getPeerServiceRemap(peerData)[PEER_SERVICE_KEY] || tracerService
77
- }
78
- return tracerService
79
- }
80
-
81
73
  /**
82
74
  * @param {import('../../../..').Span} span
83
75
  * @param {string} serviceName
@@ -91,8 +83,7 @@ class DatabasePlugin extends StoragePlugin {
91
83
  }
92
84
 
93
85
  const peerData = this.getPeerService(span.context().getTags())
94
- const dbmService = this.#getDbmServiceName(serviceName, peerData)
95
- const servicePropagation = this.#createDBMPropagationCommentService(dbmService, span, peerData)
86
+ const servicePropagation = this.#createDBMPropagationCommentService(serviceName, span, peerData)
96
87
 
97
88
  let dbmComment = servicePropagation
98
89
 
@@ -45,7 +45,6 @@ const legacyStorage = storage('legacy')
45
45
  const GIT_REV_LIST_MAX_BUFFER = 12 * 1024 * 1024 // 12MB
46
46
 
47
47
  function sanitizedExec (
48
- cmd,
49
48
  flags,
50
49
  operationMetric,
51
50
  durationMetric,
@@ -61,7 +60,7 @@ function sanitizedExec (
61
60
  startTime = Date.now()
62
61
  }
63
62
  try {
64
- let result = cachedExec(cmd, flags, { stdio: 'pipe' }).toString()
63
+ let result = cachedExec('git', flags, { stdio: 'pipe' }).toString()
65
64
 
66
65
  if (shouldTrim) {
67
66
  result = result.replaceAll(/(\r\n|\n|\r)/g, '')
@@ -106,7 +105,6 @@ function isGitAvailable () {
106
105
 
107
106
  function isShallowRepository () {
108
107
  return sanitizedExec(
109
- 'git',
110
108
  ['rev-parse', '--is-shallow-repository'],
111
109
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'check_shallow' } },
112
110
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'check_shallow' } },
@@ -115,7 +113,7 @@ function isShallowRepository () {
115
113
  }
116
114
 
117
115
  function getGitVersion () {
118
- const gitVersionString = sanitizedExec('git', ['version'])
116
+ const gitVersionString = sanitizedExec(['version'])
119
117
  const gitVersionMatches = /** @type {RegExpMatch} */ (gitVersionString.match(/git version (\d+)\.(\d+)\.(\d+)/))
120
118
  try {
121
119
  return {
@@ -138,8 +136,8 @@ function unshallowRepository (parentOnly = false) {
138
136
  log.warn('Git version is <2.27, so git unshallow will not proceed')
139
137
  return
140
138
  }
141
- const defaultRemoteName = sanitizedExec('git', ['config', '--default', 'origin', '--get', 'clone.defaultRemoteName'])
142
- const revParseHead = sanitizedExec('git', ['rev-parse', 'HEAD'])
139
+ const defaultRemoteName = sanitizedExec(['config', '--default', 'origin', '--get', 'clone.defaultRemoteName'])
140
+ const revParseHead = sanitizedExec(['rev-parse', 'HEAD'])
143
141
 
144
142
  const baseGitOptions = [
145
143
  'fetch',
@@ -167,7 +165,6 @@ function unshallowRepository (parentOnly = false) {
167
165
  { command: 'unshallow', errorType: err.code, exitCode: err.status || err.errno }
168
166
  )
169
167
  const upstreamRemote = sanitizedExec(
170
- 'git',
171
168
  ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}']
172
169
  )
173
170
  flags = [
@@ -186,7 +183,6 @@ function unshallowRepository (parentOnly = false) {
186
183
  )
187
184
  // We use sanitizedExec here because if this last option fails, we'll give up.
188
185
  sanitizedExec(
189
- 'git',
190
186
  baseGitOptions,
191
187
  null,
192
188
  null,
@@ -199,7 +195,6 @@ function unshallowRepository (parentOnly = false) {
199
195
 
200
196
  function getRepositoryUrl () {
201
197
  return sanitizedExec(
202
- 'git',
203
198
  ['config', '--get', 'remote.origin.url'],
204
199
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_repository' } },
205
200
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_repository' } },
@@ -233,7 +228,6 @@ function getGitDiff (baseCommit, targetCommit) {
233
228
  flags.push(targetCommit)
234
229
  }
235
230
  return sanitizedExec(
236
- 'git',
237
231
  flags,
238
232
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'diff' } },
239
233
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'diff' } },
@@ -244,7 +238,6 @@ function getGitDiff (baseCommit, targetCommit) {
244
238
 
245
239
  function getGitRemoteName () {
246
240
  const upstreamRemote = sanitizedExec(
247
- 'git',
248
241
  ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'],
249
242
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_remote_name' } },
250
243
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_remote_name' } },
@@ -256,7 +249,6 @@ function getGitRemoteName () {
256
249
  }
257
250
 
258
251
  const remotes = sanitizedExec(
259
- 'git',
260
252
  ['remote'],
261
253
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_remote_name' } },
262
254
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_remote_name' } },
@@ -269,7 +261,6 @@ function getGitRemoteName () {
269
261
 
270
262
  function getSourceBranch () {
271
263
  return sanitizedExec(
272
- 'git',
273
264
  ['rev-parse', '--abbrev-ref', 'HEAD'],
274
265
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_source_branch' } },
275
266
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_source_branch' } },
@@ -315,7 +306,6 @@ function checkAndFetchBranch (branch, remoteName) {
315
306
 
316
307
  function getLocalBranches (remoteName) {
317
308
  const localBranches = sanitizedExec(
318
- 'git',
319
309
  ['for-each-ref', '--format=%(refname:short)', `refs/remotes/${remoteName}`],
320
310
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_local_branches' } },
321
311
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_local_branches' } },
@@ -331,7 +321,6 @@ function getLocalBranches (remoteName) {
331
321
 
332
322
  function getMergeBase (baseBranch, sourceBranch) {
333
323
  return sanitizedExec(
334
- 'git',
335
324
  ['merge-base', baseBranch, sourceBranch],
336
325
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_merge_base' } },
337
326
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_merge_base' } },
@@ -341,7 +330,6 @@ function getMergeBase (baseBranch, sourceBranch) {
341
330
 
342
331
  function getCounts (sourceBranch, candidateBranch) {
343
332
  const counts = sanitizedExec(
344
- 'git',
345
333
  ['rev-list', '--left-right', '--count', `${candidateBranch}...${sourceBranch}`],
346
334
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_counts' } },
347
335
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_counts' } },
@@ -460,7 +448,6 @@ function generatePackFilesForCommits (commitsToUpload) {
460
448
 
461
449
  function getRepositoryRoot () {
462
450
  return sanitizedExec(
463
- 'git',
464
451
  ['rev-parse', '--show-toplevel']
465
452
  )
466
453
  }
@@ -488,13 +475,13 @@ function getGitMetadata (ciMetadata) {
488
475
  committerName,
489
476
  committerEmail,
490
477
  committerDate,
491
- ] = sanitizedExec('git', ['show', '-s', '--format=%an,%ae,%aI,%cn,%ce,%cI']).split(',')
478
+ ] = sanitizedExec(['show', '-s', '--format=%an,%ae,%aI,%cn,%ce,%cI']).split(',')
492
479
 
493
480
  const tags = {
494
481
  [GIT_COMMIT_MESSAGE]:
495
- commitMessage || sanitizedExec('git', ['show', '-s', '--format=%B'], null, null, null, false),
496
- [GIT_BRANCH]: branch || sanitizedExec('git', ['rev-parse', '--abbrev-ref', 'HEAD']),
497
- [GIT_COMMIT_SHA]: commitSHA || sanitizedExec('git', ['rev-parse', 'HEAD']),
482
+ commitMessage || sanitizedExec(['show', '-s', '--format=%B'], null, null, null, false),
483
+ [GIT_BRANCH]: branch || sanitizedExec(['rev-parse', '--abbrev-ref', 'HEAD']),
484
+ [GIT_COMMIT_SHA]: commitSHA || sanitizedExec(['rev-parse', 'HEAD']),
498
485
  [CI_WORKSPACE_PATH]: ciWorkspacePath || getRepositoryRoot(),
499
486
  }
500
487
 
@@ -513,7 +500,6 @@ function getGitMetadata (ciMetadata) {
513
500
  headCommitterEmail,
514
501
  headCommitMessage,
515
502
  ] = sanitizedExec(
516
- 'git',
517
503
  [
518
504
  'show',
519
505
  '-s',
@@ -539,7 +525,7 @@ function getGitMetadata (ciMetadata) {
539
525
 
540
526
  const entries = [
541
527
  GIT_REPOSITORY_URL,
542
- filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
528
+ filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec(['ls-remote', '--get-url'])),
543
529
  GIT_COMMIT_AUTHOR_DATE, authorDate,
544
530
  GIT_COMMIT_AUTHOR_NAME, ciAuthorName || authorName,
545
531
  GIT_COMMIT_AUTHOR_EMAIL, ciAuthorEmail || authorEmail,
@@ -563,7 +549,6 @@ function getGitInformationDiscrepancy () {
563
549
  const gitRepositoryUrl = getRepositoryUrl()
564
550
 
565
551
  const gitCommitSHA = sanitizedExec(
566
- 'git',
567
552
  ['rev-parse', 'HEAD'],
568
553
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_commit_sha' } },
569
554
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_commit_sha' } },
@@ -577,7 +562,6 @@ function fetchHeadCommitSha (headSha) {
577
562
  const remoteName = getGitRemoteName()
578
563
 
579
564
  sanitizedExec(
580
- 'git',
581
565
  [
582
566
  'fetch',
583
567
  '--update-shallow',
@@ -51,11 +51,7 @@ const supportedProxies = {
51
51
  }
52
52
 
53
53
  function createInferredProxySpan (headers, childOf, tracer, reqCtx, traceCtx, config, startSpanHelper) {
54
- if (!headers) {
55
- return null
56
- }
57
-
58
- if (!tracer._config?.inferredProxyServicesEnabled) {
54
+ if (!headers || !tracer._config?.inferredProxyServicesEnabled) {
59
55
  return null
60
56
  }
61
57
 
@@ -5,6 +5,7 @@ const fs = require('fs')
5
5
  const { URL } = require('url')
6
6
  const { stripVTControlCharacters } = require('node:util')
7
7
  const { getLageTestSessionName } = require('../../ci-visibility/lage')
8
+ const resolveRunfilePath = require('../../ci-visibility/resolve-runfile-path')
8
9
  const log = require('../../log')
9
10
  const { getEnvironmentVariable, getValueFromEnvSources } = require('../../config/helper')
10
11
  const { getSegment } = require('../../util')
@@ -250,8 +251,11 @@ const TEST_LEVEL_EVENT_TYPES = [
250
251
  'test_module_end',
251
252
  'test_session_end',
252
253
  ]
254
+ const TEST_PARALLELIZATION_ENABLED = 'test.parallelization.enabled'
255
+ const TEST_PARALLELIZATION_PLAN_TAG_PREFIX = 'test.parallelization.plan.'
253
256
  const TEST_LEVELS_METADATA = 'test_levels'
254
257
  const TEST_LEVELS_METADATA_TAGS = [
258
+ TEST_PARALLELIZATION_ENABLED,
255
259
  CI_JOB_ID,
256
260
  CI_JOB_NAME,
257
261
  CI_JOB_URL,
@@ -809,12 +813,49 @@ function getTestEnvironmentMetadata (testFramework, config, shouldSkipGitMetadat
809
813
  ...userProvidedGitMetadata,
810
814
  ...runtimeAndOSMetadata,
811
815
  }
816
+ if (/^(true|1)$/i.test(getEnvironmentVariable('_DD_TEST_PARALLELIZATION_ENABLED'))) {
817
+ metadata[TEST_PARALLELIZATION_ENABLED] = 'true'
818
+ Object.assign(metadata, getTestParallelizationPlanMetadata())
819
+ }
812
820
  if (config && config.service) {
813
821
  metadata['service.name'] = config.service
814
822
  }
815
823
  return removeInvalidMetadata(metadata)
816
824
  }
817
825
 
826
+ /** @returns {Record<string, string>} */
827
+ function getTestParallelizationPlanMetadata () {
828
+ try {
829
+ let metadataFile = getEnvironmentVariable('_DD_TEST_PARALLELIZATION_METADATA_FILE')
830
+ if (!metadataFile) {
831
+ // The manifest locator belongs to DDTest's artifact protocol, rather than tracer configuration.
832
+ // eslint-disable-next-line eslint-rules/eslint-process-env
833
+ const env = process.env
834
+ const manifestFile = env.TEST_OPTIMIZATION_MANIFEST_FILE || env.DD_TEST_OPTIMIZATION_MANIFEST_FILE
835
+ const planDirectory = manifestFile
836
+ ? path.dirname(resolveRunfilePath(manifestFile, env))
837
+ : path.join(process.cwd(), '.testoptimization')
838
+ metadataFile = path.join(planDirectory, 'plan-metadata.json')
839
+ }
840
+ const { tags } = JSON.parse(fs.readFileSync(metadataFile, 'utf8'))
841
+ if (!tags || typeof tags !== 'object' || Array.isArray(tags) ||
842
+ Object.values(tags).some(value => typeof value !== 'string')) {
843
+ return {}
844
+ }
845
+ const metadata = {}
846
+ for (const [tag, value] of Object.entries(tags)) {
847
+ if (tag.startsWith(TEST_PARALLELIZATION_PLAN_TAG_PREFIX) &&
848
+ tag.length > TEST_PARALLELIZATION_PLAN_TAG_PREFIX.length && value) {
849
+ metadata[tag] = value
850
+ }
851
+ }
852
+ return metadata
853
+ } catch (err) {
854
+ log.debug('Failed to read DDTest plan metadata: %s', err.message)
855
+ return {}
856
+ }
857
+ }
858
+
818
859
  function getTestParametersString (parametersByTestName, testName) {
819
860
  if (!parametersByTestName[testName]) {
820
861
  return ''
@@ -845,6 +886,11 @@ function getTestLevelsMetadataTags (testEnvironmentMetadata) {
845
886
  testLevelsMetadataTags[key] = value
846
887
  }
847
888
  }
889
+ for (const [key, value] of Object.entries(testEnvironmentMetadata)) {
890
+ if (key.startsWith(TEST_PARALLELIZATION_PLAN_TAG_PREFIX) && value !== undefined) {
891
+ testLevelsMetadataTags[key] = value
892
+ }
893
+ }
848
894
  return testLevelsMetadataTags
849
895
  }
850
896
 
@@ -1556,8 +1602,7 @@ function applySkippedCoverageToFileCoverage (fileCoverage, skippedBitmap) {
1556
1602
  let updated = false
1557
1603
  for (const [statementId, statementLocation] of Object.entries(fileCoverage.data.statementMap)) {
1558
1604
  const startLine = statementLocation?.start?.line
1559
- if (!isLineCoveredByBitmap(skippedBitmap, startLine)) continue
1560
- if (fileCoverage.data.s[statementId] > 0) continue
1605
+ if (!isLineCoveredByBitmap(skippedBitmap, startLine) || fileCoverage.data.s[statementId] > 0) continue
1561
1606
 
1562
1607
  fileCoverage.data.s[statementId] = 1
1563
1608
  updated = true
@@ -2256,8 +2301,7 @@ function recordTestManagementExecution (execution, executions = testManagementEx
2256
2301
  * }} execution
2257
2302
  */
2258
2303
  function recordAttemptToFixExecution (attemptToFixExecutions, execution) {
2259
- if (!execution?.testName) return
2260
- if (getValueFromEnvSources('DD_TEST_MANAGEMENT_REPORT_ENABLED') === false) return
2304
+ if (!execution?.testName || getValueFromEnvSources('DD_TEST_MANAGEMENT_REPORT_ENABLED') === false) return
2261
2305
 
2262
2306
  const { testSuite, testName, status, isDisabled, isQuarantined } = execution
2263
2307
  const identity = getTestOptimizationIdentity(testSuite, testName)
@@ -119,8 +119,7 @@ class PrioritySampler {
119
119
  const root = context._trace.started[0]
120
120
 
121
121
  // TODO: remove the decision maker tag when priority is less than AUTO_KEEP
122
- if (context._sampling.priority !== undefined) return
123
- if (!root) return // noop span
122
+ if (context._sampling.priority !== undefined || !root) return // noop span
124
123
 
125
124
  log.trace(span, auto)
126
125
 
@@ -352,11 +352,11 @@ class Profiler extends EventEmitter {
352
352
  _capture (timeout, start) {
353
353
  if (!this.enabled) return
354
354
  this.#lastStart = start
355
- if (!this.#timer || timeout !== this._timeoutInterval) {
355
+ if (this.#timer && timeout === this._timeoutInterval) {
356
+ this.#timer.refresh()
357
+ } else {
356
358
  this.#timer = setTimeout(() => this._collect(snapshotKinds.PERIODIC), timeout)
357
359
  this.#timer.unref?.()
358
- } else {
359
- this.#timer.refresh()
360
360
  }
361
361
  }
362
362
 
@@ -366,10 +366,8 @@ class Profiler extends EventEmitter {
366
366
  if (!isWebServerSpan(tags)) return
367
367
 
368
368
  const endpointName = endpointNameFromTags(tags)
369
- if (!endpointName) return
370
-
371
369
  // Make sure this is the outermost web span, just in case so we don't overcount
372
- if (findWebSpan(getStartedSpans(context), context._parentId)) return
370
+ if (!endpointName || findWebSpan(getStartedSpans(context), context._parentId)) return
373
371
 
374
372
  let counter = this.#endpointCounts.get(endpointName)
375
373
  if (counter === undefined) {
@@ -10,7 +10,8 @@ const {
10
10
  beforeCh,
11
11
  spanFinishCh,
12
12
  getActiveSpan,
13
- ensureChannelsActivated,
13
+ acquireChannels,
14
+ releaseChannels,
14
15
  } = require('../../storage-channels')
15
16
  const webTagsCache = require('../../web-tags-cache')
16
17
 
@@ -128,14 +129,6 @@ class NativeWallProfiler {
128
129
  this.#pprof = require('@datadog/pprof')
129
130
  kSampleCount = this.#pprof.time.constants.kSampleCount
130
131
 
131
- // pprof otherwise crashes in worker threads
132
- if (!process._startProfilerIdleNotifier) {
133
- process._startProfilerIdleNotifier = () => {}
134
- }
135
- if (!process._stopProfilerIdleNotifier) {
136
- process._stopProfilerIdleNotifier = () => {}
137
- }
138
-
139
132
  this.#pprof.time.start({
140
133
  collectCpuTime: this.#cpuProfilingEnabled,
141
134
  columnNumbers: 'emit',
@@ -157,7 +150,7 @@ class NativeWallProfiler {
157
150
  this.#profilerState = this.#pprof.time.getState()
158
151
  this.#lastSampleCount = 0
159
152
 
160
- ensureChannelsActivated(this.#asyncContextFrameEnabled)
153
+ acquireChannels(!this.#asyncContextFrameEnabled)
161
154
 
162
155
  if (this.#asyncContextFrameEnabled) {
163
156
  this.#setupTelemetryMetrics()
@@ -346,6 +339,7 @@ class NativeWallProfiler {
346
339
  }
347
340
  enterCh.unsubscribe(this.#boundEnter)
348
341
  spanFinishCh.unsubscribe(this.#boundSpanFinished)
342
+ releaseChannels(!this.#asyncContextFrameEnabled)
349
343
  if (this.#endpointCollectionEnabled) {
350
344
  webTagsCache.resolvedCh.unsubscribe(this.#boundSpanTagsUpdated)
351
345
  webTagsCache.deactivate()
@@ -6,6 +6,7 @@ const NoopProxy = require('./noop/proxy')
6
6
  const DatadogTracer = require('./tracer')
7
7
  const getConfig = require('./config')
8
8
  const { getEnvironmentVariable } = require('./config/helper')
9
+ const { reseed } = require('./id')
9
10
  const runtimeMetrics = require('./runtime_metrics')
10
11
  const log = require('./log')
11
12
  const { setStartupLogPluginManager, startupLog } = require('./startup-log')
@@ -234,8 +235,7 @@ class Tracer extends NoopProxy {
234
235
  })
235
236
 
236
237
  rc.setProductHandler('AGENT_TASK', (action, conf) => {
237
- if (action === 'unapply' || !conf) return
238
- if (conf.task_type !== 'tracer_flare' || !conf.args) return
238
+ if (action === 'unapply' || !conf || conf.task_type !== 'tracer_flare' || !conf.args) return
239
239
 
240
240
  this._flare.enable(config)
241
241
  this._flare.module.send(conf.args)
@@ -353,6 +353,7 @@ class Tracer extends NoopProxy {
353
353
  if (request.method === 'POST' && request.url === '/aws/lambda-microvms/runtime/v1/run') {
354
354
  ch.unsubscribe(onHttpRequest)
355
355
  drainUuidPool()
356
+ reseed()
356
357
  channel('datadog:identity:update').publish(config)
357
358
  if (this._tracingInitialized) {
358
359
  const storeTracerMetadata = require('./tracer_metadata')