dd-trace 5.132.0 → 5.134.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 (231) 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-runner-setup.mjs +27 -0
  16. package/ci/vitest-no-worker-init-setup.mjs +10 -7
  17. package/index.d.ts +41 -19
  18. package/initialize.mjs +1 -3
  19. package/openfeature/rules-based.d.ts +11 -0
  20. package/openfeature/rules-based.js +7 -0
  21. package/package.json +25 -22
  22. package/packages/datadog-core/src/storage.js +16 -0
  23. package/packages/datadog-esbuild/index.js +18 -12
  24. package/packages/datadog-instrumentations/index.js +2 -1
  25. package/packages/datadog-instrumentations/src/aerospike.js +3 -3
  26. package/packages/datadog-instrumentations/src/ai.js +3 -3
  27. package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +0 -6
  28. package/packages/datadog-instrumentations/src/aws-sdk.js +21 -13
  29. package/packages/datadog-instrumentations/src/cassandra-driver.js +25 -20
  30. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +9 -23
  31. package/packages/datadog-instrumentations/src/cucumber.js +65 -41
  32. package/packages/datadog-instrumentations/src/elasticsearch.js +1 -5
  33. package/packages/datadog-instrumentations/src/electron.js +6 -6
  34. package/packages/datadog-instrumentations/src/fastify.js +13 -4
  35. package/packages/datadog-instrumentations/src/fs.js +2 -2
  36. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +9 -5
  37. package/packages/datadog-instrumentations/src/grpc/client.js +2 -0
  38. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +28 -9
  39. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +1 -2
  40. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  41. package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
  42. package/packages/datadog-instrumentations/src/helpers/register.js +45 -1
  43. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -0
  44. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +89 -6
  45. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +5 -6
  46. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/jest.js +12 -0
  47. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +48 -31
  48. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/vitest.js +8 -0
  49. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +7 -7
  50. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +5 -0
  51. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +42 -4
  52. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +7 -10
  53. package/packages/datadog-instrumentations/src/ioredis.js +7 -5
  54. package/packages/datadog-instrumentations/src/iovalkey.js +7 -5
  55. package/packages/datadog-instrumentations/src/jest.js +72 -67
  56. package/packages/datadog-instrumentations/src/knex.js +9 -5
  57. package/packages/datadog-instrumentations/src/mariadb-bundle.js +3 -3
  58. package/packages/datadog-instrumentations/src/mocha/common.js +20 -8
  59. package/packages/datadog-instrumentations/src/mocha/main.js +140 -43
  60. package/packages/datadog-instrumentations/src/mocha/utils.js +38 -4
  61. package/packages/datadog-instrumentations/src/mocha/worker.js +1 -2
  62. package/packages/datadog-instrumentations/src/mongodb-core.js +3 -3
  63. package/packages/datadog-instrumentations/src/mongoose.js +3 -3
  64. package/packages/datadog-instrumentations/src/nova-sonic/audio.js +173 -0
  65. package/packages/datadog-instrumentations/src/nova-sonic/index.js +209 -0
  66. package/packages/datadog-instrumentations/src/nova-sonic/session.js +492 -0
  67. package/packages/datadog-instrumentations/src/openai-realtime/index.js +18 -6
  68. package/packages/datadog-instrumentations/src/openai-realtime/session.js +1 -1
  69. package/packages/datadog-instrumentations/src/openai.js +7 -0
  70. package/packages/datadog-instrumentations/src/pino.js +5 -6
  71. package/packages/datadog-instrumentations/src/playwright.js +2 -0
  72. package/packages/datadog-instrumentations/src/redis.js +27 -13
  73. package/packages/datadog-instrumentations/src/router.js +30 -0
  74. package/packages/datadog-instrumentations/src/rum-browser-scripts.js +2 -6
  75. package/packages/datadog-instrumentations/src/stripe.js +23 -12
  76. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +8 -5
  77. package/packages/datadog-instrumentations/src/vitest-main.js +16 -18
  78. package/packages/datadog-instrumentations/src/vitest-util.js +7 -4
  79. package/packages/datadog-instrumentations/src/vitest-worker.js +1 -2
  80. package/packages/datadog-instrumentations/src/vitest.js +9 -1
  81. package/packages/datadog-instrumentations/src/webdriverio.js +5 -8
  82. package/packages/datadog-instrumentations/src/ws.js +1 -4
  83. package/packages/datadog-plugin-amqplib/src/client.js +1 -2
  84. package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -5
  85. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/handler.js +1 -2
  86. package/packages/datadog-plugin-aws-sdk/src/base.js +5 -8
  87. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +18 -0
  88. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/sonic.js +45 -0
  89. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -3
  90. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -5
  91. package/packages/datadog-plugin-azure-durable-functions/src/index.js +5 -4
  92. package/packages/datadog-plugin-azure-functions/src/index.js +5 -3
  93. package/packages/datadog-plugin-claude-agent-sdk/src/index.js +0 -2
  94. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +4 -5
  95. package/packages/datadog-plugin-cypress/src/index.js +6 -6
  96. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -2
  97. package/packages/datadog-plugin-cypress/src/support.js +3 -4
  98. package/packages/datadog-plugin-express/src/code_origin.js +1 -2
  99. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
  100. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
  101. package/packages/datadog-plugin-graphql/src/execute.js +5 -5
  102. package/packages/datadog-plugin-grpc/src/util.js +1 -2
  103. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -2
  104. package/packages/datadog-plugin-mocha/src/index.js +7 -10
  105. package/packages/datadog-plugin-mocha/src/webdriverio-video.js +8 -4
  106. package/packages/datadog-plugin-mongodb-core/src/query.js +8 -5
  107. package/packages/datadog-plugin-next/src/index.js +1 -2
  108. package/packages/datadog-plugin-openai/src/tracing.js +5 -2
  109. package/packages/datadog-plugin-openai-agents/src/integration.js +6 -2
  110. package/packages/datadog-plugin-openai-agents/src/processor.js +2 -4
  111. package/packages/datadog-plugin-postgres/src/index.js +24 -0
  112. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -5
  113. package/packages/datadog-plugin-rhea/src/consumer.js +1 -4
  114. package/packages/datadog-plugin-vitest/src/index.js +5 -2
  115. package/packages/datadog-shimmer/src/shimmer.js +5 -4
  116. package/packages/datadog-webpack/index.js +55 -43
  117. package/packages/datadog-webpack/src/loader.js +56 -8
  118. package/packages/dd-trace/src/aiguard/evaluation.js +143 -1
  119. package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -4
  120. package/packages/dd-trace/src/aiguard/messages/utils.js +1 -2
  121. package/packages/dd-trace/src/aiguard/redaction.js +8 -2
  122. package/packages/dd-trace/src/appsec/api_security/normalized-route.js +3 -2
  123. package/packages/dd-trace/src/appsec/api_security/sampler.js +2 -6
  124. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -9
  125. package/packages/dd-trace/src/appsec/handlers/http-request.js +3 -9
  126. package/packages/dd-trace/src/appsec/handlers/http-response.js +7 -2
  127. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -3
  128. package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +1 -4
  129. package/packages/dd-trace/src/appsec/iast/path-line.js +2 -1
  130. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +7 -1
  131. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -3
  132. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -3
  133. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +1 -6
  134. package/packages/dd-trace/src/appsec/lambda.js +1 -3
  135. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +37 -27
  136. package/packages/dd-trace/src/appsec/rasp/lfi.js +9 -5
  137. package/packages/dd-trace/src/appsec/reporter.js +21 -1
  138. package/packages/dd-trace/src/appsec/stack_trace.js +4 -4
  139. package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +3 -6
  140. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -2
  141. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +1 -1
  142. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +13 -7
  143. package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +1 -2
  144. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +2 -8
  145. package/packages/dd-trace/src/ci-visibility/resolve-runfile-path.js +54 -0
  146. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +5 -8
  147. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +2 -53
  148. package/packages/dd-trace/src/config/config-types.d.ts +2 -2
  149. package/packages/dd-trace/src/config/defaults.js +5 -5
  150. package/packages/dd-trace/src/config/generated-config-types.d.ts +10 -0
  151. package/packages/dd-trace/src/config/helper.js +34 -3
  152. package/packages/dd-trace/src/config/index.js +55 -9
  153. package/packages/dd-trace/src/config/normalize-service.js +1 -1
  154. package/packages/dd-trace/src/config/parsers.js +2 -2
  155. package/packages/dd-trace/src/config/supported-configurations.json +44 -0
  156. package/packages/dd-trace/src/datastreams/processor.js +3 -2
  157. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -4
  158. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -5
  159. package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -5
  160. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -0
  161. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +4 -6
  162. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -0
  163. package/packages/dd-trace/src/debugger/guardrail-metrics.js +2 -2
  164. package/packages/dd-trace/src/debugger/unsupported-runtime.js +16 -0
  165. package/packages/dd-trace/src/dogstatsd.js +1 -1
  166. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  167. package/packages/dd-trace/src/exporters/common/request.js +1 -5
  168. package/packages/dd-trace/src/id.js +14 -1
  169. package/packages/dd-trace/src/lambda/handler.js +179 -19
  170. package/packages/dd-trace/src/lambda/index.js +15 -1
  171. package/packages/dd-trace/src/lambda/runtime/patch.js +34 -7
  172. package/packages/dd-trace/src/llmobs/agent-manifest.js +19 -2
  173. package/packages/dd-trace/src/llmobs/audio-utils.js +3 -2
  174. package/packages/dd-trace/src/llmobs/constants/tags.js +15 -0
  175. package/packages/dd-trace/src/llmobs/experiments/experiment.js +1 -1
  176. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +15 -0
  177. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +1 -2
  178. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -3
  179. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
  180. package/packages/dd-trace/src/llmobs/plugins/nova-sonic.js +92 -0
  181. package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +5 -0
  182. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +64 -2
  183. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +38 -0
  184. package/packages/dd-trace/src/llmobs/prompts/manager.js +5 -7
  185. package/packages/dd-trace/src/llmobs/prompts/prompt.js +1 -1
  186. package/packages/dd-trace/src/llmobs/sdk.js +15 -4
  187. package/packages/dd-trace/src/llmobs/span_processor.js +13 -2
  188. package/packages/dd-trace/src/llmobs/tagger.js +20 -10
  189. package/packages/dd-trace/src/llmobs/util.js +11 -6
  190. package/packages/dd-trace/src/llmobs/writers/base.js +4 -5
  191. package/packages/dd-trace/src/log/log.js +1 -5
  192. package/packages/dd-trace/src/openfeature/evaluation-telemetry-opt-out-hook.js +51 -0
  193. package/packages/dd-trace/src/openfeature/flagging_provider.js +48 -21
  194. package/packages/dd-trace/src/openfeature/index.js +6 -0
  195. package/packages/dd-trace/src/openfeature/writers/util.js +4 -4
  196. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +1 -1
  197. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  198. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -2
  199. package/packages/dd-trace/src/opentelemetry/otlp/common.proto +1 -1
  200. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +24 -24
  201. package/packages/dd-trace/src/opentracing/propagation/text_map.js +53 -13
  202. package/packages/dd-trace/src/otel-sampling.js +4 -5
  203. package/packages/dd-trace/src/otel-thread-ctx.js +79 -13
  204. package/packages/dd-trace/src/plugin_manager.js +1 -2
  205. package/packages/dd-trace/src/plugins/database.js +7 -16
  206. package/packages/dd-trace/src/plugins/tracing.js +0 -1
  207. package/packages/dd-trace/src/plugins/util/git.js +99 -59
  208. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -5
  209. package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -1
  210. package/packages/dd-trace/src/plugins/util/test.js +50 -4
  211. package/packages/dd-trace/src/plugins/util/web.js +90 -20
  212. package/packages/dd-trace/src/priority_sampler.js +1 -2
  213. package/packages/dd-trace/src/profiling/profiler.js +4 -6
  214. package/packages/dd-trace/src/proxy.js +1 -2
  215. package/packages/dd-trace/src/ritm.js +4 -2
  216. package/packages/dd-trace/src/serverless.js +5 -0
  217. package/packages/dd-trace/src/span_processor.js +13 -17
  218. package/packages/dd-trace/src/span_stats.js +4 -1
  219. package/packages/dd-trace/src/telemetry/endpoints.js +1 -3
  220. package/packages/dd-trace/src/telemetry/logs/log-collector.js +1 -1
  221. package/packages/dd-trace/src/util.js +37 -4
  222. package/packages/dd-trace/src/web-tags-cache.js +6 -2
  223. package/vendor/dist/@apm-js-collab/code-transformer/index.js +8 -8
  224. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
  225. package/vendor/dist/@datadog/openfeature-node-server/rules-based/LICENSE +201 -0
  226. package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.d.ts +925 -0
  227. package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.js +1 -0
  228. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  229. package/vendor/dist/protobufjs/index.js +1 -1
  230. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  231. package/vendor/dist/shell-quote/index.js +1 -1
