dd-trace 6.12.0 → 6.13.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 (97) hide show
  1. package/ci/test-optimization-validation/framework-adapters/cypress.js +9 -11
  2. package/ci/test-optimization-validation/scenarios/ci-wiring.js +5 -4
  3. package/index.d.ts +127 -26
  4. package/package.json +10 -10
  5. package/packages/datadog-instrumentations/src/bunyan.js +4 -2
  6. package/packages/datadog-instrumentations/src/helpers/bunyan.js +12 -3
  7. package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +1 -0
  8. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +28 -0
  9. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
  10. package/packages/datadog-instrumentations/src/jest.js +140 -18
  11. package/packages/datadog-instrumentations/src/mariadb-bundle.js +1597 -0
  12. package/packages/datadog-instrumentations/src/mariadb.js +7 -0
  13. package/packages/datadog-instrumentations/src/pino.js +15 -4
  14. package/packages/datadog-instrumentations/src/playwright.js +34 -20
  15. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +7 -4
  16. package/packages/datadog-instrumentations/src/vitest-worker.js +11 -0
  17. package/packages/datadog-instrumentations/src/webdriverio.js +26 -0
  18. package/packages/datadog-instrumentations/src/winston.js +6 -3
  19. package/packages/datadog-plugin-cypress/src/support.js +1 -0
  20. package/packages/datadog-plugin-http/src/client.js +2 -15
  21. package/packages/datadog-plugin-http2/src/client.js +2 -15
  22. package/packages/datadog-plugin-openai-agents/src/integration.js +15 -11
  23. package/packages/datadog-plugin-playwright/src/index.js +9 -1
  24. package/packages/datadog-plugin-undici/src/index.js +2 -15
  25. package/packages/dd-trace/src/aiguard/evaluation.js +94 -20
  26. package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -3
  27. package/packages/dd-trace/src/aiguard/messages/anthropic.js +21 -9
  28. package/packages/dd-trace/src/aiguard/noop.js +9 -1
  29. package/packages/dd-trace/src/aiguard/redaction.js +183 -0
  30. package/packages/dd-trace/src/aiguard/sdk.js +7 -2
  31. package/packages/dd-trace/src/aiguard/tags.js +2 -0
  32. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +10 -9
  33. package/packages/dd-trace/src/appsec/rule_manager.js +2 -0
  34. package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +51 -26
  35. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +5 -11
  36. package/packages/dd-trace/src/ci-visibility/final-flush.js +20 -0
  37. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +196 -29
  38. package/packages/dd-trace/src/config/generated-config-types.d.ts +6 -0
  39. package/packages/dd-trace/src/config/index.js +2 -1
  40. package/packages/dd-trace/src/config/supported-configurations.json +27 -0
  41. package/packages/dd-trace/src/debugger/devtools_client/send.js +4 -3
  42. package/packages/dd-trace/src/dogstatsd.js +45 -18
  43. package/packages/dd-trace/src/encode/agentless-json.js +5 -4
  44. package/packages/dd-trace/src/exporters/agent/index.js +22 -2
  45. package/packages/dd-trace/src/exporters/agent/writer.js +4 -4
  46. package/packages/dd-trace/src/exporters/common/writer.js +24 -2
  47. package/packages/dd-trace/src/exporters/span-stats/index.js +23 -4
  48. package/packages/dd-trace/src/external-logger/src/index.js +4 -3
  49. package/packages/dd-trace/src/flush.js +102 -0
  50. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -0
  51. package/packages/dd-trace/src/llmobs/experiments/dataset.js +51 -2
  52. package/packages/dd-trace/src/llmobs/experiments/experiment.js +420 -105
  53. package/packages/dd-trace/src/llmobs/experiments/index.js +54 -42
  54. package/packages/dd-trace/src/llmobs/experiments/noop.js +39 -8
  55. package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
  56. package/packages/dd-trace/src/llmobs/experiments/util.js +21 -0
  57. package/packages/dd-trace/src/llmobs/index.js +80 -17
  58. package/packages/dd-trace/src/llmobs/noop.js +2 -1
  59. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +8 -4
  60. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +6 -3
  61. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +13 -6
  62. package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +5 -7
  63. package/packages/dd-trace/src/llmobs/writers/base.js +60 -24
  64. package/packages/dd-trace/src/noop/span.js +5 -0
  65. package/packages/dd-trace/src/openfeature/writers/exposures.js +8 -1
  66. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +45 -3
  67. package/packages/dd-trace/src/opentelemetry/logs/index.js +4 -1
  68. package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +7 -4
  69. package/packages/dd-trace/src/opentelemetry/metrics/index.js +3 -1
  70. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +8 -0
  71. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +4 -2
  72. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +4 -2
  73. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +25 -5
  74. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +61 -25
  75. package/packages/dd-trace/src/opentelemetry/tracer.js +26 -2
  76. package/packages/dd-trace/src/opentracing/propagation/text_map.js +410 -342
  77. package/packages/dd-trace/src/opentracing/span.js +28 -0
  78. package/packages/dd-trace/src/otel-thread-ctx.js +23 -5
  79. package/packages/dd-trace/src/plugin_manager.js +2 -0
  80. package/packages/dd-trace/src/plugins/util/status-validator.js +98 -0
  81. package/packages/dd-trace/src/plugins/util/test.js +74 -21
  82. package/packages/dd-trace/src/plugins/util/web.js +2 -65
  83. package/packages/dd-trace/src/profiling/oom.js +4 -3
  84. package/packages/dd-trace/src/profiling/profiler.js +7 -0
  85. package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
  86. package/packages/dd-trace/src/profiling/profilers/wall.js +14 -14
  87. package/packages/dd-trace/src/proxy.js +36 -8
  88. package/packages/dd-trace/src/runtime_metrics/index.js +5 -0
  89. package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +5 -0
  90. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +17 -6
  91. package/packages/dd-trace/src/serverless/telemetry-delivery-tracker.js +55 -0
  92. package/packages/dd-trace/src/serverless/vercel.js +122 -0
  93. package/packages/dd-trace/src/serverless.js +37 -20
  94. package/packages/dd-trace/src/span_stats.js +40 -3
  95. package/packages/dd-trace/src/tracer.js +22 -0
  96. package/packages/dd-trace/src/web-tags-cache.js +67 -13
  97. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
@@ -66,15 +66,6 @@ const tagValueExpr = /^[\x20-\x2B\x2D-\x7E]*$/ // ASCII minus commas
66
66
  // https://github.com/nodejs/node/blob/main/lib/_http_common.js
