dd-trace 5.114.0 → 5.116.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/README.electron.md +7 -0
- package/README.md +17 -0
- package/ci/diagnose.js +2100 -0
- package/ci/init.js +23 -2
- package/ci/runbook.md +198 -0
- package/ci/test-optimization-validation/approval-artifacts.js +143 -0
- package/ci/test-optimization-validation/approval.js +299 -0
- package/ci/test-optimization-validation/artifact-id.js +20 -0
- package/ci/test-optimization-validation/bounded-json.js +121 -0
- package/ci/test-optimization-validation/ci-command-candidate.js +83 -0
- package/ci/test-optimization-validation/ci-discovery.js +181 -0
- package/ci/test-optimization-validation/ci-remediation.js +210 -0
- package/ci/test-optimization-validation/cli.js +903 -0
- package/ci/test-optimization-validation/command-blocker.js +81 -0
- package/ci/test-optimization-validation/command-output-policy.js +206 -0
- package/ci/test-optimization-validation/command-runner.js +707 -0
- package/ci/test-optimization-validation/command-suitability.js +471 -0
- package/ci/test-optimization-validation/executable-approval.js +48 -0
- package/ci/test-optimization-validation/executable.js +480 -0
- package/ci/test-optimization-validation/generated-file-policy.js +63 -0
- package/ci/test-optimization-validation/generated-files.js +351 -0
- package/ci/test-optimization-validation/generated-verifier.js +196 -0
- package/ci/test-optimization-validation/init-probe-preload.js +163 -0
- package/ci/test-optimization-validation/init-probe.js +246 -0
- package/ci/test-optimization-validation/late-initialization.js +63 -0
- package/ci/test-optimization-validation/local-command.js +163 -0
- package/ci/test-optimization-validation/manifest-loader.js +133 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +738 -0
- package/ci/test-optimization-validation/manifest-schema.js +862 -0
- package/ci/test-optimization-validation/offline-fixtures.js +327 -0
- package/ci/test-optimization-validation/offline-output.js +406 -0
- package/ci/test-optimization-validation/payload-normalizer.js +72 -0
- package/ci/test-optimization-validation/plan-writer.js +1120 -0
- package/ci/test-optimization-validation/preflight-runner.js +114 -0
- package/ci/test-optimization-validation/redaction.js +331 -0
- package/ci/test-optimization-validation/report-writer.js +1508 -0
- package/ci/test-optimization-validation/safe-files.js +203 -0
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +159 -0
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +657 -0
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +780 -0
- package/ci/test-optimization-validation/scenarios/early-flake-detection.js +141 -0
- package/ci/test-optimization-validation/scenarios/helpers.js +539 -0
- package/ci/test-optimization-validation/scenarios/test-management.js +218 -0
- package/ci/test-optimization-validation/setup-runner.js +97 -0
- package/ci/test-optimization-validation/static-diagnosis.js +159 -0
- package/ci/test-optimization-validation/test-output.js +129 -0
- package/ci/test-optimization-validation-manifest.schema.json +1 -0
- package/ci/validate-test-optimization.js +3 -0
- package/ext/exporters.js +1 -0
- package/index.d.ts +121 -8
- package/index.electron.js +3 -0
- package/init.js +18 -0
- package/initialize.mjs +1 -1
- package/loader-hook.mjs +28 -18
- package/openfeature.d.ts +1 -0
- package/openfeature.js +4 -0
- package/package.json +15 -8
- package/packages/datadog-instrumentations/src/ai.js +37 -26
- package/packages/datadog-instrumentations/src/child_process.js +1 -1
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +9 -3
- package/packages/datadog-instrumentations/src/cucumber.js +24 -10
- package/packages/datadog-instrumentations/src/cypress-config.js +398 -52
- package/packages/datadog-instrumentations/src/express.js +20 -2
- package/packages/datadog-instrumentations/src/fastify.js +7 -11
- package/packages/datadog-instrumentations/src/grpc/server.js +18 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +27 -6
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +8 -8
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +28 -2
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +8 -8
- package/packages/datadog-instrumentations/src/http2/server.js +143 -17
- package/packages/datadog-instrumentations/src/jest.js +36 -4
- package/packages/datadog-instrumentations/src/mariadb.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +0 -2
- package/packages/datadog-instrumentations/src/mocha/utils.js +0 -4
- package/packages/datadog-instrumentations/src/mongodb.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/mquery.js +2 -2
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +24 -0
- package/packages/datadog-instrumentations/src/nyc.js +0 -2
- package/packages/datadog-instrumentations/src/oracledb.js +2 -2
- package/packages/datadog-instrumentations/src/pg.js +2 -2
- package/packages/datadog-instrumentations/src/playwright.js +159 -22
- package/packages/datadog-instrumentations/src/process.js +3 -0
- package/packages/datadog-instrumentations/src/router.js +191 -106
- package/packages/datadog-instrumentations/src/selenium.js +52 -26
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +2 -2
- package/packages/datadog-instrumentations/src/vitest-main.js +0 -2
- package/packages/datadog-instrumentations/src/ws.js +2 -1
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +41 -16
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +21 -21
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +14 -8
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -24
- package/packages/datadog-plugin-cucumber/src/index.js +1 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +24 -62
- package/packages/datadog-plugin-cypress/src/index.js +6 -1
- package/packages/datadog-plugin-cypress/src/support.js +92 -26
- package/packages/datadog-plugin-electron/src/ipc.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +177 -59
- package/packages/datadog-plugin-graphql/src/parse.js +22 -1
- package/packages/datadog-plugin-graphql/src/request.js +32 -1
- package/packages/datadog-plugin-graphql/src/utils.js +42 -0
- package/packages/datadog-plugin-graphql/src/validate.js +15 -3
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +38 -6
- package/packages/datadog-plugin-jest/src/util.js +21 -6
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +2 -1
- package/packages/datadog-plugin-langchain/src/handlers/language_models.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +177 -64
- package/packages/datadog-plugin-router/src/index.js +11 -2
- package/packages/datadog-plugin-selenium/src/index.js +5 -36
- package/packages/datadog-plugin-vitest/src/index.js +4 -2
- package/packages/datadog-plugin-ws/src/close.js +2 -1
- package/packages/datadog-plugin-ws/src/producer.js +2 -1
- package/packages/datadog-plugin-ws/src/receiver.js +2 -1
- package/packages/datadog-plugin-ws/src/server.js +2 -1
- package/packages/dd-trace/index.electron.js +3 -0
- package/packages/dd-trace/index.js +2 -37
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +3 -1
- package/packages/dd-trace/src/azure_metadata.js +2 -1
- package/packages/dd-trace/src/bootstrap.js +39 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +93 -28
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +160 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +288 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/payload-projection.js +84 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +369 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +60 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +55 -5
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +5 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +62 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -2
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +6 -2
- package/packages/dd-trace/src/ci-visibility/rum.js +7 -0
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +137 -9
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +173 -9
- package/packages/dd-trace/src/ci-visibility/test-screenshot.js +90 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +20 -0
- package/packages/dd-trace/src/config/helper.js +1 -0
- package/packages/dd-trace/src/config/index.js +10 -0
- package/packages/dd-trace/src/config/supported-configurations.json +83 -0
- package/packages/dd-trace/src/constants.js +7 -0
- package/packages/dd-trace/src/datastreams/pathway.js +6 -4
- package/packages/dd-trace/src/exporter.js +2 -0
- package/packages/dd-trace/src/exporters/common/client-library-headers.js +21 -0
- package/packages/dd-trace/src/exporters/common/request.js +59 -30
- package/packages/dd-trace/src/exporters/common/url.js +15 -1
- package/packages/dd-trace/src/feature-registry.js +29 -0
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/client.js +113 -0
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +154 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +283 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +152 -0
- package/packages/dd-trace/src/llmobs/experiments/noop.js +30 -0
- package/packages/dd-trace/src/llmobs/experiments/result.js +34 -0
- package/packages/dd-trace/src/llmobs/index.js +10 -2
- package/packages/dd-trace/src/llmobs/noop.js +6 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +20 -3
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +8 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +48 -14
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +43 -0
- package/packages/dd-trace/src/llmobs/sdk.js +17 -0
- package/packages/dd-trace/src/llmobs/tagger.js +79 -7
- package/packages/dd-trace/src/llmobs/telemetry.js +2 -1
- package/packages/dd-trace/src/llmobs/util.js +32 -0
- package/packages/dd-trace/src/noop/proxy.js +5 -4
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +322 -0
- package/packages/dd-trace/src/openfeature/configuration_source.js +90 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +14 -23
- package/packages/dd-trace/src/openfeature/index.js +0 -2
- package/packages/dd-trace/src/openfeature/noop.js +1 -28
- package/packages/dd-trace/src/openfeature/register.js +35 -0
- package/packages/dd-trace/src/openfeature/remote_config.js +15 -18
- package/packages/dd-trace/src/openfeature/require-provider.js +18 -0
- package/packages/dd-trace/src/opentelemetry/span-ending-hook.js +10 -0
- package/packages/dd-trace/src/opentelemetry/span.js +5 -0
- package/packages/dd-trace/src/opentracing/propagation/log.js +11 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +80 -14
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +10 -1
- package/packages/dd-trace/src/opentracing/tracer.js +7 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -6
- package/packages/dd-trace/src/plugins/util/git.js +3 -2
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +29 -5
- package/packages/dd-trace/src/plugins/util/test.js +65 -8
- package/packages/dd-trace/src/plugins/util/web.js +12 -0
- package/packages/dd-trace/src/proxy.js +99 -10
- package/packages/dd-trace/src/span_processor.js +5 -0
- package/packages/dd-trace/src/standalone/index.js +0 -36
- package/packages/dd-trace/src/telemetry/send-data.js +2 -2
- package/packages/dd-trace/src/util.js +26 -0
- package/vendor/dist/@apm-js-collab/code-transformer/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/vendor/dist/shell-quote/index.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +0 -17
|
@@ -8,8 +8,13 @@ class LogPropagator {
|
|
|
8
8
|
this._config = config
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @param {DatadogSpanContext | null | undefined} spanContext
|
|
13
|
+
* @param {Record<string, unknown>} [carrier]
|
|
14
|
+
* @returns {Record<string, unknown> | undefined}
|
|
15
|
+
*/
|
|
11
16
|
inject (spanContext, carrier) {
|
|
12
|
-
if (
|
|
17
|
+
if (carrier === null) return
|
|
13
18
|
|
|
14
19
|
const dd = {}
|
|
15
20
|
let hasField = false
|
|
@@ -35,7 +40,11 @@ class LogPropagator {
|
|
|
35
40
|
hasField = true
|
|
36
41
|
}
|
|
37
42
|
|
|
38
|
-
if (hasField)
|
|
43
|
+
if (!hasField) return
|
|
44
|
+
|
|
45
|
+
carrier ??= {}
|
|
46
|
+
carrier.dd = dd
|
|
47
|
+
return carrier
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
extract (carrier) {
|
|
@@ -8,6 +8,7 @@ const log = require('../../log')
|
|
|
8
8
|
const tags = require('../../../../../ext/tags')
|
|
9
9
|
const { getConfiguredEnvName } = require('../../config/helper')
|
|
10
10
|
const { setAllBaggageItems, getAllBaggageItems, removeAllBaggageItems } = require('../../baggage')
|
|
11
|
+
const { hasTraceSourcePropagationTag } = require('../../standalone/tracesource')
|
|
11
12
|
const telemetryMetrics = require('../../telemetry/metrics')
|
|
12
13
|
const { DD_MAJOR } = require('../../../../../version')
|
|
13
14
|
|
|
@@ -119,22 +120,35 @@ class TextMapPropagator {
|
|
|
119
120
|
return this.#baggageTagKeysSet
|
|
120
121
|
}
|
|
121
122
|
|
|
123
|
+
/**
|
|
124
|
+
* @param {DatadogSpanContext | null | undefined} spanContext
|
|
125
|
+
* @param {Record<string, string>} [carrier]
|
|
126
|
+
* @returns {Record<string, string> | undefined}
|
|
127
|
+
*/
|
|
122
128
|
inject (spanContext, carrier) {
|
|
123
|
-
if (
|
|
124
|
-
this._injectBaggageItems(spanContext, carrier)
|
|
125
|
-
if (!spanContext) return
|
|
129
|
+
if (carrier === null) return
|
|
130
|
+
let injectedCarrier = this._injectBaggageItems(spanContext, carrier)
|
|
131
|
+
if (!spanContext) return injectedCarrier
|
|
126
132
|
|
|
127
|
-
this.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
injectCh.publish({ spanContext, carrier })
|
|
133
|
+
const injectTraceContext = this._config.apmTracingEnabled !== false ||
|
|
134
|
+
hasTraceSourcePropagationTag(spanContext._trace.tags)
|
|
135
|
+
if (injectTraceContext) {
|
|
136
|
+
injectedCarrier = this._injectDatadog(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
|
|
137
|
+
injectedCarrier = this._injectB3MultipleHeaders(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
|
|
138
|
+
injectedCarrier = this._injectB3SingleHeader(spanContext, injectedCarrier ?? carrier) ?? injectedCarrier
|
|
134
139
|
}
|
|
140
|
+
injectedCarrier = this
|
|
141
|
+
._injectTraceparent(spanContext, injectedCarrier ?? carrier, injectTraceContext) ?? injectedCarrier
|
|
142
|
+
|
|
143
|
+
if (injectedCarrier === undefined) return
|
|
144
|
+
|
|
145
|
+
carrier = injectedCarrier
|
|
146
|
+
if (injectCh.hasSubscribers) injectCh.publish({ spanContext, carrier })
|
|
135
147
|
|
|
136
148
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
137
149
|
log.debug(() => `Inject into carrier: ${JSON.stringify(pick(carrier, logKeys))}.`)
|
|
150
|
+
|
|
151
|
+
return carrier
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
extract (carrier) {
|
|
@@ -156,15 +170,23 @@ class TextMapPropagator {
|
|
|
156
170
|
return spanContext
|
|
157
171
|
}
|
|
158
172
|
|
|
173
|
+
/**
|
|
174
|
+
* @param {DatadogSpanContext} spanContext
|
|
175
|
+
* @param {Record<string, string>} [carrier]
|
|
176
|
+
* @returns {Record<string, string> | undefined}
|
|
177
|
+
*/
|
|
159
178
|
_injectDatadog (spanContext, carrier) {
|
|
160
179
|
if (!this._hasPropagationStyle('inject', 'datadog')) return
|
|
161
180
|
|
|
181
|
+
carrier ??= {}
|
|
162
182
|
carrier[traceKey] = spanContext.toTraceId()
|
|
163
183
|
carrier[spanKey] = spanContext.toSpanId()
|
|
164
184
|
|
|
165
185
|
this._injectOrigin(spanContext, carrier)
|
|
166
186
|
this._injectSamplingPriority(spanContext, carrier)
|
|
167
187
|
this._injectTags(spanContext, carrier)
|
|
188
|
+
|
|
189
|
+
return carrier
|
|
168
190
|
}
|
|
169
191
|
|
|
170
192
|
_injectOrigin (spanContext, carrier) {
|
|
@@ -183,7 +205,13 @@ class TextMapPropagator {
|
|
|
183
205
|
}
|
|
184
206
|
}
|
|
185
207
|
|
|
208
|
+
/**
|
|
209
|
+
* @param {DatadogSpanContext | null | undefined} spanContext
|
|
210
|
+
* @param {Record<string, string>} [carrier]
|
|
211
|
+
* @returns {Record<string, string> | undefined}
|
|
212
|
+
*/
|
|
186
213
|
_injectBaggageItems (spanContext, carrier) {
|
|
214
|
+
let injectedCarrier
|
|
187
215
|
if (this._config.legacyBaggageEnabled) {
|
|
188
216
|
const baggageItems = spanContext?._baggageItems
|
|
189
217
|
if (baggageItems) {
|
|
@@ -202,7 +230,8 @@ class TextMapPropagator {
|
|
|
202
230
|
if (invalidHeaderValueCharExpr.test(headerValue)) {
|
|
203
231
|
headerValue = encodeURIComponent(headerValue)
|
|
204
232
|
}
|
|
205
|
-
carrier
|
|
233
|
+
injectedCarrier ??= carrier ?? {}
|
|
234
|
+
injectedCarrier[headerName] = headerValue
|
|
206
235
|
}
|
|
207
236
|
}
|
|
208
237
|
}
|
|
@@ -213,7 +242,6 @@ class TextMapPropagator {
|
|
|
213
242
|
let byteCounter = 0
|
|
214
243
|
|
|
215
244
|
const baggageItems = getAllBaggageItems()
|
|
216
|
-
if (!baggageItems) return
|
|
217
245
|
for (const key of Object.keys(baggageItems)) {
|
|
218
246
|
const baggageKey = key.trim()
|
|
219
247
|
if (!baggageTokenExpr.test(baggageKey)) continue
|
|
@@ -242,10 +270,13 @@ class TextMapPropagator {
|
|
|
242
270
|
|
|
243
271
|
baggage = baggage.slice(0, -1)
|
|
244
272
|
if (baggage) {
|
|
245
|
-
carrier
|
|
273
|
+
injectedCarrier ??= carrier ?? {}
|
|
274
|
+
injectedCarrier.baggage = baggage
|
|
246
275
|
tracerMetrics.count('context_header_style.injected', ['header_style:baggage']).inc()
|
|
247
276
|
}
|
|
248
277
|
}
|
|
278
|
+
|
|
279
|
+
return injectedCarrier
|
|
249
280
|
}
|
|
250
281
|
|
|
251
282
|
_injectTags (spanContext, carrier) {
|
|
@@ -278,12 +309,18 @@ class TextMapPropagator {
|
|
|
278
309
|
}
|
|
279
310
|
}
|
|
280
311
|
|
|
312
|
+
/**
|
|
313
|
+
* @param {DatadogSpanContext} spanContext
|
|
314
|
+
* @param {Record<string, string>} [carrier]
|
|
315
|
+
* @returns {Record<string, string> | undefined}
|
|
316
|
+
*/
|
|
281
317
|
_injectB3MultipleHeaders (spanContext, carrier) {
|
|
282
318
|
// v5 also accepts the legacy `'b3'` spelling for multi; v6 routes `'b3'` to single-header.
|
|
283
319
|
const hasB3multi = this._hasPropagationStyle('inject', 'b3multi') ||
|
|
284
320
|
(DD_MAJOR < 6 && this._hasPropagationStyle('inject', 'b3'))
|
|
285
321
|
if (!hasB3multi) return
|
|
286
322
|
|
|
323
|
+
carrier ??= {}
|
|
287
324
|
carrier[b3TraceKey] = spanContext._traceId.toTraceIdHex(spanContext._trace.tags['_dd.p.tid'])
|
|
288
325
|
carrier[b3SpanKey] = spanContext._spanId.toString(16)
|
|
289
326
|
carrier[b3SampledKey] = spanContext._sampling.priority >= AUTO_KEEP ? '1' : '0'
|
|
@@ -295,14 +332,22 @@ class TextMapPropagator {
|
|
|
295
332
|
if (spanContext._parentId) {
|
|
296
333
|
carrier[b3ParentKey] = spanContext._parentId.toString(16)
|
|
297
334
|
}
|
|
335
|
+
|
|
336
|
+
return carrier
|
|
298
337
|
}
|
|
299
338
|
|
|
339
|
+
/**
|
|
340
|
+
* @param {DatadogSpanContext} spanContext
|
|
341
|
+
* @param {Record<string, string>} [carrier]
|
|
342
|
+
* @returns {Record<string, string> | undefined}
|
|
343
|
+
*/
|
|
300
344
|
_injectB3SingleHeader (spanContext, carrier) {
|
|
301
345
|
// v6 keeps `'b3 single header'` as a back-compat alias for callers that bypass parser normalisation.
|
|
302
346
|
const hasB3SingleHeader = this._hasPropagationStyle('inject', 'b3 single header') ||
|
|
303
347
|
(DD_MAJOR >= 6 && this._hasPropagationStyle('inject', 'b3'))
|
|
304
348
|
if (!hasB3SingleHeader) return
|
|
305
349
|
|
|
350
|
+
carrier ??= {}
|
|
306
351
|
const traceId = spanContext._traceId.toTraceIdHex(spanContext._trace.tags['_dd.p.tid'])
|
|
307
352
|
const spanId = spanContext._spanId.toString(16)
|
|
308
353
|
const sampled = spanContext._sampling.priority >= AUTO_KEEP ? '1' : '0'
|
|
@@ -311,11 +356,30 @@ class TextMapPropagator {
|
|
|
311
356
|
if (spanContext._parentId) {
|
|
312
357
|
carrier[b3HeaderKey] += '-' + spanContext._parentId.toString(16)
|
|
313
358
|
}
|
|
359
|
+
|
|
360
|
+
return carrier
|
|
314
361
|
}
|
|
315
362
|
|
|
316
|
-
|
|
363
|
+
/**
|
|
364
|
+
* @param {DatadogSpanContext} spanContext
|
|
365
|
+
* @param {Record<string, string> | undefined} carrier
|
|
366
|
+
* @param {boolean} injectTraceContext
|
|
367
|
+
* @returns {Record<string, string> | undefined}
|
|
368
|
+
*/
|
|
369
|
+
_injectTraceparent (spanContext, carrier, injectTraceContext) {
|
|
317
370
|
if (!this._hasPropagationStyle('inject', 'tracecontext')) return
|
|
318
371
|
|
|
372
|
+
if (!injectTraceContext) {
|
|
373
|
+
const tracestate = TraceState.fromString(spanContext._tracestate?.toString())
|
|
374
|
+
tracestate.delete('dd')
|
|
375
|
+
const header = tracestate.toString()
|
|
376
|
+
if (!header) return
|
|
377
|
+
carrier ??= {}
|
|
378
|
+
carrier.tracestate = header
|
|
379
|
+
return carrier
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
carrier ??= {}
|
|
319
383
|
const {
|
|
320
384
|
_sampling: { priority, mechanism },
|
|
321
385
|
_tracestate: ts = new TraceState(),
|
|
@@ -363,6 +427,8 @@ class TextMapPropagator {
|
|
|
363
427
|
})
|
|
364
428
|
|
|
365
429
|
carrier.tracestate = ts.toString()
|
|
430
|
+
|
|
431
|
+
return carrier
|
|
366
432
|
}
|
|
367
433
|
|
|
368
434
|
_hasPropagationStyle (mode, name) {
|
|
@@ -13,13 +13,22 @@ class DSMTextMapPropagator {
|
|
|
13
13
|
this.config = config
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @param {object} ctx DSM pathway context.
|
|
18
|
+
* @param {Record<string, string>} [carrier]
|
|
19
|
+
* @returns {Record<string, string> | undefined}
|
|
20
|
+
*/
|
|
16
21
|
inject (ctx, carrier) {
|
|
17
22
|
if (!this.config.dsmEnabled) return
|
|
18
23
|
|
|
19
|
-
DsmPathwayCodec.encode(ctx, carrier)
|
|
24
|
+
const injectedCarrier = DsmPathwayCodec.encode(ctx, carrier)
|
|
25
|
+
if (injectedCarrier === undefined) return
|
|
20
26
|
|
|
27
|
+
carrier = injectedCarrier
|
|
21
28
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
22
29
|
log.debug(() => `Inject into carrier (DSM): ${JSON.stringify(pick(carrier, logKeys))}.`)
|
|
30
|
+
|
|
31
|
+
return carrier
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
extract (carrier) {
|
|
@@ -101,6 +101,12 @@ class DatadogTracer {
|
|
|
101
101
|
return span
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* @param {Span|SpanContext} context
|
|
106
|
+
* @param {string} format
|
|
107
|
+
* @param {object} [carrier]
|
|
108
|
+
* @returns {object | undefined}
|
|
109
|
+
*/
|
|
104
110
|
inject (context, format, carrier) {
|
|
105
111
|
if (context instanceof Span) {
|
|
106
112
|
context = context.context()
|
|
@@ -110,7 +116,7 @@ class DatadogTracer {
|
|
|
110
116
|
if (format !== 'text_map_dsm' && format !== formats.LOG) {
|
|
111
117
|
this._prioritySampler.sample(context)
|
|
112
118
|
}
|
|
113
|
-
this._propagators[format].inject(context, carrier)
|
|
119
|
+
return this._propagators[format].inject(context, carrier)
|
|
114
120
|
} catch (e) {
|
|
115
121
|
log.error('Error injecting trace', e)
|
|
116
122
|
runtimeMetrics.increment('datadog.tracer.node.inject.errors', true)
|
|
@@ -181,6 +181,9 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
181
181
|
}
|
|
182
182
|
this.tracer._exporter.getLibraryConfiguration(this.testConfiguration, (err, libraryConfig) => {
|
|
183
183
|
if (err) {
|
|
184
|
+
this.libraryConfig = undefined
|
|
185
|
+
this.itrCorrelationId = undefined
|
|
186
|
+
this.skippableSuitesCoverage = undefined
|
|
184
187
|
log.error('Library configuration could not be fetched. %s', err.message)
|
|
185
188
|
this._addRequestErrorTag(DD_CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS, err)
|
|
186
189
|
} else {
|
|
@@ -955,17 +958,28 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
955
958
|
}
|
|
956
959
|
log.debug('Removing all Dynamic Instrumentation probes')
|
|
957
960
|
const promises = []
|
|
958
|
-
for (const
|
|
959
|
-
|
|
960
|
-
promises.push(this.removeDiProbe({ file, line }))
|
|
961
|
+
for (const [activeProbeKey, probeId] of this.fileLineToProbeId) {
|
|
962
|
+
promises.push(this.#removeDiProbe(activeProbeKey, probeId))
|
|
961
963
|
}
|
|
962
964
|
return Promise.all(promises)
|
|
963
965
|
}
|
|
964
966
|
|
|
967
|
+
/**
|
|
968
|
+
* @param {{ file: string, line: number }} location
|
|
969
|
+
*/
|
|
965
970
|
removeDiProbe ({ file, line }) {
|
|
966
|
-
const
|
|
967
|
-
|
|
968
|
-
this
|
|
971
|
+
const activeProbeKey = `${file}:${line}`
|
|
972
|
+
const probeId = this.fileLineToProbeId.get(activeProbeKey)
|
|
973
|
+
return this.#removeDiProbe(activeProbeKey, probeId)
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* @param {string} activeProbeKey
|
|
978
|
+
* @param {string|undefined} probeId
|
|
979
|
+
*/
|
|
980
|
+
#removeDiProbe (activeProbeKey, probeId) {
|
|
981
|
+
log.warn('Removing probe from %s, with id: %s', activeProbeKey, probeId)
|
|
982
|
+
this.fileLineToProbeId.delete(activeProbeKey)
|
|
969
983
|
return this.di.removeProbe(probeId)
|
|
970
984
|
}
|
|
971
985
|
|
|
@@ -13,6 +13,7 @@ const {
|
|
|
13
13
|
TELEMETRY_GIT_COMMAND_ERRORS,
|
|
14
14
|
} = require('../../ci-visibility/telemetry')
|
|
15
15
|
const { storage } = require('../../../../datadog-core')
|
|
16
|
+
const { getSegment } = require('../../util')
|
|
16
17
|
const {
|
|
17
18
|
GIT_COMMIT_SHA,
|
|
18
19
|
GIT_BRANCH,
|
|
@@ -251,7 +252,7 @@ function getGitRemoteName () {
|
|
|
251
252
|
)
|
|
252
253
|
|
|
253
254
|
if (upstreamRemote) {
|
|
254
|
-
return upstreamRemote
|
|
255
|
+
return getSegment(upstreamRemote, '/', 0)
|
|
255
256
|
}
|
|
256
257
|
|
|
257
258
|
const remotes = sanitizedExec(
|
|
@@ -263,7 +264,7 @@ function getGitRemoteName () {
|
|
|
263
264
|
false
|
|
264
265
|
)
|
|
265
266
|
|
|
266
|
-
return remotes
|
|
267
|
+
return getSegment(remotes, '\n', 0) || 'origin'
|
|
267
268
|
}
|
|
268
269
|
|
|
269
270
|
function getSourceBranch () {
|
|
@@ -26,14 +26,27 @@ const supportedProxies = {
|
|
|
26
26
|
'aws-apigateway': {
|
|
27
27
|
spanName: 'aws.apigateway',
|
|
28
28
|
component: 'aws-apigateway',
|
|
29
|
+
providesTimestamp: true,
|
|
29
30
|
},
|
|
30
31
|
'aws-httpapi': {
|
|
31
32
|
spanName: 'aws.httpapi',
|
|
32
33
|
component: 'aws-httpapi',
|
|
34
|
+
providesTimestamp: true,
|
|
33
35
|
},
|
|
34
36
|
'azure-apim': {
|
|
35
37
|
spanName: 'azure.apim',
|
|
36
38
|
component: 'azure-apim',
|
|
39
|
+
providesTimestamp: true,
|
|
40
|
+
},
|
|
41
|
+
'azure-gw': {
|
|
42
|
+
spanName: 'azure.app-gateway',
|
|
43
|
+
component: 'azure-gw',
|
|
44
|
+
providesTimestamp: false,
|
|
45
|
+
},
|
|
46
|
+
'azure-fd': {
|
|
47
|
+
spanName: 'azure.frontdoor',
|
|
48
|
+
component: 'azure-fd',
|
|
49
|
+
providesTimestamp: false,
|
|
37
50
|
},
|
|
38
51
|
}
|
|
39
52
|
|
|
@@ -109,21 +122,32 @@ function setInferredProxySpanTags (span, proxyContext) {
|
|
|
109
122
|
}
|
|
110
123
|
|
|
111
124
|
function extractInferredProxyContext (headers) {
|
|
112
|
-
if (!(
|
|
125
|
+
if (!(PROXY_HEADER_SYSTEM in headers)) {
|
|
126
|
+
return null
|
|
127
|
+
}
|
|
128
|
+
if (!Object.hasOwn(supportedProxies, headers[PROXY_HEADER_SYSTEM])) {
|
|
129
|
+
log.debug('Received headers to create inferred proxy span but headers include an unsupported proxy type: %s',
|
|
130
|
+
headers[PROXY_HEADER_SYSTEM])
|
|
131
|
+
|
|
113
132
|
return null
|
|
114
133
|
}
|
|
115
134
|
|
|
116
|
-
|
|
117
|
-
|
|
135
|
+
const detectedProxy = supportedProxies[headers[PROXY_HEADER_SYSTEM]]
|
|
136
|
+
|
|
137
|
+
if (detectedProxy.providesTimestamp && !headers[PROXY_HEADER_START_TIME_MS]) {
|
|
118
138
|
return null
|
|
119
139
|
}
|
|
120
140
|
|
|
121
141
|
return {
|
|
122
142
|
requestTime: headers[PROXY_HEADER_START_TIME_MS]
|
|
123
143
|
? Number.parseInt(headers[PROXY_HEADER_START_TIME_MS], 10)
|
|
124
|
-
:
|
|
144
|
+
: Date.now(),
|
|
125
145
|
method: headers[PROXY_HEADER_HTTPMETHOD],
|
|
126
|
-
path: headers[PROXY_HEADER_PATH]
|
|
146
|
+
path: headers[PROXY_HEADER_PATH]
|
|
147
|
+
? (headers[PROXY_HEADER_PATH].startsWith('/')
|
|
148
|
+
? headers[PROXY_HEADER_PATH]
|
|
149
|
+
: '/' + headers[PROXY_HEADER_PATH])
|
|
150
|
+
: headers[PROXY_HEADER_PATH],
|
|
127
151
|
stage: headers[PROXY_HEADER_STAGE],
|
|
128
152
|
domainName: headers[PROXY_HEADER_DOMAIN],
|
|
129
153
|
proxySystemName: headers[PROXY_HEADER_SYSTEM],
|
|
@@ -6,6 +6,7 @@ const { URL } = require('url')
|
|
|
6
6
|
const { getLageTestSessionName } = require('../../ci-visibility/lage')
|
|
7
7
|
const log = require('../../log')
|
|
8
8
|
const { getEnvironmentVariable } = require('../../config/helper')
|
|
9
|
+
const { getSegment } = require('../../util')
|
|
9
10
|
const satisfies = require('../../../../../vendor/dist/semifies')
|
|
10
11
|
|
|
11
12
|
const istanbul = require('../../../../../vendor/dist/istanbul-lib-coverage')
|
|
@@ -77,6 +78,11 @@ const {
|
|
|
77
78
|
*
|
|
78
79
|
* @typedef {{ service?: string, isServiceUserProvided?: boolean }} TestEnvironmentConfig
|
|
79
80
|
* @typedef {Record<string, string|number|undefined>} TestEnvironmentMetadata
|
|
81
|
+
* @typedef {{
|
|
82
|
+
* isRumActive?: boolean,
|
|
83
|
+
* browserVersion?: string,
|
|
84
|
+
* testExecutionId?: string
|
|
85
|
+
* }} RumTestCorrelationContext
|
|
80
86
|
*/
|
|
81
87
|
|
|
82
88
|
// session tags
|
|
@@ -130,7 +136,7 @@ const CI_APP_ORIGIN = 'ciapp-test'
|
|
|
130
136
|
// - Math.random() float values (10+ decimal digits after 0.)
|
|
131
137
|
const DYNAMIC_NAME_RE = new RegExp(
|
|
132
138
|
String.raw`\b1[6-9]\d{8,11}\b|` +
|
|
133
|
-
|
|
139
|
+
'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|' +
|
|
134
140
|
String.raw`\b\d{4}-\d{2}-\d{2}|` +
|
|
135
141
|
String.raw`(?:localhost|127\.0\.0\.1|0\.0\.0\.0):\d{4,5}\b|` +
|
|
136
142
|
String.raw`\b0\.\d{10,}`,
|
|
@@ -434,6 +440,8 @@ module.exports = {
|
|
|
434
440
|
TEST_PARAMETERS,
|
|
435
441
|
TEST_SKIP_REASON,
|
|
436
442
|
TEST_IS_RUM_ACTIVE,
|
|
443
|
+
setRumTestCorrelation,
|
|
444
|
+
setRumTestTags,
|
|
437
445
|
TEST_SOURCE_FILE,
|
|
438
446
|
TEST_FAILURE_SCREENSHOT_UPLOADED,
|
|
439
447
|
TEST_FAILURE_SCREENSHOT_UPLOAD_ERROR,
|
|
@@ -567,7 +575,7 @@ module.exports = {
|
|
|
567
575
|
// Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19
|
|
568
576
|
function getPkgManager () {
|
|
569
577
|
try {
|
|
570
|
-
return getEnvironmentVariable('npm_config_user_agent')
|
|
578
|
+
return getSegment(getEnvironmentVariable('npm_config_user_agent'), ' ', 0).replace('/', '-')
|
|
571
579
|
} catch {
|
|
572
580
|
return ''
|
|
573
581
|
}
|
|
@@ -798,6 +806,9 @@ function getTestTypeFromFramework (testFramework) {
|
|
|
798
806
|
return 'test'
|
|
799
807
|
}
|
|
800
808
|
|
|
809
|
+
/**
|
|
810
|
+
* @param {import('../../opentracing/span')} span
|
|
811
|
+
*/
|
|
801
812
|
function finishAllTraceSpans (span) {
|
|
802
813
|
for (const traceSpan of span.context()._trace.started) {
|
|
803
814
|
if (traceSpan !== span) {
|
|
@@ -806,6 +817,49 @@ function finishAllTraceSpans (span) {
|
|
|
806
817
|
}
|
|
807
818
|
}
|
|
808
819
|
|
|
820
|
+
/**
|
|
821
|
+
* @param {import('../../opentracing/span')} testSpan
|
|
822
|
+
* @param {boolean|undefined} isRumActive
|
|
823
|
+
* @param {string} [browserVersion]
|
|
824
|
+
* @returns {void}
|
|
825
|
+
*/
|
|
826
|
+
function setRumTestTags (testSpan, isRumActive, browserVersion) {
|
|
827
|
+
if (isRumActive) {
|
|
828
|
+
testSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
829
|
+
}
|
|
830
|
+
if (browserVersion) {
|
|
831
|
+
testSpan.setTag(TEST_BROWSER_VERSION, browserVersion)
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* @param {RumTestCorrelationContext} context
|
|
837
|
+
* @param {import('../../opentracing/span')|undefined} activeSpan
|
|
838
|
+
* @returns {import('../../opentracing/span')|undefined}
|
|
839
|
+
*/
|
|
840
|
+
function setRumTestCorrelation (context, activeSpan) {
|
|
841
|
+
if (!activeSpan) return
|
|
842
|
+
|
|
843
|
+
const activeContext = activeSpan.context()
|
|
844
|
+
let testSpan
|
|
845
|
+
if (activeContext.getTag(SPAN_TYPE) === 'test') {
|
|
846
|
+
testSpan = activeSpan
|
|
847
|
+
} else {
|
|
848
|
+
for (const traceSpan of activeContext._trace.started) {
|
|
849
|
+
if (traceSpan.context().getTag(SPAN_TYPE) === 'test') {
|
|
850
|
+
testSpan = traceSpan
|
|
851
|
+
break
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
if (!testSpan) return
|
|
857
|
+
|
|
858
|
+
context.testExecutionId = testSpan.context().toTraceId()
|
|
859
|
+
setRumTestTags(testSpan, context.isRumActive, context.browserVersion)
|
|
860
|
+
return testSpan
|
|
861
|
+
}
|
|
862
|
+
|
|
809
863
|
function getTestParentSpan (tracer) {
|
|
810
864
|
return tracer.extract('text_map', {
|
|
811
865
|
'x-datadog-trace-id': id().toString(10),
|
|
@@ -1360,7 +1414,6 @@ function resetCoverage (coverage) {
|
|
|
1360
1414
|
|
|
1361
1415
|
return coverageMap
|
|
1362
1416
|
.files()
|
|
1363
|
-
// eslint-disable-next-line unicorn/no-array-for-each
|
|
1364
1417
|
.forEach(filename => {
|
|
1365
1418
|
const fileCoverage = coverageMap.fileCoverageFor(filename)
|
|
1366
1419
|
fileCoverage.resetHits()
|
|
@@ -1371,7 +1424,6 @@ function mergeCoverage (coverage, targetCoverage) {
|
|
|
1371
1424
|
const coverageMap = istanbul.createCoverageMap(coverage)
|
|
1372
1425
|
return coverageMap
|
|
1373
1426
|
.files()
|
|
1374
|
-
// eslint-disable-next-line unicorn/no-array-for-each
|
|
1375
1427
|
.forEach(filename => {
|
|
1376
1428
|
const fileCoverage = coverageMap.fileCoverageFor(filename)
|
|
1377
1429
|
|
|
@@ -1454,7 +1506,7 @@ function parseAnnotations (annotations) {
|
|
|
1454
1506
|
* Returns 0 when the test is too slow to retry (≥ 5 min).
|
|
1455
1507
|
*
|
|
1456
1508
|
* @param {number} durationMs
|
|
1457
|
-
* @param {Record<string, number>} slowTestRetries
|
|
1509
|
+
* @param {Record<string, number>} slowTestRetries e.g. { '5s': 10, '10s': 5, '30s': 3, '5m': 2 }
|
|
1458
1510
|
* @returns {number}
|
|
1459
1511
|
*/
|
|
1460
1512
|
function getEfdRetryCount (durationMs, slowTestRetries) {
|
|
@@ -1469,12 +1521,17 @@ function getEfdRetryCount (durationMs, slowTestRetries) {
|
|
|
1469
1521
|
/**
|
|
1470
1522
|
* Returns the maximum retry count configured by the backend for EFD.
|
|
1471
1523
|
*
|
|
1472
|
-
* @param {Record<string, number>} slowTestRetries
|
|
1473
|
-
* @returns {number}
|
|
1524
|
+
* @param {Record<string, number> | undefined} slowTestRetries
|
|
1525
|
+
* @returns {number | undefined}
|
|
1474
1526
|
*/
|
|
1475
1527
|
function getMaxEfdRetryCount (slowTestRetries) {
|
|
1528
|
+
if (slowTestRetries === undefined) return
|
|
1529
|
+
|
|
1530
|
+
const retryCounts = Object.values(slowTestRetries)
|
|
1531
|
+
if (retryCounts.length === 0) return
|
|
1532
|
+
|
|
1476
1533
|
let maxRetries = 0
|
|
1477
|
-
for (const retryCount of
|
|
1534
|
+
for (const retryCount of retryCounts) {
|
|
1478
1535
|
if (retryCount > maxRetries) {
|
|
1479
1536
|
maxRetries = retryCount
|
|
1480
1537
|
}
|
|
@@ -185,6 +185,18 @@ const web = {
|
|
|
185
185
|
return context
|
|
186
186
|
},
|
|
187
187
|
|
|
188
|
+
// Key an existing context on the underlying `Http2Stream` so a second request
|
|
189
|
+
// backed by the same stream resolves to it via the `req.stream` lookup in
|
|
190
|
+
// `patch`. Only a mixed HTTP/2 server (raw-stream + 'request' listeners) needs
|
|
191
|
+
// this: it creates the span from a throwaway stream adapter, then the
|
|
192
|
+
// compatibility layer synthesizes the real `Http2ServerRequest` off the same
|
|
193
|
+
// stream and must reuse the adapter's span rather than open an orphan context.
|
|
194
|
+
// Confined to that path so the common single-listener request pays no extra
|
|
195
|
+
// per-request map write.
|
|
196
|
+
linkContextToStream (stream, context) {
|
|
197
|
+
contexts.set(stream, context)
|
|
198
|
+
},
|
|
199
|
+
|
|
188
200
|
// Return the request root span.
|
|
189
201
|
root (req) {
|
|
190
202
|
const context = contexts.get(req)
|