@@ -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
 
@@ -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
  }
@@ -102,8 +102,7 @@ module.exports = class PluginManager {
102
102
  loadPlugin (name) {
103
103
  const Plugin = pluginClasses[name]
104
104
 
105
- if (!Plugin) return
106
- if (!this._tracerConfig) return // TODO: don't wait for tracer to be initialized
105
+ if (!Plugin || !this._tracerConfig) return // TODO: don't wait for tracer to be initialized
107
106
 
108
107
  // Check if this is a Test Optimization plugin and Test Optimization is not enabled
109
108
  if (TEST_OPTIMIZATION_PLUGINS.has(name) && !this._tracerConfig.isCiVisibility) {
@@ -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
 
@@ -267,7 +267,6 @@ class TracingPlugin extends Plugin {
267
267
  analyticsSampler.sample(span, config.measured)
268
268
 
269
269
  // TODO: Remove this after migration to TracingChannel is done.
270
- // eslint-disable-next-line unicorn/no-unnecessary-boolean-comparison -- Context objects use the other branch.
271
270
  if (enterOrCtx === true) {
272
271
  legacyStorage.enterWith({ ...store, span })
273
272
  } else if (enterOrCtx) {
@@ -3,8 +3,10 @@
3
3
  const os = require('os')
4
4
  const path = require('path')
5
5
  const fs = require('fs')
6
+ const { execFileSync } = require('node:child_process')
6
7
 
7
8
  const log = require('../../log')
9
+ const { getEnvironmentVariables } = require('../../config/helper')
8
10
  const {
9
11
  incrementCountMetric,
10
12
  distributionMetric,
@@ -45,12 +47,12 @@ const legacyStorage = storage('legacy')
45
47
  const GIT_REV_LIST_MAX_BUFFER = 12 * 1024 * 1024 // 12MB
46
48
 
47
49
  function sanitizedExec (
48
- cmd,
49
50
  flags,
50
51
  operationMetric,
51
52
  durationMetric,
52
53
  errorMetric,
53
- shouldTrim = true
54
+ shouldTrim = true,
55
+ executionOptions
54
56
  ) {
55
57
  return legacyStorage.run({ noop: true }, () => {
56
58
  let startTime
@@ -61,7 +63,14 @@ function sanitizedExec (
61
63
  startTime = Date.now()
62
64
  }
63
65
  try {
64
- let result = cachedExec(cmd, flags, { stdio: 'pipe' }).toString()
66
+ const exec = executionOptions?.uncached ? execFileSync : cachedExec
67
+ /** @type {import('node:child_process').ExecFileSyncOptions} */
68
+ const options = { stdio: 'pipe' }
69
+ if (executionOptions?.timeout) options.timeout = executionOptions.timeout
70
+ if (executionOptions?.localOnly) {
71
+ options.env = { ...getEnvironmentVariables(), GIT_NO_LAZY_FETCH: '1', GIT_ALLOW_PROTOCOL: '' }
72
+ }
73
+ let result = exec('git', flags, options).toString()
65
74
 
66
75
  if (shouldTrim) {
67
76
  result = result.replaceAll(/(\r\n|\n|\r)/g, '')
@@ -80,6 +89,7 @@ function sanitizedExec (
80
89
  })
81
90
  }
82
91
  log.error('Git plugin error executing command', err)
92
+ if (executionOptions?.throwOnError) throw err
83
93
  return ''
84
94
  }
85
95
  })
@@ -104,18 +114,19 @@ function isGitAvailable () {
104
114
  }
105
115
  }
106
116
 
107
- function isShallowRepository () {
117
+ function isShallowRepository (uncached = false) {
108
118
  return sanitizedExec(
109
- 'git',
110
119
  ['rev-parse', '--is-shallow-repository'],
111
120
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'check_shallow' } },
112
121
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'check_shallow' } },
113
- { name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'check_shallow' } }
122
+ { name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'check_shallow' } },
123
+ true,
124
+ { uncached }
114
125
  ) === 'true'
115
126
  }