67
67
  const invalidHeaderValueCharExpr = /[^\t\x20-\x7E\x80-\xFF]/
68
68
  const traceparentExpr = /^([a-f0-9]{2})-([a-f0-9]{32})-([a-f0-9]{16})-([a-f0-9]{2})(-.*)?$/i
69
- // Dispatch table for `_extractSpanContext`. `'b3'` resolves to the matching
70
- // single/multi extractor per instance — see `#b3MethodName` — so it is not in
71
- // this table. `'baggage'` is consumed by `_extractBaggageItems`, not the loop.
72
- const EXTRACT_STYLE_METHODS = new Map([
73
- ['datadog', '_extractDatadogContext'],
74
- ['tracecontext', '_extractTraceparentContext'],
75
- ['b3 single header', '_extractB3SingleContext'],
76
- ['b3multi', '_extractB3MultiContext'],
77
- ])
78
69
  // Origin value in tracestate replaces '~', ',' and ';' with '_"
79
70
  const tracestateOriginFilter = /[^\x20-\x2B\x2D-\x3A\x3C-\x7D]/g
80
71
  // Tag keys in tracestate replace ' ', ',' and '=' with '_'
@@ -86,35 +77,216 @@ const zeroTraceId = '0000000000000000'
86
77
  const hex16 = /^[0-9A-Fa-f]{16}$/
87
78
  const percentByte = /%([0-9A-Fa-f]{2})/g
88
79
 
