dd-trace 6.12.0 → 6.14.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.
- package/LICENSE-3rdparty.csv +3 -1
- package/ci/init.js +8 -3
- package/ci/test-optimization-validation/ci-package-scripts.js +2 -2
- package/ci/test-optimization-validation/ci-remediation.js +6 -6
- package/ci/test-optimization-validation/command-blocker.js +7 -5
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +1 -1
- package/ci/test-optimization-validation/framework-adapters/cypress.js +9 -11
- package/ci/test-optimization-validation/framework-adapters/vitest.js +3 -3
- package/ci/test-optimization-validation/package-check.js +1 -1
- package/ci/test-optimization-validation/report-writer.js +7 -5
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +5 -4
- package/ci/vitest-no-worker-init-runner-setup.mjs +8 -0
- package/ci/vitest-no-worker-init-setup.mjs +13 -13
- package/ci/vitest-no-worker-init-v5-setup.mjs +4 -0
- package/index.d.ts +127 -26
- package/package.json +22 -19
- package/packages/datadog-esbuild/index.js +3 -1
- package/packages/datadog-instrumentations/src/bunyan.js +4 -2
- package/packages/datadog-instrumentations/src/cypress-config.js +19 -17
- package/packages/datadog-instrumentations/src/fs.js +24 -20
- package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +2 -2
- package/packages/datadog-instrumentations/src/graphql.js +16 -16
- package/packages/datadog-instrumentations/src/helpers/bunyan.js +12 -3
- package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +504 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +266 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +95 -30
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +0 -25
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +83 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +85 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/mercurius.js +30 -12
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +13 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +279 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +12 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +562 -27
- package/packages/datadog-instrumentations/src/jest.js +165 -38
- package/packages/datadog-instrumentations/src/knex.js +76 -0
- package/packages/datadog-instrumentations/src/mariadb-bundle.js +1597 -0
- package/packages/datadog-instrumentations/src/mariadb.js +13 -0
- package/packages/datadog-instrumentations/src/mocha/common.js +59 -2
- package/packages/datadog-instrumentations/src/mocha/main.js +25 -15
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -1
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +98 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +12 -8
- package/packages/datadog-instrumentations/src/net.js +14 -17
- package/packages/datadog-instrumentations/src/next.js +212 -62
- package/packages/datadog-instrumentations/src/openai.js +42 -40
- package/packages/datadog-instrumentations/src/pg.js +15 -0
- package/packages/datadog-instrumentations/src/pino.js +15 -4
- package/packages/datadog-instrumentations/src/playwright.js +137 -27
- package/packages/datadog-instrumentations/src/rum-browser-scripts.js +40 -0
- package/packages/datadog-instrumentations/src/sequelize.js +94 -2
- package/packages/datadog-instrumentations/src/undici.js +53 -4
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +44 -7
- package/packages/datadog-instrumentations/src/vitest-main.js +92 -9
- package/packages/datadog-instrumentations/src/vitest-worker.js +82 -14
- package/packages/datadog-instrumentations/src/webdriverio.js +986 -1
- package/packages/datadog-instrumentations/src/winston.js +6 -3
- package/packages/datadog-plugin-amqp10/src/consumer.js +3 -1
- package/packages/datadog-plugin-amqp10/src/producer.js +3 -1
- package/packages/datadog-plugin-amqp10/src/util.js +2 -1
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +6 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +16 -5
- package/packages/datadog-plugin-cassandra-driver/src/index.js +8 -3
- package/packages/datadog-plugin-cucumber/src/index.js +0 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +262 -48
- package/packages/datadog-plugin-cypress/src/support.js +1 -0
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -1
- package/packages/datadog-plugin-graphql/src/execute.js +998 -196
- package/packages/datadog-plugin-graphql/src/index.js +27 -7
- package/packages/datadog-plugin-graphql/src/jit.js +136 -0
- package/packages/datadog-plugin-graphql/src/request.js +18 -27
- package/packages/datadog-plugin-graphql/src/resolve-error.js +108 -0
- package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -2
- package/packages/datadog-plugin-graphql/src/tools/transforms.js +45 -3
- package/packages/datadog-plugin-graphql/src/utils.js +208 -120
- package/packages/datadog-plugin-graphql/src/validate.js +10 -23
- package/packages/datadog-plugin-http/src/client.js +2 -15
- package/packages/datadog-plugin-http2/src/client.js +2 -15
- package/packages/datadog-plugin-jest/src/index.js +0 -6
- package/packages/datadog-plugin-langchain/src/tracing.js +7 -0
- package/packages/datadog-plugin-mocha/src/index.js +403 -75
- package/packages/datadog-plugin-mongodb-core/src/query.js +6 -0
- package/packages/datadog-plugin-mysql/src/index.js +41 -15
- package/packages/datadog-plugin-net/src/tcp.js +3 -1
- package/packages/datadog-plugin-next/src/index.js +63 -29
- package/packages/datadog-plugin-openai-agents/src/integration.js +15 -11
- package/packages/datadog-plugin-playwright/src/index.js +176 -28
- package/packages/datadog-plugin-undici/src/index.js +29 -56
- package/packages/datadog-plugin-vitest/src/index.js +6 -12
- package/packages/dd-trace/src/aiguard/evaluation.js +96 -21
- package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -3
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +29 -10
- package/packages/dd-trace/src/aiguard/messages/openai.js +8 -1
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +20 -6
- package/packages/dd-trace/src/aiguard/noop.js +9 -1
- package/packages/dd-trace/src/aiguard/redaction.js +183 -0
- package/packages/dd-trace/src/aiguard/sdk.js +7 -2
- package/packages/dd-trace/src/aiguard/tags.js +2 -0
- package/packages/dd-trace/src/appsec/api_security/index.js +23 -6
- package/packages/dd-trace/src/appsec/api_security/sampler.js +99 -40
- package/packages/dd-trace/src/appsec/graphql.js +6 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +3 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +8 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +11 -36
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +10 -9
- package/packages/dd-trace/src/appsec/lambda.js +44 -26
- package/packages/dd-trace/src/appsec/rule_manager.js +2 -0
- package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +32 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +8 -8
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +6 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +20 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +7 -150
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +7 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agents.js +54 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +1 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +397 -234
- package/packages/dd-trace/src/ci-visibility/exporters/limits.js +9 -0
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +323 -31
- package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +42 -0
- package/packages/dd-trace/src/ci-visibility/final-flush.js +21 -0
- package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +57 -18
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +0 -3
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +164 -71
- package/packages/dd-trace/src/ci-visibility/requests/video-request.js +176 -0
- package/packages/dd-trace/src/ci-visibility/telemetry.js +10 -7
- package/packages/dd-trace/src/ci-visibility/test-video.js +61 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +10 -0
- package/packages/dd-trace/src/config/index.js +75 -14
- package/packages/dd-trace/src/config/parsers.js +11 -1
- package/packages/dd-trace/src/config/stable.js +3 -3
- package/packages/dd-trace/src/config/supported-configurations.json +47 -2
- package/packages/dd-trace/src/crashtracking/crashtracker.js +82 -18
- package/packages/dd-trace/src/debugger/config.js +12 -1
- package/packages/dd-trace/src/debugger/constants.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/request-options.js +33 -0
- package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -39
- package/packages/dd-trace/src/debugger/devtools_client/status.js +11 -6
- package/packages/dd-trace/src/debugger/devtools_client/tags.js +41 -0
- package/packages/dd-trace/src/debugger/index.js +23 -3
- package/packages/dd-trace/src/dogstatsd.js +532 -71
- package/packages/dd-trace/src/encode/0.4-cross-payload.js +170 -0
- package/packages/dd-trace/src/encode/0.4.js +5 -5
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -8
- package/packages/dd-trace/src/evp_proxy/direct.js +27 -23
- package/packages/dd-trace/src/exporters/agent/index.js +24 -3
- package/packages/dd-trace/src/exporters/agent/writer.js +28 -11
- package/packages/dd-trace/src/exporters/agentless/index.js +7 -9
- package/packages/dd-trace/src/exporters/agentless/writer.js +100 -118
- package/packages/dd-trace/src/exporters/common/agents.js +28 -6
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -2
- package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +191 -0
- package/packages/dd-trace/src/exporters/common/request.js +31 -11
- package/packages/dd-trace/src/exporters/common/url.js +40 -1
- package/packages/dd-trace/src/exporters/common/writer.js +31 -7
- package/packages/dd-trace/src/exporters/span-stats/index.js +23 -4
- package/packages/dd-trace/src/external-logger/src/index.js +4 -3
- package/packages/dd-trace/src/flush.js +105 -0
- package/packages/dd-trace/src/id.js +14 -0
- package/packages/dd-trace/src/index.js +5 -2
- package/packages/dd-trace/src/llmobs/experiments/client.js +4 -0
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +52 -2
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +420 -105
- package/packages/dd-trace/src/llmobs/experiments/index.js +54 -42
- package/packages/dd-trace/src/llmobs/experiments/noop.js +39 -8
- package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/util.js +21 -0
- package/packages/dd-trace/src/llmobs/index.js +111 -48
- package/packages/dd-trace/src/llmobs/noop.js +2 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +22 -71
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +23 -13
- package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +8 -4
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +6 -3
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +7 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +13 -6
- package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +5 -7
- package/packages/dd-trace/src/llmobs/util.js +0 -33
- package/packages/dd-trace/src/llmobs/writers/base.js +106 -53
- package/packages/dd-trace/src/log/index.js +7 -1
- package/packages/dd-trace/src/log-submission/log-submission-plugin.js +249 -0
- package/packages/dd-trace/src/noop/span.js +5 -0
- package/packages/dd-trace/src/openfeature/writers/base.js +14 -12
- package/packages/dd-trace/src/openfeature/writers/exposures.js +8 -1
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +45 -3
- package/packages/dd-trace/src/opentelemetry/logs/index.js +9 -25
- package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +7 -4
- package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +14 -4
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +18 -23
- package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +8 -0
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +18 -6
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +14 -2
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +25 -5
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +61 -25
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +19 -4
- package/packages/dd-trace/src/opentelemetry/resource-attributes.js +55 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +6 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +10 -0
- package/packages/dd-trace/src/opentelemetry/tracer.js +26 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +494 -351
- package/packages/dd-trace/src/opentracing/span.js +28 -0
- package/packages/dd-trace/src/otel-thread-ctx.js +23 -5
- package/packages/dd-trace/src/payload-tagging/index.js +2 -1
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +1 -6
- package/packages/dd-trace/src/plugins/tracing.js +12 -10
- package/packages/dd-trace/src/plugins/util/ci.js +3 -1
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +16 -15
- package/packages/dd-trace/src/plugins/util/status-validator.js +98 -0
- package/packages/dd-trace/src/plugins/util/test.js +157 -41
- package/packages/dd-trace/src/plugins/util/url.js +2 -2
- package/packages/dd-trace/src/plugins/util/web.js +6 -74
- package/packages/dd-trace/src/profiling/config.js +1 -0
- package/packages/dd-trace/src/profiling/oom.js +11 -5
- package/packages/dd-trace/src/profiling/profiler.js +30 -13
- package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
- package/packages/dd-trace/src/profiling/profilers/space.js +38 -11
- package/packages/dd-trace/src/profiling/profilers/wall.js +14 -14
- package/packages/dd-trace/src/profiling/webspan-utils.js +7 -4
- package/packages/dd-trace/src/proxy.js +108 -10
- package/packages/dd-trace/src/remote_config/index.js +319 -101
- package/packages/dd-trace/src/remote_config/scheduler.js +37 -12
- package/packages/dd-trace/src/runtime_metrics/client.js +37 -8
- package/packages/dd-trace/src/runtime_metrics/index.js +5 -0
- package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +10 -1
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +22 -7
- package/packages/dd-trace/src/sampling_rule.js +36 -9
- package/packages/dd-trace/src/serverless/telemetry-delivery-tracker.js +51 -0
- package/packages/dd-trace/src/serverless/vercel.js +155 -0
- package/packages/dd-trace/src/serverless.js +45 -21
- package/packages/dd-trace/src/service-naming/schemas/util.js +1 -1
- package/packages/dd-trace/src/span_stats.js +64 -31
- package/packages/dd-trace/src/startup-log.js +3 -2
- package/packages/dd-trace/src/telemetry/agentless-url.js +28 -0
- package/packages/dd-trace/src/telemetry/send-data.js +18 -16
- package/packages/dd-trace/src/telemetry/session-propagation.js +3 -2
- package/packages/dd-trace/src/tracer.js +26 -5
- package/packages/dd-trace/src/tracer_metadata.js +11 -3
- package/packages/dd-trace/src/web-tags-cache.js +67 -13
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +0 -27
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +0 -53
- package/packages/dd-trace/src/encode/agentless-json.js +0 -209
|
@@ -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,228 @@ 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 {Array<string | undefined>} traceTagReplacements
|
|
90
|
+
* @param {string} key
|
|
91
|
+
* @returns {boolean}
|
|
92
|
+
*/
|
|
93
|
+
function hasTraceTagReplacement (traceTagReplacements, key) {
|
|
94
|
+
for (let index = 0; index < traceTagReplacements.length; index += 2) {
|
|
95
|
+
if (traceTagReplacements[index] === key) return true
|
|
96
|
+
}
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {string | undefined} traceId
|
|
102
|
+
* @param {string | undefined} spanId
|
|
103
|
+
* @param {number} radix
|
|
104
|
+
* @returns {DatadogSpanContext | undefined}
|
|
105
|
+
*/
|
|
106
|
+
function extractGenericContext (traceId, spanId, radix) {
|
|
107
|
+
if (!traceId || invalidSegment.test(traceId)) return
|
|
108
|
+
if (!spanId) return
|
|
109
|
+
|
|
110
|
+
return new DatadogSpanContext({
|
|
111
|
+
traceId: id(traceId, radix),
|
|
112
|
+
spanId: id(spanId, radix),
|
|
113
|
+
isRemote: true,
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param {string} traceId
|
|
119
|
+
* @param {DatadogSpanContext} spanContext
|
|
120
|
+
* @returns {void}
|
|
121
|
+
*/
|
|
122
|
+
function extract128BitTraceId (traceId, spanContext) {
|
|
123
|
+
const buffer = spanContext._traceId.toBuffer()
|
|
124
|
+
|
|
125
|
+
if (buffer.length !== 16) return
|
|
126
|
+
|
|
127
|
+
const tid = traceId.slice(0, 16)
|
|
128
|
+
|
|
129
|
+
if (tid === zeroTraceId) return
|
|
130
|
+
|
|
131
|
+
spanContext._trace.tags['_dd.p.tid'] = tid
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @param {string | undefined} sampled
|
|
136
|
+
* @param {boolean} debug
|
|
137
|
+
* @returns {import('../../priority_sampler').SamplingPriority | undefined}
|
|
138
|
+
*/
|
|
139
|
+
function getB3Priority (sampled, debug) {
|
|
140
|
+
if (debug) {
|
|
141
|
+
return USER_KEEP
|
|
142
|
+
} else if (sampled === '1') {
|
|
143
|
+
return AUTO_KEEP
|
|
144
|
+
} else if (sampled === '0') {
|
|
145
|
+
return AUTO_REJECT
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {B3Context} b3
|
|
151
|
+
* @returns {DatadogSpanContext | undefined}
|
|
152
|
+
*/
|
|
153
|
+
function extractB3Context (b3) {
|
|
154
|
+
const priority = getB3Priority(b3.sampled, b3.flags === '1')
|
|
155
|
+
const spanContext = extractGenericContext(b3.traceId, b3.spanId, 16)
|
|
156
|
+
|
|
157
|
+
if (priority !== undefined) {
|
|
158
|
+
if (!spanContext) {
|
|
159
|
+
return new DatadogSpanContext({
|
|
160
|
+
traceId: id(),
|
|
161
|
+
spanId: null,
|
|
162
|
+
sampling: { priority },
|
|
163
|
+
isRemote: true,
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
spanContext._sampling.priority = priority
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (spanContext && b3.traceId) extract128BitTraceId(b3.traceId, spanContext)
|
|
171
|
+
|
|
172
|
+
return spanContext
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @param {Record<string, unknown>} carrier
|
|
177
|
+
* @returns {B3Context | undefined}
|
|
178
|
+
*/
|
|
179
|
+
function extractB3MultipleHeaders (carrier) {
|
|
180
|
+
// Parent ID is intentionally not a standalone signal for B3 extraction.
|
|
181
|
+
const traceId = readB3TraceId(carrier)
|
|
182
|
+
const sampled = readB3Sampled(carrier)
|
|
183
|
+
const flags = readB3Flags(carrier)
|
|
184
|
+
|
|
185
|
+
if (traceId === undefined && sampled === undefined && flags === undefined) return
|
|
186
|
+
|
|
187
|
+
let empty = true
|
|
188
|
+
const b3 = {}
|
|
189
|
+
const spanId = readB3SpanId(carrier)
|
|
190
|
+
|
|
191
|
+
if (traceId && spanId && b3TraceExpr.test(traceId) && b3SpanExpr.test(spanId)) {
|
|
192
|
+
b3.traceId = traceId
|
|
193
|
+
b3.spanId = spanId
|
|
194
|
+
empty = false
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (sampled) {
|
|
198
|
+
b3.sampled = sampled
|
|
199
|
+
empty = false
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (flags) {
|
|
203
|
+
b3.flags = flags
|
|
204
|
+
empty = false
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return empty ? undefined : b3
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @param {string} header
|
|
212
|
+
* @returns {B3Context}
|
|
213
|
+
*/
|
|
214
|
+
function extractB3SingleHeader (header) {
|
|
215
|
+
const traceIdEnd = header.indexOf('-')
|
|
216
|
+
|
|
217
|
+
if (traceIdEnd === -1) {
|
|
218
|
+
if (header === 'd') {
|
|
219
|
+
return {
|
|
220
|
+
sampled: '1',
|
|
221
|
+
flags: '1',
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
sampled: header,
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const spanIdStart = traceIdEnd + 1
|
|
230
|
+
const spanIdEnd = spanIdStart + 16
|
|
231
|
+
const b3 = {
|
|
232
|
+
traceId: header.slice(0, traceIdEnd),
|
|
233
|
+
spanId: header.slice(spanIdStart, spanIdEnd),
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (header.length > spanIdEnd) {
|
|
237
|
+
const sampled = header[spanIdEnd + 1]
|
|
238
|
+
b3.sampled = sampled === '0' ? '0' : '1'
|
|
239
|
+
|
|
240
|
+
if (sampled === 'd') {
|
|
241
|
+
b3.flags = '1'
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return b3
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @param {Record<string, unknown>} carrier
|
|
250
|
+
* @returns {DatadogSpanContext | undefined}
|
|
251
|
+
*/
|
|
252
|
+
function extractB3MultiContext (carrier) {
|
|
253
|
+
const b3 = extractB3MultipleHeaders(carrier)
|
|
254
|
+
if (b3 === undefined) return
|
|
255
|
+
return extractB3Context(b3)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @param {Record<string, unknown>} carrier
|
|
260
|
+
* @returns {DatadogSpanContext | undefined}
|
|
261
|
+
*/
|
|
262
|
+
function extractB3SingleContext (carrier) {
|
|
263
|
+
// Resolve the value before running the regex on the common header-less path.
|
|
264
|
+
const header = readB3(carrier)
|
|
265
|
+
if (!header || !b3HeaderExpr.test(header)) return
|
|
266
|
+
return extractB3Context(extractB3SingleHeader(header))
|
|
267
|
+
}
|
|
268
|
+
|
|
89
269
|
class TextMapPropagator {
|
|
90
|
-
/** @type {Set<string> | undefined} Cached `Set` view of
|
|
270
|
+
/** @type {Set<string> | undefined} Cached `Set` view of `#config.baggageTagKeys`. */
|
|
91
271
|
#baggageTagKeysSet
|
|
92
272
|
|
|
93
273
|
/** @type {string[] | undefined} Source array that `#baggageTagKeysSet` was built from. */
|
|
94
274
|
#baggageTagKeysSetSource
|
|
95
275
|
|
|
96
|
-
/** @type {'
|
|
97
|
-
#
|
|
276
|
+
/** @type {import('../../config')} */
|
|
277
|
+
#config
|
|
98
278
|
|
|
279
|
+
/** @type {typeof extractB3SingleContext | typeof extractB3MultiContext} */
|
|
280
|
+
#extractB3Context
|
|
281
|
+
|
|
282
|
+
/** @param {import('../../config')} config */
|
|
99
283
|
constructor (config) {
|
|
100
|
-
this
|
|
284
|
+
this.#config = config
|
|
101
285
|
|
|
102
|
-
// v6
|
|
286
|
+
// v6+: `'b3'` is always single-header. v5: `OTEL_PROPAGATORS` callers
|
|
103
287
|
// expect single, legacy `DD_TRACE_PROPAGATION_STYLE` callers expect multi.
|
|
104
|
-
/* istanbul ignore else: v5 fallback
|
|
288
|
+
/* istanbul ignore else: v5 fallback */
|
|
105
289
|
if (DD_MAJOR >= 6) {
|
|
106
|
-
this.#
|
|
290
|
+
this.#extractB3Context = extractB3SingleContext
|
|
107
291
|
} else {
|
|
108
292
|
const envName = getConfiguredEnvName('DD_TRACE_PROPAGATION_STYLE')
|
|
109
293
|
// eslint-disable-next-line eslint-rules/eslint-env-aliases
|
|
110
|
-
this.#
|
|
111
|
-
?
|
|
112
|
-
:
|
|
294
|
+
this.#extractB3Context = envName === 'OTEL_PROPAGATORS'
|
|
295
|
+
? extractB3SingleContext
|
|
296
|
+
: extractB3MultiContext
|
|
113
297
|
}
|
|
114
298
|
}
|
|
115
299
|
|
|
116
300
|
/**
|
|
117
|
-
* Returns a `Set` view of
|
|
301
|
+
* Returns a `Set` view of `#config.baggageTagKeys` that is rebuilt only
|
|
118
302
|
* when the source array reference changes. Avoids an `O(n)` `Set` alloc
|
|
119
303
|
* per baggage extract (which is per-request when baggage propagation is
|
|
120
304
|
* enabled).
|
|
@@ -122,7 +306,7 @@ class TextMapPropagator {
|
|
|
122
306
|
* @returns {Set<string>}
|
|
123
307
|
*/
|
|
124
308
|
#getBaggageTagKeysSet () {
|
|
125
|
-
const source = this.
|
|
309
|
+
const source = this.#config.baggageTagKeys
|
|
126
310
|
if (this.#baggageTagKeysSetSource !== source) {
|
|
127
311
|
this.#baggageTagKeysSet = new Set(source)
|
|
128
312
|
this.#baggageTagKeysSetSource = source
|
|
@@ -137,23 +321,36 @@ class TextMapPropagator {
|
|
|
137
321
|
*/
|
|
138
322
|
inject (spanContext, carrier) {
|
|
139
323
|
if (carrier === null) return
|
|
140
|
-
let injectedCarrier = this
|
|
324
|
+
let injectedCarrier = this.#injectBaggageItems(spanContext, carrier)
|
|
141
325
|
if (!spanContext) return injectedCarrier
|
|
142
326
|
|
|
143
|
-
const injectTraceContext = this.
|
|
327
|
+
const injectTraceContext = this.#config.apmTracingEnabled !== false ||
|
|
144
328
|
hasTraceSourcePropagationTag(spanContext._trace.tags)
|
|
329
|
+
let traceTagReplacements
|
|
330
|
+
let optionalTraceTagCount = 0
|
|
331
|
+
if (injectTraceContext && injectCh.hasSubscribers && (
|
|
332
|
+
this.#hasPropagationStyle('inject', 'datadog') || this.#hasPropagationStyle('inject', 'tracecontext')
|
|
333
|
+
)) {
|
|
334
|
+
const injection = { spanContext }
|
|
335
|
+
injectCh.publish(injection)
|
|
336
|
+
traceTagReplacements = injection.traceTagReplacements
|
|
337
|
+
optionalTraceTagCount = injection.optionalTraceTagCount ?? 0
|
|
338
|
+
}
|
|
145
339
|
if (injectTraceContext) {
|
|
146
|
-
injectedCarrier = this
|
|
147
|
-
|
|
148
|
-
|
|
340
|
+
injectedCarrier = this.#injectDatadog(
|
|
341
|
+
spanContext, injectedCarrier ?? carrier, traceTagReplacements, optionalTraceTagCount
|
|
342
|
+
) ?? injectedCarrier
|
|
343
|
+
injectedCarrier = this.#injectB3MultipleHeaders(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
|
|
344
|
+
injectedCarrier = this.#injectB3SingleHeader(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
|
|
149
345
|
}
|
|
150
346
|
injectedCarrier = this
|
|
151
|
-
|
|
347
|
+
.#injectTraceparent(
|
|
348
|
+
spanContext, injectedCarrier ?? carrier, injectTraceContext, traceTagReplacements
|
|
349
|
+
) ?? injectedCarrier
|
|
152
350
|
|
|
153
351
|
if (injectedCarrier === undefined) return
|
|
154
352
|
|
|
155
353
|
carrier = injectedCarrier
|
|
156
|
-
if (injectCh.hasSubscribers) injectCh.publish({ spanContext, carrier })
|
|
157
354
|
|
|
158
355
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
159
356
|
log.debug(() => `Inject into carrier: ${JSON.stringify(pickTextMap(carrier))}.`)
|
|
@@ -161,8 +358,12 @@ class TextMapPropagator {
|
|
|
161
358
|
return carrier
|
|
162
359
|
}
|
|
163
360
|
|
|
361
|
+
/**
|
|
362
|
+
* @param {Record<string, unknown>} carrier
|
|
363
|
+
* @returns {DatadogSpanContext | null}
|
|
364
|
+
*/
|
|
164
365
|
extract (carrier) {
|
|
165
|
-
const spanContext = this
|
|
366
|
+
const spanContext = this.#extractSpanContext(carrier)
|
|
166
367
|
if (spanContext === undefined) return null
|
|
167
368
|
|
|
168
369
|
if (extractCh.hasSubscribers) {
|
|
@@ -172,7 +373,7 @@ class TextMapPropagator {
|
|
|
172
373
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
173
374
|
log.debug(() => {
|
|
174
375
|
const keys = JSON.stringify(pickTextMap(carrier))
|
|
175
|
-
const styles = this.
|
|
376
|
+
const styles = this.#config.tracePropagationStyle.extract.join(', ')
|
|
176
377
|
|
|
177
378
|
return `Extract from carrier (${styles}): ${keys}.`
|
|
178
379
|
})
|
|
@@ -183,36 +384,26 @@ class TextMapPropagator {
|
|
|
183
384
|
/**
|
|
184
385
|
* @param {DatadogSpanContext} spanContext
|
|
185
386
|
* @param {Record<string, string>} [carrier]
|
|
387
|
+
* @param {Array<string | undefined>} [traceTagReplacements]
|
|
388
|
+
* @param {number} optionalTraceTagCount
|
|
186
389
|
* @returns {Record<string, string> | undefined}
|
|
187
390
|
*/
|
|
188
|
-
|
|
189
|
-
if (!this
|
|
391
|
+
#injectDatadog (spanContext, carrier, traceTagReplacements, optionalTraceTagCount) {
|
|
392
|
+
if (!this.#hasPropagationStyle('inject', 'datadog')) return
|
|
190
393
|
|
|
191
394
|
carrier ??= {}
|
|
192
395
|
writeDatadogTraceId(carrier, spanContext.toTraceId())
|
|
193
396
|
writeDatadogParentId(carrier, spanContext.toSpanId())
|
|
194
397
|
|
|
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
398
|
const origin = spanContext._trace.origin
|
|
399
|
+
if (origin) writeDatadogOrigin(carrier, origin)
|
|
204
400
|
|
|
205
|
-
if (origin) {
|
|
206
|
-
writeDatadogOrigin(carrier, origin)
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
_injectSamplingPriority (spanContext, carrier) {
|
|
211
401
|
const priority = spanContext._sampling.priority
|
|
402
|
+
if (Number.isInteger(priority)) writeDatadogSamplingPriority(carrier, priority.toString())
|
|
212
403
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
404
|
+
this.#injectTags(carrier, spanContext._trace.tags, traceTagReplacements, optionalTraceTagCount)
|
|
405
|
+
|
|
406
|
+
return carrier
|
|
216
407
|
}
|
|
217
408
|
|
|
218
409
|
/**
|
|
@@ -220,9 +411,9 @@ class TextMapPropagator {
|
|
|
220
411
|
* @param {Record<string, string>} [carrier]
|
|
221
412
|
* @returns {Record<string, string> | undefined}
|
|
222
413
|
*/
|
|
223
|
-
|
|
414
|
+
#injectBaggageItems (spanContext, carrier) {
|
|
224
415
|
let injectedCarrier
|
|
225
|
-
if (this.
|
|
416
|
+
if (this.#config.legacyBaggageEnabled) {
|
|
226
417
|
const baggageItems = spanContext?._baggageItems
|
|
227
418
|
if (baggageItems) {
|
|
228
419
|
for (const key of Object.keys(baggageItems)) {
|
|
@@ -241,7 +432,7 @@ class TextMapPropagator {
|
|
|
241
432
|
}
|
|
242
433
|
}
|
|
243
434
|
|
|
244
|
-
if (this
|
|
435
|
+
if (this.#hasPropagationStyle('inject', 'baggage')) {
|
|
245
436
|
let baggage = ''
|
|
246
437
|
let itemCounter = 0
|
|
247
438
|
let byteCounter = 0
|
|
@@ -259,13 +450,13 @@ class TextMapPropagator {
|
|
|
259
450
|
byteCounter += item.length
|
|
260
451
|
|
|
261
452
|
// Check for item count limit exceeded
|
|
262
|
-
if (itemCounter > this.
|
|
453
|
+
if (itemCounter > this.#config.baggageMaxItems) {
|
|
263
454
|
tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_item_count_exceeded']).inc()
|
|
264
455
|
break
|
|
265
456
|
}
|
|
266
457
|
|
|
267
458
|
// Check for byte count limit exceeded
|
|
268
|
-
if (byteCounter > this.
|
|
459
|
+
if (byteCounter > this.#config.baggageMaxBytes) {
|
|
269
460
|
tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_byte_count_exceeded']).inc()
|
|
270
461
|
break
|
|
271
462
|
}
|
|
@@ -284,30 +475,55 @@ class TextMapPropagator {
|
|
|
284
475
|
return injectedCarrier
|
|
285
476
|
}
|
|
286
477
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
478
|
+
/**
|
|
479
|
+
* @param {Record<string, string>} carrier
|
|
480
|
+
* @param {Record<string, string>} traceTags
|
|
481
|
+
* @param {Array<string | undefined>} [traceTagReplacements]
|
|
482
|
+
* @param {number} optionalTraceTagCount
|
|
483
|
+
* @returns {void}
|
|
484
|
+
*/
|
|
485
|
+
#injectTags (carrier, traceTags, traceTagReplacements, optionalTraceTagCount) {
|
|
486
|
+
if (this.#config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH === 0) {
|
|
291
487
|
log.debug('Trace tag propagation is disabled, skipping injection.')
|
|
292
488
|
return
|
|
293
489
|
}
|
|
294
490
|
|
|
295
|
-
const
|
|
491
|
+
const maxLength = this.#config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH
|
|
492
|
+
let header = ''
|
|
296
493
|
|
|
297
|
-
for (const key of Object.keys(
|
|
298
|
-
const value =
|
|
299
|
-
if (!value || !key.startsWith('_dd.p.')
|
|
300
|
-
|
|
494
|
+
for (const key of Object.keys(traceTags)) {
|
|
495
|
+
const value = traceTags[key]
|
|
496
|
+
if (!value || !key.startsWith('_dd.p.') ||
|
|
497
|
+
traceTagReplacements && hasTraceTagReplacement(traceTagReplacements, key)) {
|
|
498
|
+
continue
|
|
499
|
+
}
|
|
500
|
+
if (!tagKeyExpr.test(key) || !tagValueExpr.test(value)) {
|
|
301
501
|
log.error('Trace tags from span are invalid, skipping injection.')
|
|
302
502
|
return
|
|
303
503
|
}
|
|
304
504
|
|
|
305
|
-
|
|
505
|
+
if (header) header += ','
|
|
506
|
+
header += `${key}=${value}`
|
|
306
507
|
}
|
|
307
508
|
|
|
308
|
-
|
|
509
|
+
if (traceTagReplacements) {
|
|
510
|
+
const requiredEntryCount = traceTagReplacements.length - optionalTraceTagCount * 2
|
|
511
|
+
for (let index = 0; index < traceTagReplacements.length; index += 2) {
|
|
512
|
+
const key = traceTagReplacements[index]
|
|
513
|
+
const value = traceTagReplacements[index + 1]
|
|
514
|
+
if (!value || !key.startsWith('_dd.p.')) continue
|
|
515
|
+
if (!tagKeyExpr.test(key) || !tagValueExpr.test(value)) {
|
|
516
|
+
log.error('Trace tags from span are invalid, skipping injection.')
|
|
517
|
+
return
|
|
518
|
+
}
|
|
309
519
|
|
|
310
|
-
|
|
520
|
+
const entry = `${header ? ',' : ''}${key}=${value}`
|
|
521
|
+
if (index >= requiredEntryCount && header.length + entry.length > maxLength) break
|
|
522
|
+
header += entry
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (header.length > maxLength) {
|
|
311
527
|
log.error('Trace tags from span are too large, skipping injection.')
|
|
312
528
|
} else if (header) {
|
|
313
529
|
writeDatadogTags(carrier, header)
|
|
@@ -319,10 +535,10 @@ class TextMapPropagator {
|
|
|
319
535
|
* @param {Record<string, string>} [carrier]
|
|
320
536
|
* @returns {Record<string, string> | undefined}
|
|
321
537
|
*/
|
|
322
|
-
|
|
323
|
-
// v5 also accepts the legacy `'b3'` spelling for multi; v6 routes `'b3'` to single-header.
|
|
324
|
-
const hasB3multi = this
|
|
325
|
-
(DD_MAJOR < 6 && this
|
|
538
|
+
#injectB3MultipleHeaders (spanContext, carrier) {
|
|
539
|
+
// v5 also accepts the legacy `'b3'` spelling for multi; v6+ routes `'b3'` to single-header.
|
|
540
|
+
const hasB3multi = this.#hasPropagationStyle('inject', 'b3multi') ||
|
|
541
|
+
(DD_MAJOR < 6 && this.#hasPropagationStyle('inject', 'b3'))
|
|
326
542
|
if (!hasB3multi) return
|
|
327
543
|
|
|
328
544
|
carrier ??= {}
|
|
@@ -346,10 +562,10 @@ class TextMapPropagator {
|
|
|
346
562
|
* @param {Record<string, string>} [carrier]
|
|
347
563
|
* @returns {Record<string, string> | undefined}
|
|
348
564
|
*/
|
|
349
|
-
|
|
350
|
-
// v6 keeps `'b3 single header'` as a back-compat alias for callers that bypass parser normalisation.
|
|
351
|
-
const hasB3SingleHeader = this
|
|
352
|
-
(DD_MAJOR >= 6 && this
|
|
565
|
+
#injectB3SingleHeader (spanContext, carrier) {
|
|
566
|
+
// v6+ keeps `'b3 single header'` as a back-compat alias for callers that bypass parser normalisation.
|
|
567
|
+
const hasB3SingleHeader = this.#hasPropagationStyle('inject', 'b3 single header') ||
|
|
568
|
+
(DD_MAJOR >= 6 && this.#hasPropagationStyle('inject', 'b3'))
|
|
353
569
|
if (!hasB3SingleHeader) return
|
|
354
570
|
|
|
355
571
|
carrier ??= {}
|
|
@@ -370,10 +586,11 @@ class TextMapPropagator {
|
|
|
370
586
|
* @param {DatadogSpanContext} spanContext
|
|
371
587
|
* @param {Record<string, string> | undefined} carrier
|
|
372
588
|
* @param {boolean} injectTraceContext
|
|
589
|
+
* @param {Array<string | undefined>} [traceTagReplacements]
|
|
373
590
|
* @returns {Record<string, string> | undefined}
|
|
374
591
|
*/
|
|
375
|
-
|
|
376
|
-
if (!this
|
|
592
|
+
#injectTraceparent (spanContext, carrier, injectTraceContext, traceTagReplacements) {
|
|
593
|
+
if (!this.#hasPropagationStyle('inject', 'tracecontext')) return
|
|
377
594
|
|
|
378
595
|
if (!injectTraceContext) {
|
|
379
596
|
const tracestate = TraceState.fromString(spanContext._tracestate?.toString())
|
|
@@ -388,9 +605,12 @@ class TextMapPropagator {
|
|
|
388
605
|
carrier ??= {}
|
|
389
606
|
const {
|
|
390
607
|
_sampling: { priority, mechanism },
|
|
391
|
-
_tracestate
|
|
392
|
-
_trace: { origin
|
|
608
|
+
_tracestate,
|
|
609
|
+
_trace: { origin },
|
|
393
610
|
} = spanContext
|
|
611
|
+
const ts = traceTagReplacements
|
|
612
|
+
? TraceState.fromString(_tracestate?.toString())
|
|
613
|
+
: _tracestate ?? new TraceState()
|
|
394
614
|
|
|
395
615
|
writeTraceparent(carrier, spanContext.toTraceparent())
|
|
396
616
|
|
|
@@ -416,8 +636,9 @@ class TextMapPropagator {
|
|
|
416
636
|
state.set('o', originValue)
|
|
417
637
|
}
|
|
418
638
|
|
|
419
|
-
for (const key of Object.keys(
|
|
420
|
-
|
|
639
|
+
for (const key of Object.keys(spanContext._trace.tags)) {
|
|
640
|
+
if (traceTagReplacements && hasTraceTagReplacement(traceTagReplacements, key)) continue
|
|
641
|
+
const tagValueRaw = spanContext._trace.tags[key]
|
|
421
642
|
if (!tagValueRaw || !key.startsWith('_dd.p.')) continue
|
|
422
643
|
|
|
423
644
|
const tagKey = 't.' + key.slice(6)
|
|
@@ -430,60 +651,122 @@ class TextMapPropagator {
|
|
|
430
651
|
|
|
431
652
|
state.set(tagKey, tagValue)
|
|
432
653
|
}
|
|
433
|
-
})
|
|
434
654
|
|
|
435
|
-
|
|
655
|
+
if (traceTagReplacements) {
|
|
656
|
+
for (let index = 0; index < traceTagReplacements.length; index += 2) {
|
|
657
|
+
const key = traceTagReplacements[index]
|
|
658
|
+
if (!key.startsWith('_dd.p.')) continue
|
|
436
659
|
|
|
437
|
-
|
|
438
|
-
|
|
660
|
+
const tagKey = 't.' + key.slice(6)
|
|
661
|
+
.replaceAll(tracestateTagKeyFilter, '_')
|
|
662
|
+
const tagValueRaw = traceTagReplacements[index + 1]
|
|
663
|
+
if (!tagValueRaw) {
|
|
664
|
+
state.delete(tagKey)
|
|
665
|
+
continue
|
|
666
|
+
}
|
|
439
667
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
668
|
+
const tagValue = tagValueRaw
|
|
669
|
+
.toString()
|
|
670
|
+
.replaceAll(tracestateTagValueFilter, '_')
|
|
671
|
+
.replaceAll('=', '~')
|
|
443
672
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
673
|
+
state.set(tagKey, tagValue)
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
writeTracestate(carrier, ts.toString())
|
|
449
679
|
|
|
450
|
-
|
|
451
|
-
return tags.DD_PARENT_ID in spanContext._trace.tags
|
|
680
|
+
return carrier
|
|
452
681
|
}
|
|
453
682
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
683
|
+
/**
|
|
684
|
+
* @param {'inject' | 'extract'} mode
|
|
685
|
+
* @param {string} name
|
|
686
|
+
* @returns {boolean}
|
|
687
|
+
*/
|
|
688
|
+
#hasPropagationStyle (mode, name) {
|
|
689
|
+
return this.#config.tracePropagationStyle[mode].includes(name)
|
|
459
690
|
}
|
|
460
691
|
|
|
461
|
-
|
|
462
|
-
|
|
692
|
+
/**
|
|
693
|
+
* @param {DatadogSpanContext | undefined} w3cSpanContext
|
|
694
|
+
* @param {DatadogSpanContext} firstSpanContext
|
|
695
|
+
* @param {Record<string, unknown>} carrier
|
|
696
|
+
* @param {DatadogSpanContext | undefined} datadogContext
|
|
697
|
+
* @returns {DatadogSpanContext}
|
|
698
|
+
*/
|
|
699
|
+
#resolveTraceContextConflicts (w3cSpanContext, firstSpanContext, carrier, datadogContext) {
|
|
700
|
+
if (w3cSpanContext === undefined ||
|
|
701
|
+
firstSpanContext.toTraceId(true) !== w3cSpanContext.toTraceId(true) ||
|
|
702
|
+
firstSpanContext.toSpanId() === w3cSpanContext.toSpanId()) {
|
|
463
703
|
return firstSpanContext
|
|
464
704
|
}
|
|
465
|
-
if (
|
|
705
|
+
if (tags.DD_PARENT_ID in w3cSpanContext._trace.tags) {
|
|
466
706
|
// tracecontext headers contain a p value, ensure this value is sent to backend
|
|
467
707
|
firstSpanContext._trace.tags[tags.DD_PARENT_ID] = w3cSpanContext._trace.tags[tags.DD_PARENT_ID]
|
|
468
708
|
} else {
|
|
469
709
|
// if p value is not present in tracestate, use the parent id from the datadog headers
|
|
470
|
-
|
|
710
|
+
datadogContext ||= extractGenericContext(readDatadogTraceId(carrier), readDatadogParentId(carrier), 10)
|
|
711
|
+
if (datadogContext) {
|
|
712
|
+
firstSpanContext._trace.tags[tags.DD_PARENT_ID] = datadogContext._spanId.toString().padStart(16, '0')
|
|
713
|
+
}
|
|
471
714
|
}
|
|
472
715
|
// the span_id in tracecontext takes precedence over the first extracted propagation style
|
|
473
716
|
firstSpanContext._spanId = w3cSpanContext._spanId
|
|
474
717
|
return firstSpanContext
|
|
475
718
|
}
|
|
476
719
|
|
|
477
|
-
|
|
720
|
+
/**
|
|
721
|
+
* @param {Record<string, unknown>} carrier
|
|
722
|
+
* @returns {DatadogSpanContext | undefined}
|
|
723
|
+
*/
|
|
724
|
+
#extractSpanContext (carrier) {
|
|
478
725
|
let context
|
|
726
|
+
let datadogContext
|
|
479
727
|
let style = ''
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
728
|
+
let extractBaggage = false
|
|
729
|
+
let traceContext
|
|
730
|
+
let traceContextExtracted = false
|
|
731
|
+
for (const extractor of this.#config.tracePropagationStyle.extract) {
|
|
732
|
+
let extractedContext
|
|
733
|
+
switch (extractor) {
|
|
734
|
+
case 'datadog':
|
|
735
|
+
datadogContext = this.#extractDatadogContext(carrier)
|
|
736
|
+
extractedContext = datadogContext
|
|
737
|
+
if (extractedContext !== undefined && !this.#config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) {
|
|
738
|
+
if (!traceContextExtracted) {
|
|
739
|
+
traceContext = this.#extractTraceparentContext(carrier)
|
|
740
|
+
traceContextExtracted = true
|
|
741
|
+
}
|
|
742
|
+
this.#addTraceContextState(extractedContext, traceContext)
|
|
743
|
+
}
|
|
744
|
+
break
|
|
745
|
+
case 'tracecontext':
|
|
746
|
+
if (!traceContextExtracted) {
|
|
747
|
+
traceContext = this.#extractTraceparentContext(carrier)
|
|
748
|
+
traceContextExtracted = true
|
|
749
|
+
}
|
|
750
|
+
extractedContext = traceContext
|
|
751
|
+
break
|
|
752
|
+
case 'b3':
|
|
753
|
+
extractedContext = this.#extractB3Context(carrier)
|
|
754
|
+
break
|
|
755
|
+
case 'b3 single header':
|
|
756
|
+
extractedContext = extractB3SingleContext(carrier)
|
|
757
|
+
break
|
|
758
|
+
case 'b3multi':
|
|
759
|
+
extractedContext = extractB3MultiContext(carrier)
|
|
760
|
+
break
|
|
761
|
+
case 'baggage':
|
|
762
|
+
extractBaggage = true
|
|
763
|
+
continue
|
|
764
|
+
case 'none':
|
|
765
|
+
continue
|
|
766
|
+
default:
|
|
767
|
+
log.warn('Unknown propagation style:', extractor)
|
|
768
|
+
continue
|
|
485
769
|
}
|
|
486
|
-
const extractedContext = this[method](carrier)
|
|
487
770
|
if (extractedContext === undefined) {
|
|
488
771
|
continue
|
|
489
772
|
}
|
|
@@ -491,14 +774,14 @@ class TextMapPropagator {
|
|
|
491
774
|
if (context === undefined) {
|
|
492
775
|
context = extractedContext
|
|
493
776
|
style = extractor
|
|
494
|
-
if (this.
|
|
777
|
+
if (this.#config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) {
|
|
495
778
|
break
|
|
496
779
|
}
|
|
497
780
|
} else {
|
|
498
781
|
// If extractor is tracecontext, add tracecontext specific information to the context
|
|
499
782
|
if (extractor === 'tracecontext') {
|
|
500
|
-
context = this
|
|
501
|
-
|
|
783
|
+
context = this.#resolveTraceContextConflicts(
|
|
784
|
+
extractedContext, context, carrier, datadogContext)
|
|
502
785
|
}
|
|
503
786
|
if (extractedContext._traceId && extractedContext._spanId &&
|
|
504
787
|
extractedContext.toTraceId(true) !== context.toTraceId(true)) {
|
|
@@ -511,10 +794,14 @@ class TextMapPropagator {
|
|
|
511
794
|
}
|
|
512
795
|
}
|
|
513
796
|
|
|
514
|
-
if (
|
|
797
|
+
if (context && (style === 'datadog' || style === 'tracecontext')) {
|
|
798
|
+
this.#extractLegacyBaggageItems(carrier, context)
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (this.#config.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT === 'ignore') {
|
|
515
802
|
if (context !== undefined) context._links = []
|
|
516
803
|
} else {
|
|
517
|
-
if (this.
|
|
804
|
+
if (this.#config.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT === 'restart' && context) {
|
|
518
805
|
context._links = []
|
|
519
806
|
context._links.push({
|
|
520
807
|
context,
|
|
@@ -524,78 +811,47 @@ class TextMapPropagator {
|
|
|
524
811
|
},
|
|
525
812
|
})
|
|
526
813
|
}
|
|
527
|
-
this.
|
|
814
|
+
if (!extractBaggage && this.#config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) {
|
|
815
|
+
extractBaggage = this.#hasPropagationStyle('extract', 'baggage')
|
|
816
|
+
}
|
|
817
|
+
this.#extractBaggageItems(carrier, context, extractBaggage)
|
|
528
818
|
}
|
|
529
819
|
|
|
530
|
-
return context || this
|
|
820
|
+
return context || this.#extractSqsdContext(carrier)
|
|
531
821
|
}
|
|
532
822
|
|
|
533
|
-
|
|
823
|
+
/**
|
|
824
|
+
* @param {Record<string, unknown>} carrier
|
|
825
|
+
* @returns {DatadogSpanContext | undefined}
|
|
826
|
+
*/
|
|
827
|
+
#extractDatadogContext (carrier) {
|
|
534
828
|
if (!carrier) return
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
10
|
|
539
|
-
)
|
|
829
|
+
const traceId = readDatadogTraceId(carrier)
|
|
830
|
+
if (!traceId) return
|
|
831
|
+
const spanContext = extractGenericContext(traceId, readDatadogParentId(carrier), 10)
|
|
540
832
|
|
|
541
833
|
if (!spanContext) return spanContext
|
|
542
834
|
|
|
543
|
-
|
|
544
|
-
|
|
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
|
-
}
|
|
835
|
+
const origin = readDatadogOrigin(carrier)
|
|
836
|
+
if (typeof origin === 'string') spanContext._trace.origin = origin
|
|
589
837
|
|
|
590
|
-
|
|
838
|
+
const header = readDatadogSamplingPriority(carrier)
|
|
839
|
+
if (header !== undefined) {
|
|
840
|
+
const priority = Number.parseInt(header, 10)
|
|
841
|
+
if (Number.isInteger(priority)) spanContext._sampling.priority = priority
|
|
591
842
|
}
|
|
592
843
|
|
|
593
|
-
this
|
|
844
|
+
const traceTags = this.#extractTags(carrier)
|
|
845
|
+
if (traceTags) spanContext._trace.tags = traceTags
|
|
594
846
|
|
|
595
847
|
return spanContext
|
|
596
848
|
}
|
|
597
849
|
|
|
598
|
-
|
|
850
|
+
/**
|
|
851
|
+
* @param {Record<string, unknown>} carrier
|
|
852
|
+
* @returns {DatadogSpanContext | undefined}
|
|
853
|
+
*/
|
|
854
|
+
#extractSqsdContext (carrier) {
|
|
599
855
|
const headerValue = readSqsd(carrier)
|
|
600
856
|
if (!headerValue) return
|
|
601
857
|
let parsed
|
|
@@ -604,10 +860,32 @@ class TextMapPropagator {
|
|
|
604
860
|
} catch {
|
|
605
861
|
return
|
|
606
862
|
}
|
|
607
|
-
|
|
863
|
+
const spanContext = this.#extractDatadogContext(parsed)
|
|
864
|
+
if (!spanContext) return
|
|
865
|
+
|
|
866
|
+
this.#extractLegacyBaggageItems(parsed, spanContext)
|
|
867
|
+
if (this.#config.DD_TRACE_PROPAGATION_EXTRACT_FIRST) return spanContext
|
|
868
|
+
|
|
869
|
+
this.#addTraceContextState(spanContext, this.#extractTraceparentContext(parsed))
|
|
870
|
+
return spanContext
|
|
608
871
|
}
|
|
609
872
|
|
|
610
|
-
|
|
873
|
+
/**
|
|
874
|
+
* @param {DatadogSpanContext} datadogContext
|
|
875
|
+
* @param {DatadogSpanContext | undefined} traceContext
|
|
876
|
+
*/
|
|
877
|
+
#addTraceContextState (datadogContext, traceContext) {
|
|
878
|
+
if (traceContext && datadogContext._traceId.equals(traceContext._traceId)) {
|
|
879
|
+
datadogContext._traceparent = traceContext._traceparent
|
|
880
|
+
datadogContext._tracestate = traceContext._tracestate
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* @param {Record<string, unknown>} carrier
|
|
886
|
+
* @returns {DatadogSpanContext | undefined}
|
|
887
|
+
*/
|
|
888
|
+
#extractTraceparentContext (carrier) {
|
|
611
889
|
const headerValue = readTraceparent(carrier)
|
|
612
890
|
if (!headerValue) return
|
|
613
891
|
const matches = headerValue.trim().match(traceparentExpr)
|
|
@@ -634,7 +912,7 @@ class TextMapPropagator {
|
|
|
634
912
|
tracestate,
|
|
635
913
|
})
|
|
636
914
|
|
|
637
|
-
|
|
915
|
+
extract128BitTraceId(traceId, spanContext)
|
|
638
916
|
|
|
639
917
|
tracestate.forVendor('dd', state => {
|
|
640
918
|
for (const [key, value] of state.entries()) {
|
|
@@ -683,147 +961,78 @@ class TextMapPropagator {
|
|
|
683
961
|
}
|
|
684
962
|
})
|
|
685
963
|
|
|
686
|
-
this._extractLegacyBaggageItems(carrier, spanContext)
|
|
687
964
|
return spanContext
|
|
688
965
|
}
|
|
689
966
|
}
|
|
690
967
|
|
|
691
968
|
/**
|
|
692
|
-
* @param {string
|
|
693
|
-
* @param {
|
|
694
|
-
* @
|
|
695
|
-
* @returns {DatadogSpanContext | undefined}
|
|
969
|
+
* @param {Record<string, unknown>} carrier
|
|
970
|
+
* @param {DatadogSpanContext} spanContext
|
|
971
|
+
* @returns {void}
|
|
696
972
|
*/
|
|
697
|
-
|
|
698
|
-
if (!
|
|
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
|
|
973
|
+
#extractLegacyBaggageItems (carrier, spanContext) {
|
|
974
|
+
if (!this.#config.legacyBaggageEnabled) return
|
|
782
975
|
readLegacyBaggage(carrier, spanContext._baggageItems)
|
|
783
976
|
}
|
|
784
977
|
|
|
785
|
-
|
|
978
|
+
/**
|
|
979
|
+
* @param {Record<string, unknown> | undefined} carrier
|
|
980
|
+
* @param {DatadogSpanContext | undefined} spanContext
|
|
981
|
+
* @param {boolean} extractBaggage
|
|
982
|
+
* @returns {void}
|
|
983
|
+
*/
|
|
984
|
+
#extractBaggageItems (carrier, spanContext, extractBaggage) {
|
|
786
985
|
removeAllBaggageItems()
|
|
787
|
-
if (!carrier || !
|
|
986
|
+
if (!carrier || !extractBaggage) return
|
|
788
987
|
const header = readBaggage(carrier)
|
|
789
988
|
if (!header) return
|
|
790
989
|
|
|
791
|
-
const baggages = header.split(',')
|
|
792
990
|
const baggageTagKeys = this.#getBaggageTagKeysSet()
|
|
793
991
|
const tagAllKeys = baggageTagKeys.has('*')
|
|
794
992
|
/** @type {Record<string, string> | undefined} */
|
|
795
993
|
let items
|
|
796
994
|
let itemCount = 0
|
|
797
995
|
let byteCount = 0
|
|
996
|
+
let start = 0
|
|
798
997
|
|
|
799
|
-
|
|
800
|
-
if (itemCount >= this.
|
|
998
|
+
while (start <= header.length) {
|
|
999
|
+
if (itemCount >= this.#config.baggageMaxItems) {
|
|
801
1000
|
tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_item_count_exceeded']).inc()
|
|
802
1001
|
break
|
|
803
1002
|
}
|
|
1003
|
+
|
|
1004
|
+
const memberStart = start
|
|
1005
|
+
const commaIndex = header.indexOf(',', memberStart)
|
|
1006
|
+
const end = commaIndex === -1 ? header.length : commaIndex
|
|
1007
|
+
|
|
804
1008
|
// Charge the comma slot before the empty-entry skip so a `,,,,,foo=bar` can't iterate for free.
|
|
805
|
-
byteCount +=
|
|
806
|
-
if (byteCount > this.
|
|
1009
|
+
byteCount += end - memberStart + 1
|
|
1010
|
+
if (byteCount > this.#config.baggageMaxBytes) {
|
|
807
1011
|
tracerMetrics.count('context_header.truncated', ['truncation_reason:baggage_byte_count_exceeded']).inc()
|
|
808
1012
|
break
|
|
809
1013
|
}
|
|
810
|
-
if (
|
|
1014
|
+
if (memberStart === end) {
|
|
1015
|
+
start = end + 1
|
|
1016
|
+
continue
|
|
1017
|
+
}
|
|
811
1018
|
|
|
812
1019
|
// Per W3C baggage, list-members can contain optional properties after `;`.
|
|
813
1020
|
// Example: key=value;prop=1;prop2
|
|
814
1021
|
// https://www.w3.org/TR/baggage/#header-content
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
if (
|
|
1022
|
+
let memberEnd = header.indexOf(';', memberStart)
|
|
1023
|
+
if (memberEnd === -1 || memberEnd > end) memberEnd = end
|
|
1024
|
+
const equalsIndex = header.indexOf('=', memberStart)
|
|
1025
|
+
start = end + 1
|
|
1026
|
+
|
|
1027
|
+
if (equalsIndex === -1 || equalsIndex >= memberEnd) {
|
|
1028
|
+
const member = header.slice(memberStart, memberEnd).trim()
|
|
1029
|
+
if (!member) continue
|
|
821
1030
|
tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
|
|
822
1031
|
return
|
|
823
1032
|
}
|
|
824
1033
|
|
|
825
|
-
const key =
|
|
826
|
-
let value =
|
|
1034
|
+
const key = header.slice(memberStart, equalsIndex).trim()
|
|
1035
|
+
let value = header.slice(equalsIndex + 1, memberEnd).trim()
|
|
827
1036
|
|
|
828
1037
|
if (!baggageTokenExpr.test(key) || !value) {
|
|
829
1038
|
tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
|
|
@@ -856,27 +1065,17 @@ class TextMapPropagator {
|
|
|
856
1065
|
}
|
|
857
1066
|
}
|
|
858
1067
|
|
|
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
1068
|
/**
|
|
870
1069
|
* @param {Record<string, unknown>} carrier
|
|
871
1070
|
* @returns {Record<string, string> | undefined}
|
|
872
1071
|
*/
|
|
873
|
-
|
|
1072
|
+
#extractTags (carrier) {
|
|
874
1073
|
const header = readDatadogTags(carrier)
|
|
875
1074
|
if (!header) return
|
|
876
1075
|
|
|
877
|
-
if (this.
|
|
1076
|
+
if (this.#config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH === 0) {
|
|
878
1077
|
log.debug('Trace tag propagation is disabled, skipping extraction.')
|
|
879
|
-
} else if (header.length > this.
|
|
1078
|
+
} else if (header.length > this.#config.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH) {
|
|
880
1079
|
log.error('Trace tags from carrier are too large, skipping extraction.')
|
|
881
1080
|
} else {
|
|
882
1081
|
const tags = {}
|
|
@@ -890,7 +1089,7 @@ class TextMapPropagator {
|
|
|
890
1089
|
const key = header.slice(start, hasSeparator ? separator : end)
|
|
891
1090
|
const value = hasSeparator ? header.slice(separator + 1, end) : ''
|
|
892
1091
|
|
|
893
|
-
if (!
|
|
1092
|
+
if (!tagKeyExpr.test(key) || !tagValueExpr.test(value)) {
|
|
894
1093
|
log.error('Trace tags from carrier are invalid, skipping extraction.')
|
|
895
1094
|
return
|
|
896
1095
|
}
|
|
@@ -907,62 +1106,6 @@ class TextMapPropagator {
|
|
|
907
1106
|
return tags
|
|
908
1107
|
}
|
|
909
1108
|
}
|
|
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
1109
|
}
|
|
967
1110
|
|
|
968
1111
|
module.exports = TextMapPropagator
|