116
127
 
117
128
  function getGitVersion () {
118
- const gitVersionString = sanitizedExec('git', ['version'])
129
+ const gitVersionString = sanitizedExec(['version'])
119
130
  const gitVersionMatches = /** @type {RegExpMatch} */ (gitVersionString.match(/git version (\d+)\.(\d+)\.(\d+)/))
120
131
  try {
121
132
  return {
@@ -138,8 +149,8 @@ function unshallowRepository (parentOnly = false) {
138
149
  log.warn('Git version is <2.27, so git unshallow will not proceed')
139
150
  return
140
151
  }
141
- const defaultRemoteName = sanitizedExec('git', ['config', '--default', 'origin', '--get', 'clone.defaultRemoteName'])
142
- const revParseHead = sanitizedExec('git', ['rev-parse', 'HEAD'])
152
+ const defaultRemoteName = sanitizedExec(['config', '--default', 'origin', '--get', 'clone.defaultRemoteName'])
153
+ const revParseHead = sanitizedExec(['rev-parse', 'HEAD'])
143
154
 
144
155
  const baseGitOptions = [
145
156
  'fetch',
@@ -167,7 +178,6 @@ function unshallowRepository (parentOnly = false) {
167
178
  { command: 'unshallow', errorType: err.code, exitCode: err.status || err.errno }
168
179
  )
169
180
  const upstreamRemote = sanitizedExec(
170
- 'git',
171
181
  ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}']
172
182
  )
173
183
  flags = [
@@ -186,7 +196,6 @@ function unshallowRepository (parentOnly = false) {
186
196
  )
187
197
  // We use sanitizedExec here because if this last option fails, we'll give up.
188
198
  sanitizedExec(
189
- 'git',
190
199
  baseGitOptions,
191
200
  null,
192
201
  null,
@@ -199,7 +208,6 @@ function unshallowRepository (parentOnly = false) {
199
208
 
200
209
  function getRepositoryUrl () {
201
210
  return sanitizedExec(
202
- 'git',
203
211
  ['config', '--get', 'remote.origin.url'],
204
212
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_repository' } },
205
213
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_repository' } },
@@ -228,23 +236,29 @@ function getLatestCommits () {
228
236
  }
229
237
 
230
238
  function getGitDiff (baseCommit, targetCommit) {
239
+ // Fetch the required snapshots explicitly; a depth-1 metadata fetch does not provide their ancestry.
240
+ for (const commit of targetCommit ? [baseCommit, targetCommit] : [baseCommit]) {
241
+ if (!hasLocalGitObject(commit)) {
242
+ // Use the current checkout state so a stale cache cannot shorten a complete clone.
243
+ fetchHeadCommitSha(commit, isShallowRepository(true))
244
+ }
245
+ }
231
246
  const flags = ['diff', '-U0', '--word-diff=porcelain', baseCommit]
232
247
  if (targetCommit) {
233
248
  flags.push(targetCommit)
234
249
  }
235
250
  return sanitizedExec(
236
- 'git',
237
251
  flags,
238
252
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'diff' } },
239
253
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'diff' } },
240
254
  { name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'diff' } },
241
- false // important not to trim or we'll lose the line breaks which we need to detect impacted tests
255
+ false, // important not to trim or we'll lose the line breaks which we need to detect impacted tests
256
+ { uncached: true }
242
257
  )
243
258
  }
244
259
 
245
260
  function getGitRemoteName () {
246
261
  const upstreamRemote = sanitizedExec(
247
- 'git',
248
262
  ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'],
249
263
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_remote_name' } },
250
264
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_remote_name' } },
@@ -256,7 +270,6 @@ function getGitRemoteName () {
256
270
  }
257
271
 
258
272
  const remotes = sanitizedExec(
259
- 'git',
260
273
  ['remote'],
261
274
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_remote_name' } },
262
275
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_remote_name' } },
@@ -269,7 +282,6 @@ function getGitRemoteName () {
269
282
 
270
283
  function getSourceBranch () {
271
284
  return sanitizedExec(
272
- 'git',
273
285
  ['rev-parse', '--abbrev-ref', 'HEAD'],
274
286
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_source_branch' } },
275
287
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_source_branch' } },
@@ -315,7 +327,6 @@ function checkAndFetchBranch (branch, remoteName) {
315
327
 
316
328
  function getLocalBranches (remoteName) {
317
329
  const localBranches = sanitizedExec(
318
- 'git',
319
330
  ['for-each-ref', '--format=%(refname:short)', `refs/remotes/${remoteName}`],
320
331
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_local_branches' } },
321
332
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_local_branches' } },
@@ -331,7 +342,6 @@ function getLocalBranches (remoteName) {
331
342
 
332
343
  function getMergeBase (baseBranch, sourceBranch) {
333
344
  return sanitizedExec(
334
- 'git',
335
345
  ['merge-base', baseBranch, sourceBranch],
336
346
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_merge_base' } },
337
347
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_merge_base' } },
@@ -341,7 +351,6 @@ function getMergeBase (baseBranch, sourceBranch) {
341
351
 
342
352
  function getCounts (sourceBranch, candidateBranch) {
343
353
  const counts = sanitizedExec(
344
- 'git',
345
354
  ['rev-list', '--left-right', '--count', `${candidateBranch}...${sourceBranch}`],
346
355
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_counts' } },
347
356
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_counts' } },
@@ -460,7 +469,6 @@ function generatePackFilesForCommits (commitsToUpload) {
460
469
 
461
470
  function getRepositoryRoot () {
462
471
  return sanitizedExec(
463
- 'git',
464
472
  ['rev-parse', '--show-toplevel']
465
473
  )
466
474
  }
@@ -477,6 +485,7 @@ function getGitMetadata (ciMetadata) {
477
485
  authorEmail: ciAuthorEmail,
478
486
  ciWorkspacePath,
479
487
  headCommitSha,
488
+ pullRequestBaseBranchSha,
480
489
  } = ciMetadata
481
490
 
482
491
  // With stdio: 'pipe', errors in this command will not be output to the parent process,
@@ -488,19 +497,36 @@ function getGitMetadata (ciMetadata) {
488
497
  committerName,
489
498
  committerEmail,
490
499
  committerDate,
491
- ] = sanitizedExec('git', ['show', '-s', '--format=%an,%ae,%aI,%cn,%ce,%cI']).split(',')
500
+ ] = sanitizedExec(['show', '-s', '--format=%an,%ae,%aI,%cn,%ce,%cI']).split(',')
492
501
 
493
502
  const tags = {
494
503
  [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']),
504
+ commitMessage || sanitizedExec(['show', '-s', '--format=%B'], null, null, null, false),
505
+ [GIT_BRANCH]: branch || sanitizedExec(['rev-parse', '--abbrev-ref', 'HEAD']),
506
+ [GIT_COMMIT_SHA]: commitSHA || sanitizedExec(['rev-parse', 'HEAD']),
498
507
  [CI_WORKSPACE_PATH]: ciWorkspacePath || getRepositoryRoot(),
499
508
  }
500
509
 
501
510
  if (headCommitSha) {
502
- if (isShallowRepository()) {
503
- fetchHeadCommitSha(headCommitSha)
511
+ const shallow = isShallowRepository(true)
512
+ const fetchedAtDepthOne = shallow && fetchHeadCommitSha(headCommitSha)
513
+ const headFlags = [
514
+ 'show',
515
+ '-s',
516
+ '--format=\'%H","%aI","%an","%ae","%cI","%cn","%ce","%B\'',
517
+ headCommitSha,
518
+ ]
519
+ // Only explicit, bounded fetches may contact the remote during head metadata recovery.
520
+ const headOptions = { uncached: true, localOnly: true }
521
+ let headInfo = sanitizedExec(headFlags, null, null, null, false, headOptions)
522
+ if (!headInfo && (fetchedAtDepthOne || !shallow)) {
523
+ fetchHeadCommitSha(headCommitSha, false)
524
+ headInfo = sanitizedExec(headFlags, null, null, null, false, headOptions)
525
+ }
526
+
527
+ // Prepare a known diff base while the remote is available, including when Git upload is disabled.
528
+ if (shallow && pullRequestBaseBranchSha && !hasLocalGitObject(pullRequestBaseBranchSha)) {
529
+ fetchHeadCommitSha(pullRequestBaseBranchSha)
504
530
  }
505
531
 
506
532
  const [
@@ -512,19 +538,7 @@ function getGitMetadata (ciMetadata) {
512
538
  headCommitterName,
513
539
  headCommitterEmail,
514
540
  headCommitMessage,
515
- ] = sanitizedExec(
516
- 'git',
517
- [
518
- 'show',
519
- '-s',
520
- '--format=\'%H","%aI","%an","%ae","%cI","%cn","%ce","%B\'',
521
- headCommitSha,
522
- ],
523
- null,
524
- null,
525
- null,
526
- false
527
- ).split('","')
541
+ ] = headInfo.split('","')
528
542
 
529
543
  if (gitHeadCommitSha) {
530
544
  tags[GIT_COMMIT_HEAD_AUTHOR_DATE] = headAuthorDate
@@ -539,7 +553,7 @@ function getGitMetadata (ciMetadata) {
539
553
 
540
554
  const entries = [
541
555
  GIT_REPOSITORY_URL,
542
- filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
556
+ filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec(['ls-remote', '--get-url'])),
543
557
  GIT_COMMIT_AUTHOR_DATE, authorDate,
544
558
  GIT_COMMIT_AUTHOR_NAME, ciAuthorName || authorName,
545
559
  GIT_COMMIT_AUTHOR_EMAIL, ciAuthorEmail || authorEmail,
@@ -563,7 +577,6 @@ function getGitInformationDiscrepancy () {
563
577
  const gitRepositoryUrl = getRepositoryUrl()
564
578
 
565
579
  const gitCommitSHA = sanitizedExec(
566
- 'git',
567
580
  ['rev-parse', 'HEAD'],
568
581
  { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_commit_sha' } },
569
582
  { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_commit_sha' } },
@@ -573,24 +586,51 @@ function getGitInformationDiscrepancy () {
573
586
  return { gitRepositoryUrl, gitCommitSHA }
574
587
  }
575
588
 
576
- function fetchHeadCommitSha (headSha) {
577
- const remoteName = getGitRemoteName()
589
+ /** @param {string} sha */
590
+ function hasLocalGitObject (sha) {
591
+ return legacyStorage.run({ noop: true }, () => {
592
+ try {
593
+ execFileSync('git', ['cat-file', '-e', sha], {
594
+ stdio: 'pipe',
595
+ // Older Git versions ignore GIT_NO_LAZY_FETCH, so also disallow transports for this local-only probe.
596
+ env: { ...getEnvironmentVariables(), GIT_NO_LAZY_FETCH: '1', GIT_ALLOW_PROTOCOL: '' },
597
+ })
598
+ return true
599
+ } catch {
600
+ return false
601
+ }
602
+ })
603
+ }
578
604
 
579
- sanitizedExec(
580
- 'git',
581
- [
582
- 'fetch',
583
- '--update-shallow',
584
- '--filter=blob:none',
585
- '--recurse-submodules=no',
586
- '--no-write-fetch-head',
587
- remoteName,
588
- headSha,
589
- ],
590
- { name: TELEMETRY_GIT_COMMAND, tags: { command: 'fetch_head_commit_sha' } },
591
- { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'fetch_head_commit_sha' } },
592
- { name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'fetch_head_commit_sha' } }
593
- )
605
+ function fetchHeadCommitSha (headSha, useDepth = true) {
606
+ const remoteName = getGitRemoteName()
607
+ // Existing heads retain the original repair/history behavior; a failed bounded fetch also retries that path.
608
+ const depths = useDepth && !hasLocalGitObject(headSha) ? [true, false] : [false]
609
+ for (const shallow of depths) {
610
+ try {
611
+ sanitizedExec(
612
+ [
613
+ 'fetch',
614
+ ...(shallow ? ['--depth=1'] : []),
615
+ '--update-shallow',
616
+ '--filter=blob:none',
617
+ '--recurse-submodules=no',
618
+ '--no-write-fetch-head',
619
+ remoteName,
620
+ headSha,
621
+ ],
622
+ { name: TELEMETRY_GIT_COMMAND, tags: { command: 'fetch_head_commit_sha' } },
623
+ { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'fetch_head_commit_sha' } },
624
+ { name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'fetch_head_commit_sha' } },
625
+ true,
626
+ { uncached: true, throwOnError: true, timeout: 5000 }
627
+ )
628
+ return shallow
629
+ } catch {
630
+ // sanitizedExec records the failure; retry without a depth limit if the bounded fetch failed.
631
+ }
632
+ }
633
+ return false
594
634
  }
595
635
 
596
636
  module.exports = {
@@ -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
 
@@ -12,8 +12,9 @@ const NODE_MODULES_PATTERN_START = `node_modules${sep}`
12
12
  * current file path ends with the expected path structure from the repo root.
13
13
  * This is needed for local and CI where dd-trace-js is not in node_modules.
14
14
  * In production, these frames are already filtered by isNodeModulesFrame.
15
+ * Bundled into ESM output, `__filename` is not defined, and dd-trace is not running from its repo.
15
16
  */
16
- const SHOULD_FILTER_DD_TRACE_INSTRUMENTAION = __filename.endsWith(
17
+ const SHOULD_FILTER_DD_TRACE_INSTRUMENTAION = typeof __filename === 'string' && __filename.endsWith(
17
18
  join('packages', 'dd-trace', 'src', 'plugins', 'util', 'stacktrace.js')
18
19
  )
19
20