80
+ /**
81
+ * @typedef {object} B3Context
82
+ * @property {string} [flags]
83
+ * @property {string} [sampled]
84
+ * @property {string} [spanId]
85
+ * @property {string} [traceId]
86
+ */
87
+
88
+ /**
89
+ * @param {string | undefined} traceId
90
+ * @param {string | undefined} spanId
91
+ * @param {number} radix
92
+ * @returns {DatadogSpanContext | undefined}
93
+ */
94
+ function extractGenericContext (traceId, spanId, radix) {
95
+ if (!traceId || invalidSegment.test(traceId)) return
96
+ if (!spanId) return
97
+
98
+ return new DatadogSpanContext({
99
+ traceId: id(traceId, radix),
100
+ spanId: id(spanId, radix),
101
+ isRemote: true,
102
+ })
103
+ }
104
+
105
+ /**
106
+ * @param {string} traceId
107
+ * @param {DatadogSpanContext} spanContext
108
+ * @returns {void}
109
+ */
110
+ function extract128BitTraceId (traceId, spanContext) {
111
+ const buffer = spanContext._traceId.toBuffer()
112
+
113
+ if (buffer.length !== 16) return
114
+
115
+ const tid = traceId.slice(0, 16)
116
+
117
+ if (tid === zeroTraceId) return
118
+
119
+ spanContext._trace.tags['_dd.p.tid'] = tid
120
+ }
121
+
122
+ /**
123
+ * @param {string | undefined} sampled
124
+ * @param {boolean} debug
125
+ * @returns {import('../../priority_sampler').SamplingPriority | undefined}
126
+ */
127
+ function getB3Priority (sampled, debug) {
128
+ if (debug) {
129
+ return USER_KEEP
130
+ } else if (sampled === '1') {
131
+ return AUTO_KEEP
132
+ } else if (sampled === '0') {
133
+ return AUTO_REJECT
134
+ }
135
+ }
136
+
137
+ /**
138
+ * @param {B3Context} b3
139
+ * @returns {DatadogSpanContext | undefined}
140
+ */
141
+ function extractB3Context (b3) {
142
+ const priority = getB3Priority(b3.sampled, b3.flags === '1')
143
+ const spanContext = extractGenericContext(b3.traceId, b3.spanId, 16)
144
+
145
+ if (priority !== undefined) {
146
+ if (!spanContext) {
147
+ return new DatadogSpanContext({
148
+ traceId: id(),
149
+ spanId: null,
150
+ sampling: { priority },
151
+ isRemote: true,
152
+ })
153
+ }
154
+
155
+ spanContext._sampling.priority = priority
156
+ }
157
+
158
+ if (spanContext && b3.traceId) extract128BitTraceId(b3.traceId, spanContext)
159
+
160
+ return spanContext
161
+ }
162
+
163
+ /**
164
+ * @param {Record<string, unknown>} carrier
165
+ * @returns {B3Context | undefined}
166
+ */
167
+ function extractB3MultipleHeaders (carrier) {
168
+ // Parent ID is intentionally not a standalone signal for B3 extraction.
169
+ const traceId = readB3TraceId(carrier)
170
+ const sampled = readB3Sampled(carrier)
171
+ const flags = readB3Flags(carrier)
172
+
173
+ if (traceId === undefined && sampled === undefined && flags === undefined) return
174
+
175
+ let empty = true
176
+ const b3 = {}
177
+ const spanId = readB3SpanId(carrier)
178
+
179
+ if (traceId && spanId && b3TraceExpr.test(traceId) && b3SpanExpr.test(spanId)) {
180
+ b3.traceId = traceId
181
+ b3.spanId = spanId
182
+ empty = false
183
+ }
184
+
185
+ if (sampled) {
186
+ b3.sampled = sampled
187
+ empty = false
188
+ }
189
+
190
+ if (flags) {
191
+ b3.flags = flags
192
+ empty = false
193
+ }
194
+
195
+ return empty ? undefined : b3
196
+ }
197
+
198
+ /**
199
+ * @param {string} header
200
+ * @returns {B3Context}
201
+ */
202
+ function extractB3SingleHeader (header) {
203
+ const traceIdEnd = header.indexOf('-')
204
+
205
+ if (traceIdEnd === -1) {
206
+ if (header === 'd') {
207
+ return {
208
+ sampled: '1',
209
+ flags: '1',
210
+ }
211
+ }
212
+ return {
213
+ sampled: header,
214
+ }
215
+ }
216
+
217
+ const spanIdStart = traceIdEnd + 1
218
+ const spanIdEnd = spanIdStart + 16
219
+ const b3 = {
220
+ traceId: header.slice(0, traceIdEnd),
221
+ spanId: header.slice(spanIdStart, spanIdEnd),
222
+ }
223
+
224
+ if (header.length > spanIdEnd) {
225
+ const sampled = header[spanIdEnd + 1]
226
+ b3.sampled = sampled === '0' ? '0' : '1'
227
+
228
+ if (sampled === 'd') {
229
+ b3.flags = '1'
230
+ }
231
+ }
232
+
233
+ return b3
234
+ }
235
+
236
+ /**
237
+ * @param {Record<string, unknown>} carrier
238
+ * @returns {DatadogSpanContext | undefined}
239
+ */
240
+ function extractB3MultiContext (carrier) {
241
+ const b3 = extractB3MultipleHeaders(carrier)
242
+ if (b3 === undefined) return
243
+ return extractB3Context(b3)
244
+ }
245
+
246
+ /**
247
+ * @param {Record<string, unknown>} carrier
248
+ * @returns {DatadogSpanContext | undefined}
249
+ */
250
+ function extractB3SingleContext (carrier) {
251
+ // Resolve the value before running the regex on the common header-less path.
252
+ const header = readB3(carrier)
253
+ if (!header || !b3HeaderExpr.test(header)) return
254
+ return extractB3Context(extractB3SingleHeader(header))
255
+ }
256
+
89
257
  class TextMapPropagator {
90
- /** @type {Set<string> | undefined} Cached `Set` view of `_config.baggageTagKeys`. */
258
+ /** @type {Set<string> | undefined} Cached `Set` view of `#config.baggageTagKeys`. */
91
259
  #baggageTagKeysSet
92
260
 
93
261
  /** @type {string[] | undefined} Source array that `#baggageTagKeysSet` was built from. */
94
262
  #baggageTagKeysSetSource
95
263
 
96
- /** @type {'_extractB3SingleContext' | '_extractB3MultiContext'} */
97
- #b3MethodName
264
+ /** @type {import('../../config')} */
265
+ #config
266
+
267
+ /** @type {typeof extractB3SingleContext | typeof extractB3MultiContext} */
268
+ #extractB3Context
98
269
 
270
+ /** @param {import('../../config')} config */
99
271
  constructor (config) {
100
- this._config = config
272
+ this.#config = config
101
273
 
102
- // v6: `'b3'` is always single-header. v5: `OTEL_PROPAGATORS` callers
274
+ // v6+: `'b3'` is always single-header. v5: `OTEL_PROPAGATORS` callers
103
275
  // expect single, legacy `DD_TRACE_PROPAGATION_STYLE` callers expect multi.
104
- /* istanbul ignore else: v5 fallback, master ships 6.0.0-pre */
276
+ /* istanbul ignore else: v5 fallback */
105
277
  if (DD_MAJOR >= 6) {
106
- this.#b3MethodName = '_extractB3SingleContext'
278
+ this.#extractB3Context = extractB3SingleContext
107
279
  } else {
108
280
  const envName = getConfiguredEnvName('DD_TRACE_PROPAGATION_STYLE')
109
281
  // eslint-disable-next-line eslint-rules/eslint-env-aliases
110
- this.#b3MethodName = envName === 'OTEL_PROPAGATORS'
111
- ? '_extractB3SingleContext'
112
- : '_extractB3MultiContext'
282
+ this.#extractB3Context = envName === 'OTEL_PROPAGATORS'
283
+ ? extractB3SingleContext
284
+ : extractB3MultiContext
113
285
  }
114
286
  }
115
287
 
116
288
  /**
117
- * Returns a `Set` view of `_config.baggageTagKeys` that is rebuilt only
289
+ * Returns a `Set` view of `#config.baggageTagKeys` that is rebuilt only
118
290
  * when the source array reference changes. Avoids an `O(n)` `Set` alloc
119
291
  * per baggage extract (which is per-request when baggage propagation is
120
292
  * enabled).
@@ -122,7 +294,7 @@ class TextMapPropagator {
122
294
  * @returns {Set<string>}
123
295
  */
124
296
  #getBaggageTagKeysSet () {
125
- const source = this._config.baggageTagKeys
297
+ const source = this.#config.baggageTagKeys
126
298
  if (this.#baggageTagKeysSetSource !== source) {
127
299
  this.#baggageTagKeysSet = new Set(source)
128
300
  this.#baggageTagKeysSetSource = source
@@ -137,18 +309,18 @@ class TextMapPropagator {
137
309
  */
138
310
  inject (spanContext, carrier) {
139
311
  if (carrier === null) return
140
- let injectedCarrier = this._injectBaggageItems(spanContext, carrier)
312
+ let injectedCarrier = this.#injectBaggageItems(spanContext, carrier)
141
313
  if (!spanContext) return injectedCarrier
142
314
 
143
- const injectTraceContext = this._config.apmTracingEnabled !== false ||
315
+ const injectTraceContext = this.#config.apmTracingEnabled !== false ||
144
316
  hasTraceSourcePropagationTag(spanContext._trace.tags)
145
317
  if (injectTraceContext) {
146
- injectedCarrier = this._injectDatadog(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
147
- injectedCarrier = this._injectB3MultipleHeaders(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
148
- injectedCarrier = this._injectB3SingleHeader(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
318
+ injectedCarrier = this.#injectDatadog(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
319
+ injectedCarrier = this.#injectB3MultipleHeaders(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
320
+ injectedCarrier = this.#injectB3SingleHeader(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
149
321
  }
150
322
  injectedCarrier = this
151
- ._injectTraceparent(spanContext, injectedCarrier ?? carrier, injectTraceContext) ?? injectedCarrier
323
+ .#injectTraceparent(spanContext, injectedCarrier ?? carrier, injectTraceContext) ?? injectedCarrier
152
324
 
153
325
  if (injectedCarrier === undefined) return
154
326
 
@@ -161,8 +333,12 @@ class TextMapPropagator {
161
333
  return carrier
162
334
  }
163
335
 
336
+ /**
337
+ * @param {Record<string, unknown>} carrier
338
+ * @returns {DatadogSpanContext | null}
339
+ */
164
340
  extract (carrier) {
165
- const spanContext = this._extractSpanContext(carrier)
341
+ const spanContext = this.#extractSpanContext(carrier)
166
342
  if (spanContext === undefined) return null
167
343
 
168
344
  if (extractCh.hasSubscribers) {
@@ -172,7 +348,7 @@ class TextMapPropagator {
172
348
  // eslint-disable-next-line eslint-rules/eslint-log-printf-style
173
349
  log.debug(() => {
174
350
  const keys = JSON.stringify(pickTextMap(carrier))
175
- const styles = this._config.tracePropagationStyle.extract.join(', ')
351
+ const styles = this.#config.tracePropagationStyle.extract.join(', ')
176
352
 
177
353
  return `Extract from carrier (${styles}): ${keys}.`
178
354
  })
@@ -185,34 +361,22 @@ class TextMapPropagator {
185
361
  * @param {Record<string, string>} [carrier]
186
362
  * @returns {Record<string, string> | undefined}
187
363
  */
188
- _injectDatadog (spanContext, carrier) {
189
- if (!this._hasPropagationStyle('inject', 'datadog')) return
364
+ #injectDatadog (spanContext, carrier) {
365
+ if (!this.#hasPropagationStyle('inject', 'datadog')) return
190
366
 
191
367
  carrier ??= {}
192
368
  writeDatadogTraceId(carrier, spanContext.toTraceId())
193
369
  writeDatadogParentId(carrier, spanContext.toSpanId())
194
370
 
195
- this._injectOrigin(spanContext, carrier)
196
- this._injectSamplingPriority(spanContext, carrier)
197
- this._injectTags(spanContext, carrier)
198
-
199
- return carrier
200
- }
201
-
202
- _injectOrigin (spanContext, carrier) {
203
371
  const origin = spanContext._trace.origin
372
+ if (origin) writeDatadogOrigin(carrier, origin)
204
373
 
205
- if (origin) {
206
- writeDatadogOrigin(carrier, origin)
207
- }
208
- }
209
-
210
- _injectSamplingPriority (spanContext, carrier) {
211
374
  const priority = spanContext._sampling.priority
375
+ if (Number.isInteger(priority)) writeDatadogSamplingPriority(carrier, priority.toString())
212
376
 
213
- if (Number.isInteger(priority)) {
214
- writeDatadogSamplingPriority(carrier, priority.toString())
215
- }
377
+ this.#injectTags(spanContext, carrier)
378
+
379
+ return carrier
216
380
  }
217
381
 
218
382
  /**
@@ -220,9 +384,9 @@ class TextMapPropagator {
220
384
  * @param {Record<string, string>} [carrier]
221
385
  * @returns {Record<string, string> | undefined}
222
386
  */
223
- _injectBaggageItems (spanContext, carrier) {
387
+ #injectBaggageItems (spanContext, carrier) {
224
388
  let injectedCarrier
225
- if (this._config.legacyBaggageEnabled) {
389
+ if (this.#config.legacyBaggageEnabled) {
226
390
  const baggageItems = spanContext?._baggageItems
227
391
  if (baggageItems) {
228
392
  for (const key of Object.keys(baggageItems)) {
@@ -241,7 +405,7 @@ class TextMapPropagator {
241
405
  }
242
406
  }
243
407
 
244
- if (this._hasPropagationStyle('inject', 'baggage')) {
408
+ if (this.#hasPropagationStyle('inject', 'baggage')) {
245
409
  let baggage = ''
246
410
  let itemCounter = 0
247
411
  let byteCounter = 0
@@ -259,13 +423,13 @@ class TextMapPropagator {
259
423
  byteCounter += item.length
260
424
 
261
425
  // Check for item count limit exceeded
262
- if (itemCounter > this._config.baggageMaxItems) {
426
+ if (itemCounter > this.#config.baggageMaxItems) {
263
427
  tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_item_count_exceeded']).inc()
264
428
  break
265
429
  }
266
430
 
267
431
  // Check for byte count limit exceeded
268
- if (byteCounter > this._config.baggageMaxBytes) {
432
+ if (byteCounter > this.#config.baggageMaxBytes) {
269
433
  tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_byte_count_exceeded']).inc()
270
434
  break
271
435
  }
@@ -284,30 +448,34 @@ class TextMapPropagator {
284
448
  return injectedCarrier
285
449
  }
286
450
 
287
- _injectTags (spanContext, carrier) {
451
+ /**
452
+ * @param {DatadogSpanContext} spanContext
453
+ * @param {Record<string, string>} carrier
454
+ * @returns {void}
455
+ */
456
+ #injectTags (spanContext, carrier) {
288
457
  const trace = spanContext._trace
289
458
 
290
- if (this._config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH === 0) {
459
+ if (this.#config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH === 0) {
291
460
  log.debug('Trace tag propagation is disabled, skipping injection.')
292
461
  return
293
462
  }
294
463
 
295
- const tags = []
464
+ let header = ''
296
465
 
297
466
  for (const key of Object.keys(trace.tags)) {
298
467
  const value = trace.tags[key]
299
468
  if (!value || !key.startsWith('_dd.p.')) continue
300
- if (!this._validateTagKey(key) || !this._validateTagValue(value)) {
469
+ if (!tagKeyExpr.test(key) || !tagValueExpr.test(value)) {
301
470
  log.error('Trace tags from span are invalid, skipping injection.')
302
471
  return
303
472
  }
304
473
 
305
- tags.push(`${key}=${value}`)
474
+ if (header) header += ','
475
+ header += `${key}=${value}`
306
476
  }
307
477
 
308
- const header = tags.join(',')
309
-
310
- if (header.length > this._config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH) {
478
+ if (header.length > this.#config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH) {
311
479
  log.error('Trace tags from span are too large, skipping injection.')
312
480
  } else if (header) {
313
481
  writeDatadogTags(carrier, header)
@@ -319,10 +487,10 @@ class TextMapPropagator {
319
487
  * @param {Record<string, string>} [carrier]
320
488
  * @returns {Record<string, string> | undefined}
321
489
  */
322
- _injectB3MultipleHeaders (spanContext, carrier) {
323
- // v5 also accepts the legacy `'b3'` spelling for multi; v6 routes `'b3'` to single-header.
324
- const hasB3multi = this._hasPropagationStyle('inject', 'b3multi') ||
325
- (DD_MAJOR < 6 && this._hasPropagationStyle('inject', 'b3'))
490
+ #injectB3MultipleHeaders (spanContext, carrier) {
491
+ // v5 also accepts the legacy `'b3'` spelling for multi; v6+ routes `'b3'` to single-header.
492
+ const hasB3multi = this.#hasPropagationStyle('inject', 'b3multi') ||
493
+ (DD_MAJOR < 6 && this.#hasPropagationStyle('inject', 'b3'))
326
494
  if (!hasB3multi) return
327
495
 
328
496
  carrier ??= {}
@@ -346,10 +514,10 @@ class TextMapPropagator {
346
514
  * @param {Record<string, string>} [carrier]
347
515
  * @returns {Record<string, string> | undefined}
348
516
  */
349
- _injectB3SingleHeader (spanContext, carrier) {
350
- // v6 keeps `'b3 single header'` as a back-compat alias for callers that bypass parser normalisation.
351
- const hasB3SingleHeader = this._hasPropagationStyle('inject', 'b3 single header') ||
352
- (DD_MAJOR >= 6 && this._hasPropagationStyle('inject', 'b3'))
517
+ #injectB3SingleHeader (spanContext, carrier) {
518
+ // v6+ keeps `'b3 single header'` as a back-compat alias for callers that bypass parser normalisation.
519
+ const hasB3SingleHeader = this.#hasPropagationStyle('inject', 'b3 single header') ||
520
+ (DD_MAJOR >= 6 && this.#hasPropagationStyle('inject', 'b3'))
353
521
  if (!hasB3SingleHeader) return
354
522
 
355
523
  carrier ??= {}
@@ -372,8 +540,8 @@ class TextMapPropagator {
372
540
  * @param {boolean} injectTraceContext
373
541
  * @returns {Record<string, string> | undefined}
374
542
  */
375
- _injectTraceparent (spanContext, carrier, injectTraceContext) {
376
- if (!this._hasPropagationStyle('inject', 'tracecontext')) return
543
+ #injectTraceparent (spanContext, carrier, injectTraceContext) {
544
+ if (!this.#hasPropagationStyle('inject', 'tracecontext')) return
377
545
 
378
546
  if (!injectTraceContext) {
379
547
  const tracestate = TraceState.fromString(spanContext._tracestate?.toString())
@@ -437,53 +605,93 @@ class TextMapPropagator {
437
605
  return carrier
438
606
  }
439
607
 
440
- _hasPropagationStyle (mode, name) {
441
- return this._config.tracePropagationStyle[mode].includes(name)
442
- }
443
-
444
- _hasTraceIdConflict (w3cSpanContext, firstSpanContext) {
445
- return w3cSpanContext !== undefined &&
446
- firstSpanContext.toTraceId(true) === w3cSpanContext.toTraceId(true) &&
447
- firstSpanContext.toSpanId() !== w3cSpanContext.toSpanId()
448
- }
449
-
450
- _hasParentIdInTags (spanContext) {
451
- return tags.DD_PARENT_ID in spanContext._trace.tags
452
- }
453
-
454
- _updateParentIdFromDdHeaders (carrier, firstSpanContext) {
455
- const ddCtx = this._extractDatadogContext(carrier)
456
- if (ddCtx !== undefined) {
457
- firstSpanContext._trace.tags[tags.DD_PARENT_ID] = ddCtx._spanId.toString().padStart(16, '0')
458
- }
608
+ /**
609
+ * @param {'inject' | 'extract'} mode
610
+ * @param {string} name
611
+ * @returns {boolean}
612
+ */
613
+ #hasPropagationStyle (mode, name) {
614
+ return this.#config.tracePropagationStyle[mode].includes(name)
459
615
  }
460
616
 
461
- _resolveTraceContextConflicts (w3cSpanContext, firstSpanContext, carrier) {
462
- if (!this._hasTraceIdConflict(w3cSpanContext, firstSpanContext)) {
617
+ /**
618
+ * @param {DatadogSpanContext | undefined} w3cSpanContext
619
+ * @param {DatadogSpanContext} firstSpanContext
620
+ * @param {Record<string, unknown>} carrier
621
+ * @param {DatadogSpanContext | undefined} datadogContext
622
+ * @returns {DatadogSpanContext}
623
+ */
624
+ #resolveTraceContextConflicts (w3cSpanContext, firstSpanContext, carrier, datadogContext) {
625
+ if (w3cSpanContext === undefined ||
626
+ firstSpanContext.toTraceId(true) !== w3cSpanContext.toTraceId(true) ||
627
+ firstSpanContext.toSpanId() === w3cSpanContext.toSpanId()) {
463
628
  return firstSpanContext
464
629
  }
465
- if (this._hasParentIdInTags(w3cSpanContext)) {
630
+ if (tags.DD_PARENT_ID in w3cSpanContext._trace.tags) {
466
631
  // tracecontext headers contain a p value, ensure this value is sent to backend
467
632
  firstSpanContext._trace.tags[tags.DD_PARENT_ID] = w3cSpanContext._trace.tags[tags.DD_PARENT_ID]
468
633
  } else {
469
634
  // if p value is not present in tracestate, use the parent id from the datadog headers
470
- this._updateParentIdFromDdHeaders(carrier, firstSpanContext)
635
+ datadogContext ||= extractGenericContext(readDatadogTraceId(carrier), readDatadogParentId(carrier), 10)
636
+ if (datadogContext) {
637
+ firstSpanContext._trace.tags[tags.DD_PARENT_ID] = datadogContext._spanId.toString().padStart(16, '0')
638
+ }
471
639
  }
472
640
  // the span_id in tracecontext takes precedence over the first extracted propagation style
473
641
  firstSpanContext._spanId = w3cSpanContext._spanId
474
642
  return firstSpanContext
475
643
  }
476
644
 
477
- _extractSpanContext (carrier) {
645
+ /**
646
+ * @param {Record<string, unknown>} carrier
647
+ * @returns {DatadogSpanContext | undefined}
648
+ */
649
+ #extractSpanContext (carrier) {
478
650
  let context
651
+ let datadogContext
479
652
  let style = ''
480
- for (const extractor of this._config.tracePropagationStyle.extract) {
481
- const method = extractor === 'b3' ? this.#b3MethodName : EXTRACT_STYLE_METHODS.get(extractor)
482
- if (method === undefined) {
483
- if (extractor !== 'baggage') log.warn('Unknown propagation style:', extractor)
484
- continue
653
+ let extractBaggage = false
654
+ let traceContext
655
+ let traceContextExtracted = false
656
+ for (const extractor of this.#config.tracePropagationStyle.extract) {
657
+ let extractedContext
658
+ switch (extractor) {
659
+ case 'datadog':
660
+ datadogContext = this.#extractDatadogContext(carrier)
661
+ extractedContext = datadogContext
662
+ if (extractedContext !== undefined && !this.#config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) {
663
+ if (!traceContextExtracted) {
664
+ traceContext = this.#extractTraceparentContext(carrier)
665
+ traceContextExtracted = true
666
+ }
667
+ this.#addTraceContextState(extractedContext, traceContext)
668
+ }
669
+ break
670
+ case 'tracecontext':
671
+ if (!traceContextExtracted) {
672
+ traceContext = this.#extractTraceparentContext(carrier)
673
+ traceContextExtracted = true
674
+ }
675
+ extractedContext = traceContext
676
+ break
677
+ case 'b3':
678
+ extractedContext = this.#extractB3Context(carrier)
679
+ break
680
+ case 'b3 single header':
681
+ extractedContext = extractB3SingleContext(carrier)
682
+ break
683
+ case 'b3multi':
684
+ extractedContext = extractB3MultiContext(carrier)
685
+ break
686
+ case 'baggage':
687
+ extractBaggage = true
688
+ continue
689
+ case 'none':
690
+ continue
691
+ default:
692
+ log.warn('Unknown propagation style:', extractor)
693
+ continue
485
694
  }
486
- const extractedContext = this[method](carrier)
487
695
  if (extractedContext === undefined) {
488
696
  continue
489
697
  }
@@ -491,14 +699,14 @@ class TextMapPropagator {
491
699
  if (context === undefined) {
492
700
  context = extractedContext
493
701
  style = extractor
494
- if (this._config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) {
702
+ if (this.#config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) {
495
703
  break
496
704
  }
497
705
  } else {
498
706
  // If extractor is tracecontext, add tracecontext specific information to the context
499
707
  if (extractor === 'tracecontext') {
500
- context = this._resolveTraceContextConflicts(
501
- this._extractTraceparentContext(carrier), context, carrier)
708
+ context = this.#resolveTraceContextConflicts(
709
+ extractedContext, context, carrier, datadogContext)
502
710
  }
503
711
  if (extractedContext._traceId && extractedContext._spanId &&
504
712
  extractedContext.toTraceId(true) !== context.toTraceId(true)) {
@@ -511,10 +719,14 @@ class TextMapPropagator {
511
719
  }
512
720
  }
513
721
 
514
- if (this._config.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT === 'ignore') {
722
+ if (context && (style === 'datadog' || style === 'tracecontext')) {
723
+ this.#extractLegacyBaggageItems(carrier, context)
724
+ }
725
+
726
+ if (this.#config.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT === 'ignore') {
515
727
  if (context !== undefined) context._links = []
516
728
  } else {
517
- if (this._config.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT === 'restart' && context) {
729
+ if (this.#config.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT === 'restart' && context) {
518
730
  context._links = []
519
731
  context._links.push({
520
732
  context,
@@ -524,78 +736,47 @@ class TextMapPropagator {
524
736
  },
525
737
  })
526
738
  }
527
- this._extractBaggageItems(carrier, context)
739
+ if (!extractBaggage && this.#config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) {
740
+ extractBaggage = this.#hasPropagationStyle('extract', 'baggage')
741
+ }
742
+ this.#extractBaggageItems(carrier, context, extractBaggage)
528
743
  }
529
744
 
530
- return context || this._extractSqsdContext(carrier)
745
+ return context || this.#extractSqsdContext(carrier)
531
746
  }
532
747
 
533
- _extractDatadogContext (carrier) {
748
+ /**
749
+ * @param {Record<string, unknown>} carrier
750
+ * @returns {DatadogSpanContext | undefined}
751
+ */
752
+ #extractDatadogContext (carrier) {
534
753
  if (!carrier) return
535
- const spanContext = this._extractGenericContext(
536
- readDatadogTraceId(carrier),
537
- readDatadogParentId(carrier),
538
- 10
539
- )
754
+ const traceId = readDatadogTraceId(carrier)
755
+ if (!traceId) return
756
+ const spanContext = extractGenericContext(traceId, readDatadogParentId(carrier), 10)
540
757
 
541
758
  if (!spanContext) return spanContext
542
759
 
543
- this._extractOrigin(carrier, spanContext)
544
- this._extractLegacyBaggageItems(carrier, spanContext)
545
- this._extractSamplingPriority(carrier, spanContext)
546
- const traceTags = this._extractTags(carrier)
547
- if (traceTags) spanContext._trace.tags = traceTags
548
-
549
- if (this._config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) return spanContext
550
-
551
- const tc = this._extractTraceparentContext(carrier)
552
-
553
- if (tc && spanContext._traceId.equals(tc._traceId)) {
554
- spanContext._traceparent = tc._traceparent
555
- spanContext._tracestate = tc._tracestate
556
- }
557
-
558
- return spanContext
559
- }
560
-
561
- _extractB3MultiContext (carrier) {
562
- const b3 = this._extractB3MultipleHeaders(carrier)
563
- if (b3 === undefined) return
564
- return this._extractB3Context(b3)
565
- }
566
-
567
- _extractB3SingleContext (carrier) {
568
- // Check the resolved value first so the regex does not run on header-less requests.
569
- const header = readB3(carrier)
570
- if (!header || !b3HeaderExpr.test(header)) return
571
- return this._extractB3Context(this._extractB3SingleHeader(header))
572
- }
573
-
574
- _extractB3Context (b3) {
575
- const debug = b3.flags === '1'
576
- const priority = this._getPriority(b3.sampled, debug)
577
- const spanContext = this._extractGenericContext(b3.traceId, b3.spanId, 16)
578
-
579
- if (priority !== undefined) {
580
- if (!spanContext) {
581
- // B3 can force a sampling decision without providing IDs
582
- return new DatadogSpanContext({
583
- traceId: id(),
584
- spanId: null,
585
- sampling: { priority },
586
- isRemote: true,
587
- })
588
- }
760
+ const origin = readDatadogOrigin(carrier)
761
+ if (typeof origin === 'string') spanContext._trace.origin = origin
589
762
 
590
- spanContext._sampling.priority = priority
763
+ const header = readDatadogSamplingPriority(carrier)
764
+ if (header !== undefined) {
765
+ const priority = Number.parseInt(header, 10)
766
+ if (Number.isInteger(priority)) spanContext._sampling.priority = priority
591
767
  }
592
768
 
593
- this._extract128BitTraceId(b3.traceId, spanContext)
769
+ const traceTags = this.#extractTags(carrier)
770
+ if (traceTags) spanContext._trace.tags = traceTags
594
771
 
595
772
  return spanContext
596
773
  }
597
774
 
598
- _extractSqsdContext (carrier) {
775
+ /**
776
+ * @param {Record<string, unknown>} carrier
777
+ * @returns {DatadogSpanContext | undefined}
778
+ */
779
+ #extractSqsdContext (carrier) {
599
780
  const headerValue = readSqsd(carrier)
600
781
  if (!headerValue) return
601
782
  let parsed
@@ -604,10 +785,32 @@ class TextMapPropagator {
604
785
  } catch {
605
786
  return
606
787
  }
607
- return this._extractDatadogContext(parsed)
788
+ const spanContext = this.#extractDatadogContext(parsed)
789
+ if (!spanContext) return
790
+
791
+ this.#extractLegacyBaggageItems(parsed, spanContext)
792
+ if (this.#config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) return spanContext
793
+
794
+ this.#addTraceContextState(spanContext, this.#extractTraceparentContext(parsed))
795
+ return spanContext
608
796
  }
609
797
 
610
- _extractTraceparentContext (carrier) {
798
+ /**
799
+ * @param {DatadogSpanContext} datadogContext
800
+ * @param {DatadogSpanContext | undefined} traceContext
801
+ */
802
+ #addTraceContextState (datadogContext, traceContext) {
803
+ if (traceContext && datadogContext._traceId.equals(traceContext._traceId)) {
804
+ datadogContext._traceparent = traceContext._traceparent
805
+ datadogContext._tracestate = traceContext._tracestate
806
+ }
807
+ }
808
+
809
+ /**
810
+ * @param {Record<string, unknown>} carrier
811
+ * @returns {DatadogSpanContext | undefined}
812
+ */
813
+ #extractTraceparentContext (carrier) {
611
814
  const headerValue = readTraceparent(carrier)
612
815
  if (!headerValue) return
613
816
  const matches = headerValue.trim().match(traceparentExpr)
@@ -634,7 +837,7 @@ class TextMapPropagator {
634
837
  tracestate,
635
838
  })
636
839
 
637
- this._extract128BitTraceId(traceId, spanContext)
840
+ extract128BitTraceId(traceId, spanContext)
638
841
 
639
842
  tracestate.forVendor('dd', state => {
640
843
  for (const [key, value] of state.entries()) {
@@ -683,147 +886,78 @@ class TextMapPropagator {
683
886
  }
684
887
  })
685
888
 
686
- this._extractLegacyBaggageItems(carrier, spanContext)
687
889
  return spanContext
688
890
  }
689
891
  }
690
892
 
691
893
  /**
692
- * @param {string | undefined} traceId
693
- * @param {string | undefined} spanId
694
- * @param {number} radix
695
- * @returns {DatadogSpanContext | undefined}
894
+ * @param {Record<string, unknown>} carrier
895
+ * @param {DatadogSpanContext} spanContext
896
+ * @returns {void}
696
897
  */
697
- _extractGenericContext (traceId, spanId, radix) {
698
- if (!traceId || invalidSegment.test(traceId)) return
699
- if (!spanId) return
700
-
701
- return new DatadogSpanContext({
702
- traceId: id(traceId, radix),
703
- spanId: id(spanId, radix),
704
- isRemote: true,
705
- })
706
- }
707
-
708
- _extractB3MultipleHeaders (carrier) {
709
- // The parent-id field is intentionally absent: this method never consults it,
710
- // so a parent-id-only carrier should bail with the rest.
711
- const traceId = readB3TraceId(carrier)
712
- const sampled = readB3Sampled(carrier)
713
- const flags = readB3Flags(carrier)
714
-
715
- if (traceId === undefined && sampled === undefined && flags === undefined) {
716
- return
717
- }
718
-
719
- let empty = true
720
- const b3 = {}
721
- const spanId = readB3SpanId(carrier)
722
-
723
- if (traceId && spanId && b3TraceExpr.test(traceId) && b3SpanExpr.test(spanId)) {
724
- b3.traceId = traceId
725
- b3.spanId = spanId
726
- empty = false
727
- }
728
-
729
- if (sampled) {
730
- b3.sampled = sampled
731
- empty = false
732
- }
733
-
734
- if (flags) {
735
- b3.flags = flags
736
- empty = false
737
- }
738
-
739
- return empty ? undefined : b3
740
- }
741
-
742
- /** @param {string} header */
743
- _extractB3SingleHeader (header) {
744
- const parts = header.split('-')
745
-
746
- if (parts[0] === 'd') {
747
- return {
748
- sampled: '1',
749
- flags: '1',
750
- }
751
- } else if (parts.length === 1) {
752
- return {
753
- sampled: parts[0],
754
- }
755
- }
756
- const b3 = {
757
- traceId: parts[0],
758
- spanId: parts[1],
759
- }
760
-
761
- if (parts[2]) {
762
- b3.sampled = parts[2] === '0' ? '0' : '1'
763
-
764
- if (parts[2] === 'd') {
765
- b3.flags = '1'
766
- }
767
- }
768
-
769
- return b3
770
- }
771
-
772
- _extractOrigin (carrier, spanContext) {
773
- const origin = readDatadogOrigin(carrier)
774
-
775
- if (typeof origin === 'string') {
776
- spanContext._trace.origin = origin
777
- }
778
- }
779
-
780
- _extractLegacyBaggageItems (carrier, spanContext) {
781
- if (!this._config.legacyBaggageEnabled) return
898
+ #extractLegacyBaggageItems (carrier, spanContext) {
899
+ if (!this.#config.legacyBaggageEnabled) return
782
900
  readLegacyBaggage(carrier, spanContext._baggageItems)
783
901
  }
784
902
 
785
- _extractBaggageItems (carrier, spanContext) {
903
+ /**
904
+ * @param {Record<string, unknown> | undefined} carrier
905
+ * @param {DatadogSpanContext | undefined} spanContext
906
+ * @param {boolean} extractBaggage
907
+ * @returns {void}
908
+ */
909
+ #extractBaggageItems (carrier, spanContext, extractBaggage) {
786
910
  removeAllBaggageItems()
787
- if (!carrier || !this._hasPropagationStyle('extract', 'baggage')) return
911
+ if (!carrier || !extractBaggage) return
788
912
  const header = readBaggage(carrier)
789
913
  if (!header) return
790
914
 
791
- const baggages = header.split(',')
792
915
  const baggageTagKeys = this.#getBaggageTagKeysSet()
793
916
  const tagAllKeys = baggageTagKeys.has('*')
794
917
  /** @type {Record<string, string> | undefined} */
795
918
  let items
796
919
  let itemCount = 0
797
920
  let byteCount = 0
921
+ let start = 0
798
922
 
799
- for (const keyValue of baggages) {
800
- if (itemCount >= this._config.baggageMaxItems) {
923
+ while (start <= header.length) {
924
+ if (itemCount >= this.#config.baggageMaxItems) {
801
925
  tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_item_count_exceeded']).inc()
802
926
  break
803
927
  }
928
+
929
+ const memberStart = start
930
+ const commaIndex = header.indexOf(',', memberStart)
931
+ const end = commaIndex === -1 ? header.length : commaIndex
932
+
804
933
  // Charge the comma slot before the empty-entry skip so a `,,,,,foo=bar` can't iterate for free.
805
- byteCount += keyValue.length + 1
806
- if (byteCount > this._config.baggageMaxBytes) {
934
+ byteCount += end - memberStart + 1
935
+ if (byteCount > this.#config.baggageMaxBytes) {
807
936
  tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_byte_count_exceeded']).inc()
808
937
  break
809
938
  }
810
- if (!keyValue) continue
939
+ if (memberStart === end) {
940
+ start = end + 1
941
+ continue
942
+ }
811
943
 
812
944
  // Per W3C baggage, list-members can contain optional properties after `;`.
813
945
  // Example: key=value;prop=1;prop2
814
946
  // https://www.w3.org/TR/baggage/#header-content
815
- const semicolonIdx = keyValue.indexOf(';')
816
- const member = (semicolonIdx === -1 ? keyValue : keyValue.slice(0, semicolonIdx)).trim()
817
- if (!member) continue
818
-
819
- const eqIdx = member.indexOf('=')
820
- if (eqIdx === -1) {
947
+ let memberEnd = header.indexOf(';', memberStart)
948
+ if (memberEnd === -1 || memberEnd > end) memberEnd = end
949
+ const equalsIndex = header.indexOf('=', memberStart)
950
+ start = end + 1
951
+
952
+ if (equalsIndex === -1 || equalsIndex >= memberEnd) {
953
+ const member = header.slice(memberStart, memberEnd).trim()
954
+ if (!member) continue
821
955
  tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
822
956
  return
823
957
  }
824
958
 
825
- const key = member.slice(0, eqIdx).trim()
826
- let value = member.slice(eqIdx + 1).trim()
959
+ const key = header.slice(memberStart, equalsIndex).trim()
960
+ let value = header.slice(equalsIndex + 1, memberEnd).trim()
827
961
 
828
962
  if (!baggageTokenExpr.test(key) || !value) {
829
963
  tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
@@ -856,27 +990,17 @@ class TextMapPropagator {
856
990
  }
857
991
  }
858
992
 
859
- _extractSamplingPriority (carrier, spanContext) {
860
- const header = readDatadogSamplingPriority(carrier)
861
- if (header === undefined) return
862
- const priority = Number.parseInt(header, 10)
863
-
864
- if (Number.isInteger(priority)) {
865
- spanContext._sampling.priority = priority
866
- }
867
- }
868
-
869
993
  /**
870
994
  * @param {Record<string, unknown>} carrier
871
995
  * @returns {Record<string, string> | undefined}
872
996
  */
873
- _extractTags (carrier) {
997
+ #extractTags (carrier) {
874
998
  const header = readDatadogTags(carrier)
875
999
  if (!header) return
876
1000
 
877
- if (this._config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH === 0) {
1001
+ if (this.#config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH === 0) {
878
1002
  log.debug('Trace tag propagation is disabled, skipping extraction.')
879
- } else if (header.length > this._config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH) {
1003
+ } else if (header.length > this.#config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH) {
880
1004
  log.error('Trace tags from carrier are too large, skipping extraction.')
881
1005
  } else {
882
1006
  const tags = {}
@@ -890,7 +1014,7 @@ class TextMapPropagator {
890
1014
  const key = header.slice(start, hasSeparator ? separator : end)
891
1015
  const value = hasSeparator ? header.slice(separator + 1, end) : ''
892
1016
 
893
- if (!this._validateTagKey(key) || !this._validateTagValue(value)) {
1017
+ if (!tagKeyExpr.test(key) || !tagValueExpr.test(value)) {
894
1018
  log.error('Trace tags from carrier are invalid, skipping extraction.')
895
1019
  return
896
1020
  }
@@ -907,62 +1031,6 @@ class TextMapPropagator {
907
1031
  return tags
908
1032
  }
909
1033
  }
910
-
911
- _extract128BitTraceId (traceId, spanContext) {
912
- if (!spanContext) return
913
-
914
- const buffer = spanContext._traceId.toBuffer()
915
-
916
- if (buffer.length !== 16) return
917
-
918
- const tid = traceId.slice(0, 16)
919
-
920
- if (tid === zeroTraceId) return
921
-
922
- spanContext._trace.tags['_dd.p.tid'] = tid
923
- }
924
-
925
- _validateTagKey (key) {
926
- return tagKeyExpr.test(key)
927
- }
928
-
929
- _validateTagValue (value) {
930
- return tagValueExpr.test(value)
931
- }
932
-
933
- _getPriority (sampled, debug) {
934
- if (debug) {
935
- return USER_KEEP
936
- } else if (sampled === '1') {
937
- return AUTO_KEEP
938
- } else if (sampled === '0') {
939
- return AUTO_REJECT
940
- }
941
- }
942
-
943
- /**
944
- * @param {number} traceparentSampled
945
- * @param {number|undefined} tracestateSamplingPriority
946
- * @param {string|null} origin
947
- * @returns {import('../../priority_sampler').SamplingPriority}
948
- */
949
- static _getSamplingPriority (traceparentSampled, tracestateSamplingPriority, origin) {
950
- const fromRumWithoutPriority = !tracestateSamplingPriority && origin === 'rum'
951
-
952
- let samplingPriority =
953
- /** @type {import('../../priority_sampler').SamplingPriority} */ (tracestateSamplingPriority ?? AUTO_KEEP)
954
- if (!fromRumWithoutPriority) {
955
- if (traceparentSampled === 0 &&
956
- (!tracestateSamplingPriority || tracestateSamplingPriority >= 0)) {
957
- samplingPriority = AUTO_REJECT
958
- } else if (traceparentSampled === 1 &&
959
- (!tracestateSamplingPriority || tracestateSamplingPriority < 0)) {
960
- samplingPriority = AUTO_KEEP
961
- }
962
- }
963
-
964
- return samplingPriority
965
- }
966
1034
  }
967
1035
 
968
1036
  module.exports = TextMapPropagator