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
|
@@ -92,8 +92,10 @@ function Hook (modules, options, onrequire) {
|
|
|
92
92
|
let name, basedir, hooks
|
|
93
93
|
// return known patched modules immediately
|
|
94
94
|
if (cache[moduleId]) {
|
|
95
|
-
// require.cache
|
|
96
|
-
|
|
95
|
+
// Use Node's cache: bundlers replace require.cache with their own factory cache,
|
|
96
|
+
// whose not-yet-evaluated external modules can still have empty exports.
|
|
97
|
+
// @ts-expect-error - Module._cache is not typed
|
|
98
|
+
const cacheEntry = Module._cache[filename]
|
|
97
99
|
if (cacheEntry && cacheEntry.exports !== cache[moduleId].original) {
|
|
98
100
|
return cacheEntry.exports
|
|
99
101
|
}
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
const { getEnvironmentVariable, getValueFromEnvSources } = require('./config/helper')
|
|
4
4
|
|
|
5
5
|
const IS_AWS_LAMBDA_MICROVM = getEnvironmentVariable('AWS_LAMBDA_MICROVM_IMAGE_ARN') !== undefined
|
|
6
|
+
// Standard Lambda, whose sandbox freezes between invocations. Excludes Lambda Lite (native-http),
|
|
7
|
+
// Managed Instances (lambda-managed-instances) and MicroVMs.
|
|
8
|
+
const IS_STANDARD_AWS_LAMBDA = !IS_AWS_LAMBDA_MICROVM && ['on-demand', 'provisioned-concurrency', 'snap-start']
|
|
9
|
+
.includes(getEnvironmentVariable('AWS_LAMBDA_INITIALIZATION_TYPE'))
|
|
6
10
|
const isVercelAtStartup = getEnvironmentVariable('VERCEL') === '1'
|
|
7
11
|
|
|
8
12
|
function getIsGCPFunction () {
|
|
@@ -28,6 +32,10 @@ function enableGCPPubSubPushSubscription () {
|
|
|
28
32
|
getValueFromEnvSources('DD_TRACE_GCP_PUBSUB_PUSH_ENABLED')
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
function getIsAzureContainerApp () {
|
|
36
|
+
return getEnvironmentVariable('CONTAINER_APP_NAME') !== undefined
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
function getIsAzureFunction () {
|
|
32
40
|
return getEnvironmentVariable('FUNCTIONS_EXTENSION_VERSION') !== undefined &&
|
|
33
41
|
getEnvironmentVariable('FUNCTIONS_WORKER_RUNTIME') !== undefined
|
|
@@ -99,11 +107,13 @@ module.exports = {
|
|
|
99
107
|
supportsServerlessTelemetryRetention,
|
|
100
108
|
createServerlessDeliveryTracker,
|
|
101
109
|
getIsGCPFunction,
|
|
110
|
+
getIsAzureContainerApp,
|
|
102
111
|
getIsAzureFunction,
|
|
103
112
|
enableGCPPubSubPushSubscription,
|
|
104
113
|
getIsFlexConsumptionAzureFunction,
|
|
105
114
|
initializeServerlessTelemetry,
|
|
106
115
|
IS_AWS_LAMBDA_MICROVM,
|
|
116
|
+
IS_STANDARD_AWS_LAMBDA,
|
|
107
117
|
// true only for a Node that bundles its own OpenSSL, whose CSPRNG keeps the snapshot's DRBG
|
|
108
118
|
// state across a MicroVM clone resume
|
|
109
119
|
NODE_BUNDLES_OPENSSL: process.config.variables.node_shared_openssl === false,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { AUTO_REJECT } = require('../../../ext/priority')
|
|
3
|
+
const { AUTO_KEEP, AUTO_REJECT } = require('../../../ext/priority')
|
|
4
4
|
const log = require('./log')
|
|
5
5
|
const spanFormat = require('./span_format')
|
|
6
6
|
const SpanSampler = require('./span_sampler')
|
|
@@ -15,32 +15,23 @@ const finishedSpans = new WeakSet()
|
|
|
15
15
|
|
|
16
16
|
let otelSampling
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* @param {import('./opentracing/span')} span
|
|
22
|
-
* @param {boolean} isFirstSpanInChunk
|
|
23
|
-
* @param {string | false} processTagsValue
|
|
24
|
-
*/
|
|
25
|
-
function formatOtlpSpan (span, isFirstSpanInChunk, processTagsValue) {
|
|
26
|
-
const formattedSpan = spanFormat(span, isFirstSpanInChunk, processTagsValue)
|
|
27
|
-
const context = span.context()
|
|
18
|
+
/** @param {import('./opentracing/span_context')} context */
|
|
19
|
+
function serializeOtlpTraceState (context) {
|
|
28
20
|
const traceState = context._tracestate?.clone() ?? new TraceState()
|
|
29
21
|
otelSampling ??= require('./otel-sampling')
|
|
30
22
|
otelSampling.updateOtelTraceState(context, traceState)
|
|
31
|
-
|
|
32
|
-
return formattedSpan
|
|
23
|
+
return traceState.toString()
|
|
33
24
|
}
|
|
34
25
|
|
|
35
26
|
class SpanProcessor {
|
|
36
|
-
#
|
|
27
|
+
#exportOtlpTraces
|
|
37
28
|
|
|
38
29
|
constructor (exporter, prioritySampler, config, otlpStatsExporter, exportOtlpTraces) {
|
|
39
30
|
this._exporter = exporter
|
|
40
31
|
this._prioritySampler = prioritySampler
|
|
41
32
|
this._config = config
|
|
42
33
|
this._killAll = false
|
|
43
|
-
this.#
|
|
34
|
+
this.#exportOtlpTraces = exportOtlpTraces
|
|
44
35
|
|
|
45
36
|
if (config.stats?.DD_TRACE_STATS_COMPUTATION_ENABLED &&
|
|
46
37
|
!config.appsec?.DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED) {
|
|
@@ -95,13 +86,18 @@ class SpanProcessor {
|
|
|
95
86
|
let isFirstSpanInChunk = true
|
|
96
87
|
const stampApmDisabled = this._config.apmTracingEnabled === false
|
|
97
88
|
const discard = this.#isDiscarded(spanContext)
|
|
98
|
-
const
|
|
89
|
+
const exportOtlpTraces = this.#exportOtlpTraces && !(spanContext._sampling.priority < AUTO_KEEP)
|
|
90
|
+
let traceState
|
|
99
91
|
|
|
100
92
|
for (const span of started) {
|
|
101
93
|
if (span._duration === undefined) {
|
|
102
94
|
active.push(span)
|
|
103
95
|
} else if (!discard) {
|
|
104
|
-
const formattedSpan =
|
|
96
|
+
const formattedSpan = spanFormat(span, isFirstSpanInChunk, this._processTags)
|
|
97
|
+
if (exportOtlpTraces) {
|
|
98
|
+
traceState ??= serializeOtlpTraceState(spanContext)
|
|
99
|
+
formattedSpan.trace_state = traceState
|
|
100
|
+
}
|
|
105
101
|
if (stampApmDisabled) {
|
|
106
102
|
formattedSpan.metrics[APM_TRACING_ENABLED_KEY] = 0
|
|
107
103
|
}
|
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
const dc = require('dc-polyfill')
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
|
+
const { isACFActive } = require('../../datadog-core/src/storage')
|
|
5
6
|
|
|
6
7
|
// Channels that surface tracer-storage events to interested consumers
|
|
7
8
|
// (currently the wall profiler and the OTEP-4947 thread context writer).
|
|
8
9
|
//
|
|
9
10
|
// dd-trace:storage:enter — fires when the active legacy-storage store
|
|
10
|
-
// changes. Published by the shimmer installed in
|
|
11
|
-
// dd-trace:storage:before — fires from an async_hooks "before" callback
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
11
|
+
// changes. Published by the shimmer installed in acquireChannels().
|
|
12
|
+
// dd-trace:storage:before — fires from an async_hooks "before" callback while
|
|
13
|
+
// at least one consumer that acquired the channels needs it. Used by the
|
|
14
|
+
// wall profiler in its non-AsyncContextFrame (single holder) mode to refresh
|
|
15
|
+
// the sample context at the start of each async resource callback.
|
|
15
16
|
// dd-trace:span:finish, dd-trace:span:tags:update — published by the
|
|
16
17
|
// tracer core (opentracing/span.js). Re-exported here as a convenience
|
|
17
18
|
// so consumers have a single import path for storage-related channels.
|
|
@@ -25,55 +26,119 @@ function getActiveSpan () {
|
|
|
25
26
|
return store && store.span
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
// The legacy storage instrumentation feeding enterCh and beforeCh is installed
|
|
30
|
+
// lazily via acquireChannels() / releaseChannels(), ref-counted across
|
|
31
|
+
// consumers, so that once the last consumer stops (e.g. the profiler is turned
|
|
32
|
+
// off remotely), instrumentation is undone.
|
|
33
|
+
// Consumers MUST balance every acquireChannels() call with a matching
|
|
34
|
+
// releaseChannels() when they no longer use them.
|
|
35
|
+
let refCount = 0
|
|
36
|
+
// The async hook has a separate count: it's only needed by some consumers, and
|
|
37
|
+
// is a per-callback cost, so it's disabled as soon as the last of them releases.
|
|
38
|
+
let beforeRefCount = 0
|
|
39
|
+
let inRun = false
|
|
40
|
+
let beforeHook
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
// Wrappers currently installed on legacy storage, keyed by method name. Each
|
|
43
|
+
// entry records the method's own property descriptor from before wrapping
|
|
44
|
+
// (undefined when the method was inherited from the prototype) so it can be
|
|
45
|
+
// restored exactly.
|
|
46
|
+
const installedWrappers = new Map()
|
|
47
|
+
|
|
48
|
+
function wrapEnterWith (original) {
|
|
49
|
+
return function (store) {
|
|
50
|
+
const retVal = original.call(this, store)
|
|
51
|
+
if (!inRun && refCount !== 0) enterCh.publish()
|
|
52
|
+
return retVal
|
|
53
|
+
}
|
|
54
|
+
}
|
|
36
55
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
function wrapRun (original) {
|
|
57
|
+
const shimmer = require('../../datadog-shimmer')
|
|
58
|
+
return function (store, callback, ...args) {
|
|
59
|
+
if (refCount === 0) return original.call(this, store, callback, ...args)
|
|
60
|
+
const wrappedCb = shimmer.wrapFunction(callback, cb => function (...args) {
|
|
61
|
+
inRun = false
|
|
62
|
+
enterCh.publish()
|
|
63
|
+
const retVal = cb.apply(this, args)
|
|
64
|
+
inRun = true
|
|
45
65
|
return retVal
|
|
46
|
-
}
|
|
47
|
-
|
|
66
|
+
})
|
|
67
|
+
inRun = true
|
|
68
|
+
const retVal = original.call(this, store, wrappedCb, ...args)
|
|
69
|
+
enterCh.publish()
|
|
70
|
+
inRun = false
|
|
71
|
+
return retVal
|
|
72
|
+
}
|
|
73
|
+
}
|
|
48
74
|
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
75
|
+
function installWrapper (target, name, wrapper) {
|
|
76
|
+
if (installedWrappers.has(name)) return
|
|
77
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, name)
|
|
78
|
+
require('../../datadog-shimmer').wrap(target, name, wrapper)
|
|
79
|
+
installedWrappers.set(name, { descriptor, wrapped: target[name] })
|
|
80
|
+
}
|
|
54
81
|
|
|
82
|
+
function uninstallWrappers (target) {
|
|
83
|
+
for (const [name, { descriptor, wrapped }] of installedWrappers) {
|
|
84
|
+
// If someone else wrapped the method on top of ours, restoring would
|
|
85
|
+
// silently drop their wrapper too. Leave ours in place instead; it
|
|
86
|
+
// short-circuits while released, and gets reused on the next acquisition.
|
|
87
|
+
if (target[name] !== wrapped) continue
|
|
88
|
+
if (descriptor === undefined) {
|
|
89
|
+
delete target[name]
|
|
90
|
+
} else {
|
|
91
|
+
Object.defineProperty(target, name, descriptor)
|
|
92
|
+
}
|
|
93
|
+
installedWrappers.delete(name)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Acquires a reference to the channel publishers. The first reference installs
|
|
99
|
+
* the legacy storage instrumentation publishing on enterCh.
|
|
100
|
+
*
|
|
101
|
+
* @param {boolean} needsBeforeHook Whether the consumer needs beforeCh events.
|
|
102
|
+
* The same value must be passed to the matching releaseChannels() call.
|
|
103
|
+
*/
|
|
104
|
+
function acquireChannels (needsBeforeHook) {
|
|
105
|
+
if (refCount++ === 0) {
|
|
106
|
+
// We need to instrument enterWith() on the legacy storage — that's the storage
|
|
107
|
+
// carrying span data and the only one consumers of these channels care about.
|
|
108
|
+
const legacyStorage = storage('legacy')
|
|
109
|
+
installWrapper(legacyStorage, 'enterWith', wrapEnterWith)
|
|
55
110
|
// In ACF-based implementation run() delegates to enterWith() so it doesn't
|
|
56
|
-
// need to be separately instrumented.
|
|
111
|
+
// need to be separately instrumented. In non-ACF implementation run()
|
|
57
112
|
// doesn't delegate to enterWith(), so separate instrumentation is necessary.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
inRun = false
|
|
62
|
-
enterCh.publish()
|
|
63
|
-
const retVal = cb.apply(this, args)
|
|
64
|
-
inRun = true
|
|
65
|
-
return retVal
|
|
66
|
-
})
|
|
67
|
-
inRun = true
|
|
68
|
-
const retVal = original.call(this, store, wrappedCb, ...args)
|
|
69
|
-
enterCh.publish()
|
|
70
|
-
inRun = false
|
|
71
|
-
return retVal
|
|
72
|
-
}
|
|
73
|
-
})
|
|
113
|
+
if (!isACFActive) {
|
|
114
|
+
installWrapper(legacyStorage, 'run', wrapRun)
|
|
115
|
+
}
|
|
74
116
|
}
|
|
75
117
|
|
|
76
|
-
|
|
118
|
+
if (needsBeforeHook && beforeRefCount++ === 0) {
|
|
119
|
+
beforeHook ??= require('async_hooks').createHook({ before: () => beforeCh.publish() })
|
|
120
|
+
beforeHook.enable()
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Releases one acquireChannels() reference. The async hook is disabled when the
|
|
126
|
+
* last reference needing it is released, and the legacy storage instrumentation
|
|
127
|
+
* is removed when the last reference overall is released.
|
|
128
|
+
*
|
|
129
|
+
* @param {boolean} needsBeforeHook The value passed to the matching
|
|
130
|
+
* acquireChannels() call.
|
|
131
|
+
*/
|
|
132
|
+
function releaseChannels (needsBeforeHook) {
|
|
133
|
+
if (refCount === 0) return
|
|
134
|
+
|
|
135
|
+
if (needsBeforeHook && beforeRefCount !== 0 && --beforeRefCount === 0) {
|
|
136
|
+
beforeHook.disable()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (--refCount === 0) {
|
|
140
|
+
uninstallWrappers(storage('legacy'))
|
|
141
|
+
}
|
|
77
142
|
}
|
|
78
143
|
|
|
79
144
|
module.exports = {
|
|
@@ -82,5 +147,6 @@ module.exports = {
|
|
|
82
147
|
spanFinishCh,
|
|
83
148
|
tagsUpdateCh,
|
|
84
149
|
getActiveSpan,
|
|
85
|
-
|
|
150
|
+
acquireChannels,
|
|
151
|
+
releaseChannels,
|
|
86
152
|
}
|
|
@@ -95,10 +95,8 @@ function onFastifyRoute (routeData) {
|
|
|
95
95
|
* @param {{ method?: string, path?: string }} param0
|
|
96
96
|
*/
|
|
97
97
|
function onExpressRoute ({ method, path }) {
|
|
98
|
-
if (!method || !path) return
|
|
99
|
-
|
|
100
98
|
// If wildcard already recorded for this path, skip specific methods
|
|
101
|
-
if (wildcardEndpoints.has(path)) return
|
|
99
|
+
if (!method || !path || wildcardEndpoints.has(path)) return
|
|
102
100
|
|
|
103
101
|
recordEndpoint(method, path, 'express.request')
|
|
104
102
|
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const path = require('path')
|
|
4
|
+
const { types: { isTypedArray } } = require('node:util')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array |
|
|
8
|
+
* Float32Array | Float64Array | BigInt64Array | BigUint64Array | DataView} BinaryView
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const getTypedArrayLength = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), 'length').get
|
|
4
12
|
|
|
5
13
|
/**
|
|
6
14
|
* `for-in` with an early return is the only allocation-free shape for
|
|
@@ -12,11 +20,31 @@ const path = require('path')
|
|
|
12
20
|
* @param {object | undefined} obj
|
|
13
21
|
*/
|
|
14
22
|
function isEmpty (obj) {
|
|
23
|
+
if (Array.isArray(obj) || ArrayBuffer.isView(obj)) {
|
|
24
|
+
// `for-in` materializes every index key up front, which exhausts memory on large bodies, so return as soon as
|
|
25
|
+
// there are elements. Empty ones have no index keys to materialize, so check their own keys, which still detects
|
|
26
|
+
// named properties without walking a Buffer's enumerable prototype methods.
|
|
27
|
+
const length = Array.isArray(obj) ? obj.length : typedArrayLength(obj)
|
|
28
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
29
|
+
return length === 0 && Object.keys(obj).length === 0
|
|
30
|
+
}
|
|
31
|
+
// `for-in` over a string also materializes every index key, so large raw string bodies need the same shortcut.
|
|
32
|
+
if (typeof obj === 'string') return obj.length === 0
|
|
15
33
|
// eslint-disable-next-line no-unreachable-loop
|
|
16
34
|
for (const _ in obj) return false
|
|
17
35
|
return true
|
|
18
36
|
}
|
|
19
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Reads the element count through the intrinsic getter, which, unlike `view.length`, an instance or subclass cannot
|
|
40
|
+
* shadow with application code. A `DataView` exposes no indexed elements, so it counts as zero.
|
|
41
|
+
*
|
|
42
|
+
* @param {BinaryView} view
|
|
43
|
+
*/
|
|
44
|
+
function typedArrayLength (view) {
|
|
45
|
+
return isTypedArray(view) ? getTypedArrayLength.call(view) : 0
|
|
46
|
+
}
|
|
47
|
+
|
|
20
48
|
function isTrue (str) {
|
|
21
49
|
str = String(str).toLowerCase()
|
|
22
50
|
return str === 'true' || str === '1'
|
|
@@ -167,4 +195,5 @@ module.exports = {
|
|
|
167
195
|
normalizePluginEnvName,
|
|
168
196
|
formatKnuthRate,
|
|
169
197
|
truncateString,
|
|
198
|
+
typedArrayLength,
|
|
170
199
|
}
|
|
@@ -120,8 +120,12 @@ function onTagsUpdate (span) {
|
|
|
120
120
|
// the ancestor's own update is what settles the endpoint. Skipped entirely
|
|
121
121
|
// when nobody is listening, keeping this the same early return it used to be
|
|
122
122
|
// for consumers that only care about web-tag discovery.
|
|
123
|
-
if (
|
|
124
|
-
|
|
123
|
+
if (
|
|
124
|
+
!endpointResolvedCh.hasSubscribers || cached.endpointFinal || cached.webTags !== tags ||
|
|
125
|
+
finalEndpoint(tags) === undefined
|
|
126
|
+
) {
|
|
127
|
+
return
|
|
128
|
+
}
|
|
125
129
|
cached.endpointFinal = true
|
|
126
130
|
endpointResolvedCh.publish(span)
|
|
127
131
|
}
|