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