dd-trace 5.82.0 → 5.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +77 -79
- package/ci/init.js +6 -6
- package/index.d.ts +213 -4
- package/loader-hook.mjs +1 -1
- package/package.json +59 -56
- package/packages/datadog-core/src/storage.js +7 -7
- package/packages/datadog-esbuild/index.js +6 -0
- package/packages/datadog-instrumentations/src/ai.js +7 -3
- package/packages/datadog-instrumentations/src/child_process.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +1 -1
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/instrumentations.js +4 -3
- package/packages/datadog-instrumentations/src/helpers/register.js +3 -7
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +6 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +73 -16
- package/packages/datadog-instrumentations/src/http/client.js +2 -2
- package/packages/datadog-instrumentations/src/jest.js +124 -64
- package/packages/datadog-instrumentations/src/koa.js +2 -1
- package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
- package/packages/datadog-instrumentations/src/mocha/main.js +2 -2
- package/packages/datadog-instrumentations/src/mocha/worker.js +1 -1
- package/packages/datadog-instrumentations/src/mocha.js +1 -1
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/mysql2.js +2 -2
- package/packages/datadog-instrumentations/src/net.js +13 -5
- package/packages/datadog-instrumentations/src/nyc.js +1 -1
- package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -4
- package/packages/datadog-instrumentations/src/pg.js +4 -2
- package/packages/datadog-instrumentations/src/playwright.js +15 -11
- package/packages/datadog-instrumentations/src/selenium.js +2 -2
- package/packages/datadog-instrumentations/src/undici.js +12 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +4 -4
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +2 -2
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
- package/packages/datadog-plugin-cucumber/src/index.js +35 -34
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -2
- package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -2
- package/packages/datadog-plugin-express/src/code_origin.js +21 -15
- package/packages/datadog-plugin-fastify/src/code_origin.js +17 -4
- package/packages/datadog-plugin-jest/src/index.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-mongodb-core/src/index.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +26 -26
- package/packages/datadog-plugin-undici/src/index.js +305 -2
- package/packages/datadog-plugin-vitest/src/index.js +5 -5
- package/packages/datadog-shimmer/src/shimmer.js +2 -5
- package/packages/dd-trace/index.js +19 -0
- package/packages/dd-trace/src/agent/info.js +57 -0
- package/packages/dd-trace/src/agent/url.js +28 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +47 -7
- package/packages/dd-trace/src/appsec/rasp/index.js +2 -4
- package/packages/dd-trace/src/azure_metadata.js +8 -3
- package/packages/dd-trace/src/baggage.js +36 -11
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +5 -1
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +3 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +5 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +5 -11
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -4
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -4
- package/packages/dd-trace/src/ci-visibility/telemetry.js +6 -2
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
- package/packages/dd-trace/src/{config_defaults.js → config/defaults.js} +3 -3
- package/packages/dd-trace/src/{config-helper.js → config/helper.js} +88 -15
- package/packages/dd-trace/src/{config.js → config/index.js} +107 -46
- package/packages/dd-trace/src/config/remote_config.js +188 -19
- package/packages/dd-trace/src/{config_stable.js → config/stable.js} +20 -32
- package/packages/dd-trace/src/{supported-configurations.json → config/supported-configurations.json} +3 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +2 -5
- package/packages/dd-trace/src/datastreams/processor.js +1 -1
- package/packages/dd-trace/src/datastreams/writer.js +2 -8
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -7
- package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +10 -11
- package/packages/dd-trace/src/debugger/devtools_client/send.js +3 -3
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/constants.js +1 -1
- package/packages/dd-trace/src/debugger/index.js +83 -15
- package/packages/dd-trace/src/dogstatsd.js +5 -11
- package/packages/dd-trace/src/encode/0.4.js +2 -2
- package/packages/dd-trace/src/exporter.js +1 -1
- package/packages/dd-trace/src/exporters/agent/index.js +5 -11
- package/packages/dd-trace/src/exporters/agent/writer.js +12 -16
- package/packages/dd-trace/src/exporters/common/{agent-info-exporter.js → buffering-exporter.js} +10 -37
- package/packages/dd-trace/src/exporters/common/docker.js +2 -2
- package/packages/dd-trace/src/exporters/common/request.js +1 -1
- package/packages/dd-trace/src/exporters/common/util.js +2 -2
- package/packages/dd-trace/src/exporters/span-stats/index.js +3 -10
- package/packages/dd-trace/src/flare/index.js +1 -1
- package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
- package/packages/dd-trace/src/index.js +4 -4
- package/packages/dd-trace/src/lambda/handler.js +2 -2
- package/packages/dd-trace/src/lambda/index.js +2 -2
- package/packages/dd-trace/src/lambda/runtime/patch.js +2 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +2 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +8 -1
- package/packages/dd-trace/src/llmobs/index.js +2 -2
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +3 -4
- package/packages/dd-trace/src/llmobs/sdk.js +33 -6
- package/packages/dd-trace/src/llmobs/span_processor.js +17 -7
- package/packages/dd-trace/src/llmobs/tagger.js +175 -1
- package/packages/dd-trace/src/llmobs/writers/base.js +118 -45
- package/packages/dd-trace/src/llmobs/writers/spans.js +4 -3
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -9
- package/packages/dd-trace/src/log/index.js +50 -35
- package/packages/dd-trace/src/log/writer.js +13 -78
- package/packages/dd-trace/src/noop/proxy.js +3 -3
- package/packages/dd-trace/src/openfeature/writers/base.js +9 -16
- package/packages/dd-trace/src/openfeature/writers/util.js +3 -8
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +2 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +48 -6
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +45 -21
- package/packages/dd-trace/src/opentracing/span.js +4 -4
- package/packages/dd-trace/src/plugin_manager.js +8 -6
- package/packages/dd-trace/src/plugins/util/ci.js +5 -8
- package/packages/dd-trace/src/plugins/util/git-cache.js +3 -3
- package/packages/dd-trace/src/plugins/util/test.js +1 -1
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +41 -43
- package/packages/dd-trace/src/profiler.js +4 -39
- package/packages/dd-trace/src/profiling/config.js +74 -34
- package/packages/dd-trace/src/profiling/exporter_cli.js +5 -5
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +9 -2
- package/packages/dd-trace/src/profiling/index.js +1 -1
- package/packages/dd-trace/src/profiling/libuv-size.js +1 -1
- package/packages/dd-trace/src/profiling/profiler.js +57 -2
- package/packages/dd-trace/src/proxy.js +34 -5
- package/packages/dd-trace/src/remote_config/capabilities.js +4 -0
- package/packages/dd-trace/src/remote_config/index.js +2 -7
- package/packages/dd-trace/src/ritm.js +8 -4
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -2
- package/packages/dd-trace/src/serverless.js +2 -2
- package/packages/dd-trace/src/span_processor.js +2 -2
- package/packages/dd-trace/src/startup-log.js +7 -16
- package/packages/dd-trace/src/telemetry/endpoints.js +67 -5
- package/packages/dd-trace/src/telemetry/send-data.js +103 -4
- package/packages/dd-trace/src/telemetry/telemetry.js +229 -110
- package/vendor/dist/@isaacs/ttlcache/index.js +1 -1
- package/vendor/dist/esquery/index.js +1 -1
- package/vendor/dist/meriyah/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- /package/packages/dd-trace/src/{git_properties.js → config/git_properties.js} +0 -0
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
const logger = require('../../log')
|
|
4
4
|
const { EVP_PROXY_AGENT_BASE_PATH } = require('../constants/writers')
|
|
5
5
|
const telemetry = require('../telemetry')
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
/** @type {AgentInfoExporter} */
|
|
9
|
-
let agentInfoExporter
|
|
6
|
+
const { fetchAgentInfo } = require('../../agent/info')
|
|
7
|
+
const { getAgentUrl } = require('../../agent/url')
|
|
10
8
|
|
|
11
9
|
function setAgentStrategy (config, setWritersAgentlessValue) {
|
|
12
10
|
const agentlessEnabled = config.llmobs.agentlessEnabled
|
|
@@ -16,11 +14,7 @@ function setAgentStrategy (config, setWritersAgentlessValue) {
|
|
|
16
14
|
return
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
agentInfoExporter = new AgentInfoExporter(config)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
agentInfoExporter.getAgentInfo((err, agentInfo) => {
|
|
17
|
+
fetchAgentInfo(getAgentUrl(config), (err, agentInfo) => {
|
|
24
18
|
if (err) {
|
|
25
19
|
setWritersAgentlessValue(true)
|
|
26
20
|
return
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const { inspect } = require('util')
|
|
3
3
|
const { isTrue } = require('../util')
|
|
4
|
-
const {
|
|
4
|
+
const { getValueFromEnvSources } = require('../config/helper')
|
|
5
5
|
const { traceChannel, debugChannel, infoChannel, warnChannel, errorChannel } = require('./channels')
|
|
6
6
|
const logWriter = require('./writer')
|
|
7
7
|
const { Log, LogConfig, NoTransmitError } = require('./log')
|
|
@@ -31,31 +31,31 @@ const log = {
|
|
|
31
31
|
use (logger) {
|
|
32
32
|
config.logger = logger
|
|
33
33
|
logWriter.use(logger)
|
|
34
|
-
return
|
|
34
|
+
return log
|
|
35
35
|
},
|
|
36
36
|
|
|
37
37
|
toggle (enabled, logLevel) {
|
|
38
38
|
config.enabled = enabled
|
|
39
39
|
config.logLevel = logLevel
|
|
40
40
|
logWriter.toggle(enabled, logLevel)
|
|
41
|
-
return
|
|
41
|
+
return log
|
|
42
42
|
},
|
|
43
43
|
|
|
44
44
|
reset () {
|
|
45
45
|
logWriter.reset()
|
|
46
|
-
|
|
47
|
-
errorChannel
|
|
46
|
+
log._deprecate = memoize((code, message) => {
|
|
47
|
+
publishFormatted(errorChannel, null, message)
|
|
48
48
|
return true
|
|
49
49
|
})
|
|
50
50
|
|
|
51
|
-
return
|
|
51
|
+
return log
|
|
52
52
|
},
|
|
53
53
|
|
|
54
54
|
trace (...args) {
|
|
55
55
|
if (traceChannel.hasSubscribers) {
|
|
56
56
|
const logRecord = {}
|
|
57
57
|
|
|
58
|
-
Error.captureStackTrace(logRecord,
|
|
58
|
+
Error.captureStackTrace(logRecord, log.trace)
|
|
59
59
|
|
|
60
60
|
const stack = logRecord.stack.split('\n')
|
|
61
61
|
const fn = stack[1].replace(/^\s+at ([^\s]+) .+/, '$1')
|
|
@@ -64,56 +64,53 @@ const log = {
|
|
|
64
64
|
|
|
65
65
|
stack[0] = `Trace: ${fn}(${params})`
|
|
66
66
|
|
|
67
|
-
traceChannel
|
|
67
|
+
publishFormatted(traceChannel, null, stack.join('\n'))
|
|
68
68
|
}
|
|
69
|
-
return
|
|
69
|
+
return log
|
|
70
70
|
},
|
|
71
71
|
|
|
72
72
|
debug (...args) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
return this
|
|
73
|
+
publishFormatted(debugChannel, null, ...args)
|
|
74
|
+
return log
|
|
77
75
|
},
|
|
78
76
|
|
|
79
77
|
info (...args) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
return this
|
|
78
|
+
publishFormatted(infoChannel, null, ...args)
|
|
79
|
+
return log
|
|
84
80
|
},
|
|
85
81
|
|
|
86
82
|
warn (...args) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
return this
|
|
83
|
+
publishFormatted(warnChannel, null, ...args)
|
|
84
|
+
return log
|
|
91
85
|
},
|
|
92
86
|
|
|
93
87
|
error (...args) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
88
|
+
publishFormatted(errorChannel, formatted => {
|
|
89
|
+
const stackTraceLimitBackup = Error.stackTraceLimit
|
|
90
|
+
Error.stackTraceLimit = 0
|
|
91
|
+
const newError = new Error(formatted)
|
|
92
|
+
Error.stackTraceLimit = stackTraceLimitBackup
|
|
93
|
+
Error.captureStackTrace(newError, log.error)
|
|
94
|
+
return newError
|
|
95
|
+
}, ...args)
|
|
96
|
+
return log
|
|
98
97
|
},
|
|
99
98
|
|
|
100
99
|
errorWithoutTelemetry (...args) {
|
|
101
100
|
args.push(NO_TRANSMIT)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
return this
|
|
101
|
+
publishFormatted(errorChannel, null, ...args)
|
|
102
|
+
return log
|
|
106
103
|
},
|
|
107
104
|
|
|
108
105
|
deprecate (code, message) {
|
|
109
|
-
return
|
|
106
|
+
return log._deprecate(code, message)
|
|
110
107
|
},
|
|
111
108
|
|
|
112
109
|
isEnabled (fleetStableConfigValue, localStableConfigValue) {
|
|
113
110
|
return isTrue(
|
|
114
111
|
fleetStableConfigValue ??
|
|
115
|
-
|
|
116
|
-
(
|
|
112
|
+
getValueFromEnvSources('DD_TRACE_DEBUG') ??
|
|
113
|
+
(getValueFromEnvSources('OTEL_LOG_LEVEL') === 'debug' || undefined) ??
|
|
117
114
|
localStableConfigValue ??
|
|
118
115
|
config.enabled
|
|
119
116
|
)
|
|
@@ -126,14 +123,32 @@ const log = {
|
|
|
126
123
|
) {
|
|
127
124
|
return optionsValue ??
|
|
128
125
|
fleetStableConfigValue ??
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
getValueFromEnvSources('DD_TRACE_LOG_LEVEL') ??
|
|
127
|
+
getValueFromEnvSources('OTEL_LOG_LEVEL') ??
|
|
131
128
|
localStableConfigValue ??
|
|
132
129
|
config.logLevel
|
|
133
130
|
}
|
|
134
131
|
}
|
|
135
132
|
|
|
136
|
-
|
|
133
|
+
function publishFormatted (ch, formatter, ...args) {
|
|
134
|
+
if (ch.hasSubscribers) {
|
|
135
|
+
const log = Log.parse(...args)
|
|
136
|
+
const { formatted, cause } = getErrorLog(log)
|
|
137
|
+
|
|
138
|
+
// calling twice ch.publish() because Error cause is only available in Node.js v16.9.0
|
|
139
|
+
// TODO: replace it with Error(message, { cause }) when cause has broad support
|
|
140
|
+
if (formatted) ch.publish(formatter?.(formatted) || formatted)
|
|
141
|
+
if (cause) ch.publish(cause)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function getErrorLog (err) {
|
|
146
|
+
if (typeof err?.delegate === 'function') {
|
|
147
|
+
const result = err.delegate()
|
|
148
|
+
return Array.isArray(result) ? Log.parse(...result) : Log.parse(result)
|
|
149
|
+
}
|
|
150
|
+
return err
|
|
151
|
+
}
|
|
137
152
|
|
|
138
153
|
log.reset()
|
|
139
154
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const { storage } = require('../../../datadog-core')
|
|
4
4
|
const { LogChannel } = require('./channels')
|
|
5
|
-
const { Log } = require('./log')
|
|
6
5
|
const defaultLogger = {
|
|
7
6
|
debug: msg => console.debug(msg), /* eslint-disable-line no-console */
|
|
8
7
|
info: msg => console.info(msg), /* eslint-disable-line no-console */
|
|
@@ -13,7 +12,6 @@ const defaultLogger = {
|
|
|
13
12
|
let enabled = false
|
|
14
13
|
let logger = defaultLogger
|
|
15
14
|
let logChannel = new LogChannel()
|
|
16
|
-
let stackTraceLimitFunction = onError
|
|
17
15
|
|
|
18
16
|
function withNoop (fn) {
|
|
19
17
|
const store = storage('legacy').getStore()
|
|
@@ -24,7 +22,7 @@ function withNoop (fn) {
|
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
function unsubscribeAll () {
|
|
27
|
-
logChannel.unsubscribe({ trace
|
|
25
|
+
logChannel.unsubscribe({ trace, debug, info, warn, error })
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
function toggleSubscription (enable, level) {
|
|
@@ -32,7 +30,7 @@ function toggleSubscription (enable, level) {
|
|
|
32
30
|
|
|
33
31
|
if (enable) {
|
|
34
32
|
logChannel = new LogChannel(level)
|
|
35
|
-
logChannel.subscribe({ trace
|
|
33
|
+
logChannel.subscribe({ trace, debug, info, warn, error })
|
|
36
34
|
}
|
|
37
35
|
}
|
|
38
36
|
|
|
@@ -53,89 +51,26 @@ function reset () {
|
|
|
53
51
|
toggleSubscription(false)
|
|
54
52
|
}
|
|
55
53
|
|
|
56
|
-
function
|
|
57
|
-
|
|
58
|
-
const result = err.delegate()
|
|
59
|
-
return Array.isArray(result) ? Log.parse(...result) : Log.parse(result)
|
|
60
|
-
}
|
|
61
|
-
return err
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function setStackTraceLimitFunction (fn) {
|
|
65
|
-
if (typeof fn !== 'function') {
|
|
66
|
-
throw new TypeError('stackTraceLimitFunction must be a function')
|
|
67
|
-
}
|
|
68
|
-
stackTraceLimitFunction = fn
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function onError (err) {
|
|
72
|
-
const { formatted, cause } = getErrorLog(err)
|
|
73
|
-
|
|
74
|
-
// calling twice logger.error() because Error cause is only available in Node.js v16.9.0
|
|
75
|
-
// TODO: replace it with Error(message, { cause }) when cause has broad support
|
|
76
|
-
if (formatted) {
|
|
77
|
-
withNoop(() => {
|
|
78
|
-
const stackTraceLimitBackup = Error.stackTraceLimit
|
|
79
|
-
Error.stackTraceLimit = 0
|
|
80
|
-
const newError = new Error(formatted)
|
|
81
|
-
Error.stackTraceLimit = stackTraceLimitBackup
|
|
82
|
-
Error.captureStackTrace(newError, stackTraceLimitFunction)
|
|
83
|
-
logger.error(newError)
|
|
84
|
-
})
|
|
85
|
-
}
|
|
86
|
-
if (cause) withNoop(() => logger.error(cause))
|
|
54
|
+
function error (err) {
|
|
55
|
+
withNoop(() => logger.error(err))
|
|
87
56
|
}
|
|
88
57
|
|
|
89
|
-
function
|
|
90
|
-
|
|
91
|
-
if (formatted) withNoop(() => logger.warn(formatted))
|
|
92
|
-
if (cause) withNoop(() => logger.warn(cause))
|
|
58
|
+
function warn (log) {
|
|
59
|
+
withNoop(() => logger.warn ? logger.warn(log) : logger.debug(log))
|
|
93
60
|
}
|
|
94
61
|
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
if (formatted) withNoop(() => logger.info(formatted))
|
|
98
|
-
if (cause) withNoop(() => logger.info(cause))
|
|
62
|
+
function info (log) {
|
|
63
|
+
withNoop(() => logger.info ? logger.info(log) : logger.debug(log))
|
|
99
64
|
}
|
|
100
65
|
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
if (formatted) withNoop(() => logger.debug(formatted))
|
|
104
|
-
if (cause) withNoop(() => logger.debug(cause))
|
|
66
|
+
function debug (log) {
|
|
67
|
+
withNoop(() => logger.debug(log))
|
|
105
68
|
}
|
|
106
69
|
|
|
107
|
-
function
|
|
108
|
-
const { formatted, cause } = getErrorLog(log)
|
|
70
|
+
function trace (log) {
|
|
109
71
|
// Using logger.debug() because not all loggers have trace level,
|
|
110
72
|
// and console.trace() has a completely different meaning.
|
|
111
|
-
|
|
112
|
-
if (cause) withNoop(() => logger.debug(cause))
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function error (...args) {
|
|
116
|
-
onError(Log.parse(...args))
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function warn (...args) {
|
|
120
|
-
const log = Log.parse(...args)
|
|
121
|
-
if (!logger.warn) return onDebug(log)
|
|
122
|
-
|
|
123
|
-
onWarn(log)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function info (...args) {
|
|
127
|
-
const log = Log.parse(...args)
|
|
128
|
-
if (!logger.info) return onDebug(log)
|
|
129
|
-
|
|
130
|
-
onInfo(log)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function debug (...args) {
|
|
134
|
-
onDebug(Log.parse(...args))
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function trace (...args) {
|
|
138
|
-
onTrace(Log.parse(...args))
|
|
73
|
+
withNoop(() => logger.debug(log))
|
|
139
74
|
}
|
|
140
75
|
|
|
141
|
-
module.exports = { use, toggle, reset, error, warn, info, debug, trace
|
|
76
|
+
module.exports = { use, toggle, reset, error, warn, info, debug, trace }
|
|
@@ -23,10 +23,10 @@ class NoopProxy {
|
|
|
23
23
|
this.llmobs = noopLLMObs
|
|
24
24
|
this.openfeature = noopOpenFeatureProvider
|
|
25
25
|
this.aiguard = noopAIGuard
|
|
26
|
-
this.setBaggageItem = () => {}
|
|
27
|
-
this.getBaggageItem = () => {}
|
|
26
|
+
this.setBaggageItem = (key, value) => {}
|
|
27
|
+
this.getBaggageItem = (key) => {}
|
|
28
28
|
this.getAllBaggageItems = () => {}
|
|
29
|
-
this.removeBaggageItem = () => {}
|
|
29
|
+
this.removeBaggageItem = (keyToRemove) => {}
|
|
30
30
|
this.removeAllBaggageItems = () => {}
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { URL, format } = require('node:url')
|
|
4
3
|
const request = require('../../exporters/common/request')
|
|
5
4
|
const { safeJSONStringify } = require('../../exporters/common/util')
|
|
5
|
+
const { getAgentUrl } = require('../../agent/url')
|
|
6
6
|
|
|
7
7
|
const log = require('../../log')
|
|
8
8
|
|
|
@@ -23,6 +23,7 @@ const log = require('../../log')
|
|
|
23
23
|
* @class BaseFFEWriter
|
|
24
24
|
*/
|
|
25
25
|
class BaseFFEWriter {
|
|
26
|
+
#destroyer
|
|
26
27
|
/**
|
|
27
28
|
* @param {BaseFFEWriterOptions} options - Writer configuration options
|
|
28
29
|
*/
|
|
@@ -56,12 +57,10 @@ class BaseFFEWriter {
|
|
|
56
57
|
this.flush()
|
|
57
58
|
}, this._interval).unref()
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
process.once('beforeExit', this._beforeExitHandler)
|
|
60
|
+
const destroyer = this.destroy.bind(this)
|
|
61
|
+
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(destroyer)
|
|
63
62
|
|
|
64
|
-
this
|
|
63
|
+
this.#destroyer = destroyer
|
|
65
64
|
this._droppedEvents = 0
|
|
66
65
|
}
|
|
67
66
|
|
|
@@ -141,12 +140,12 @@ class BaseFFEWriter {
|
|
|
141
140
|
* Cleans up resources and flushes remaining events
|
|
142
141
|
*/
|
|
143
142
|
destroy () {
|
|
144
|
-
if (
|
|
143
|
+
if (this.#destroyer) {
|
|
145
144
|
log.debug(() => `Stopping ${this.constructor.name}`)
|
|
146
145
|
clearInterval(this._periodic)
|
|
147
|
-
process.removeListener('beforeExit', this._beforeExitHandler)
|
|
148
146
|
this.flush()
|
|
149
|
-
this
|
|
147
|
+
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.delete(this.#destroyer)
|
|
148
|
+
this.#destroyer = undefined
|
|
150
149
|
|
|
151
150
|
if (this._droppedEvents > 0) {
|
|
152
151
|
log.warn(`${this.constructor.name} dropped ${this._droppedEvents} events due to buffer overflow`)
|
|
@@ -159,13 +158,7 @@ class BaseFFEWriter {
|
|
|
159
158
|
* @returns {URL} Constructs agent URL from config
|
|
160
159
|
*/
|
|
161
160
|
_getAgentUrl () {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return this._config.url ?? new URL(format({
|
|
165
|
-
protocol: 'http:',
|
|
166
|
-
hostname: hostname || 'localhost',
|
|
167
|
-
port: port || 8126
|
|
168
|
-
}))
|
|
161
|
+
return getAgentUrl(this._config)
|
|
169
162
|
}
|
|
170
163
|
|
|
171
164
|
/**
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const logger = require('../../log')
|
|
4
4
|
const { EVP_PROXY_AGENT_BASE_PATH } = require('../constants/constants')
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
let agentInfoExporter
|
|
5
|
+
const { fetchAgentInfo } = require('../../agent/info')
|
|
6
|
+
const { getAgentUrl } = require('../../agent/url')
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Determines if the agent supports EVP proxy and sets the writer enabled state accordingly
|
|
@@ -12,11 +11,7 @@ let agentInfoExporter
|
|
|
12
11
|
* @param {Function} setWriterEnabledValue - Callback to set the writer enabled state
|
|
13
12
|
*/
|
|
14
13
|
function setAgentStrategy (config, setWriterEnabledValue) {
|
|
15
|
-
|
|
16
|
-
agentInfoExporter = new AgentInfoExporter(config)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
agentInfoExporter.getAgentInfo((err, agentInfo) => {
|
|
14
|
+
fetchAgentInfo(getAgentUrl(config), (err, agentInfo) => {
|
|
20
15
|
if (err) {
|
|
21
16
|
logger.debug('FFE Writer disabled - error getting agent info:', err.message)
|
|
22
17
|
setWriterEnabledValue(false)
|
|
@@ -90,7 +90,7 @@ class OtlpHttpExporterBase {
|
|
|
90
90
|
data += chunk
|
|
91
91
|
})
|
|
92
92
|
|
|
93
|
-
res.
|
|
93
|
+
res.once('end', () => {
|
|
94
94
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
95
95
|
resultCallback({ code: 0 })
|
|
96
96
|
} else {
|
|
@@ -105,7 +105,7 @@ class OtlpHttpExporterBase {
|
|
|
105
105
|
resultCallback({ code: 1, error })
|
|
106
106
|
})
|
|
107
107
|
|
|
108
|
-
req.
|
|
108
|
+
req.once('timeout', () => {
|
|
109
109
|
req.destroy()
|
|
110
110
|
const error = new Error('Request timeout')
|
|
111
111
|
resultCallback({ code: 1, error })
|
|
@@ -5,12 +5,48 @@ const { sanitizeAttributes } = require('../../../../vendor/dist/@opentelemetry/c
|
|
|
5
5
|
|
|
6
6
|
const id = require('../id')
|
|
7
7
|
const log = require('../log')
|
|
8
|
+
const DatadogSpanContext = require('../opentracing/span_context')
|
|
8
9
|
const TextMapPropagator = require('../opentracing/propagation/text_map')
|
|
9
10
|
const TraceState = require('../opentracing/propagation/tracestate')
|
|
10
11
|
const SpanContext = require('./span_context')
|
|
11
12
|
const Span = require('./span')
|
|
12
13
|
const Sampler = require('./sampler')
|
|
13
14
|
|
|
15
|
+
function normalizeLinkContext (context) {
|
|
16
|
+
if (!context) return
|
|
17
|
+
|
|
18
|
+
// OTel API bridge SpanContext wrapper
|
|
19
|
+
if (context._ddContext) return context._ddContext
|
|
20
|
+
|
|
21
|
+
// Datadog span context
|
|
22
|
+
if (typeof context.toTraceId === 'function' && typeof context.toSpanId === 'function') {
|
|
23
|
+
return context
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Standard OTel SpanContext (traceId/spanId)
|
|
27
|
+
if (typeof context.traceId !== 'string' || typeof context.spanId !== 'string') {
|
|
28
|
+
// Invalid
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let sampling
|
|
33
|
+
if (typeof context.traceFlags === 'number') {
|
|
34
|
+
sampling = { priority: context.traceFlags & 1 }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let tracestate
|
|
38
|
+
if (context.traceState?.serialize) {
|
|
39
|
+
tracestate = TraceState.fromString(context.traceState.serialize())
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return new DatadogSpanContext({
|
|
43
|
+
traceId: id(context.traceId, 16),
|
|
44
|
+
spanId: id(context.spanId, 16),
|
|
45
|
+
sampling,
|
|
46
|
+
tracestate
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
14
50
|
class Tracer {
|
|
15
51
|
constructor (library, config, tracerProvider) {
|
|
16
52
|
this._sampler = new Sampler()
|
|
@@ -96,7 +132,7 @@ class Tracer {
|
|
|
96
132
|
context = api.trace.deleteSpan(context)
|
|
97
133
|
}
|
|
98
134
|
const parentSpan = api.trace.getSpan(context)
|
|
99
|
-
const parentSpanContext = parentSpan
|
|
135
|
+
const parentSpanContext = parentSpan?.spanContext()
|
|
100
136
|
let spanContext
|
|
101
137
|
if (parentSpanContext && api.trace.isSpanContextValid(parentSpanContext)) {
|
|
102
138
|
spanContext = parentSpanContext._ddContext
|
|
@@ -107,12 +143,18 @@ class Tracer {
|
|
|
107
143
|
}
|
|
108
144
|
|
|
109
145
|
const spanKind = options.kind || api.SpanKind.INTERNAL
|
|
110
|
-
const links =
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
146
|
+
const links = []
|
|
147
|
+
if (options.links?.length) {
|
|
148
|
+
for (const link of options.links) {
|
|
149
|
+
const ddContext = normalizeLinkContext(link?.context)
|
|
150
|
+
if (!ddContext) continue
|
|
151
|
+
|
|
152
|
+
links.push({
|
|
153
|
+
context: ddContext,
|
|
154
|
+
attributes: sanitizeAttributes(link.attributes)
|
|
155
|
+
})
|
|
114
156
|
}
|
|
115
|
-
}
|
|
157
|
+
}
|
|
116
158
|
const attributes = sanitizeAttributes(options.attributes)
|
|
117
159
|
|
|
118
160
|
// TODO: sampling API is not yet supported
|
|
@@ -34,11 +34,19 @@ const b3HeaderKey = 'b3'
|
|
|
34
34
|
const sqsdHeaderHey = 'x-aws-sqsd-attr-_datadog'
|
|
35
35
|
const b3HeaderExpr = /^(([0-9a-f]{16}){1,2}-[0-9a-f]{16}(-[01d](-[0-9a-f]{16})?)?|[01d])$/i
|
|
36
36
|
const baggageExpr = new RegExp(`^${baggagePrefix}(.+)$`)
|
|
37
|
+
// W3C Baggage key grammar: key = token (RFC 7230).
|
|
38
|
+
// Spec (up-to-date): "Propagation format for distributed context: Baggage" §3.3.1
|
|
39
|
+
// https://www.w3.org/TR/baggage/#header-content
|
|
40
|
+
// https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6
|
|
41
|
+
const baggageTokenExpr = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/
|
|
37
42
|
const tagKeyExpr = /^_dd\.p\.[\x21-\x2B\x2D-\x7E]+$/ // ASCII minus spaces and commas
|
|
38
43
|
const tagValueExpr = /^[\x20-\x2B\x2D-\x7E]*$/ // ASCII minus commas
|
|
39
44
|
// RFC7230 token (used by HTTP header field-name) and compatible with Node's header name validation.
|
|
40
45
|
// See https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6
|
|
41
46
|
const httpHeaderNameExpr = /^[0-9A-Za-z!#$%&'*+\-.^_`|~]+$/
|
|
47
|
+
// Compatible with Node's internal header value validation (allows HTAB, SP-~, and \x80-\xFF only)
|
|
48
|
+
// https://github.com/nodejs/node/blob/main/lib/_http_common.js
|
|
49
|
+
const invalidHeaderValueCharExpr = /[^\t\x20-\x7E\x80-\xFF]/
|
|
42
50
|
const traceparentExpr = /^([a-f0-9]{2})-([a-f0-9]{32})-([a-f0-9]{16})-([a-f0-9]{2})(-.*)?$/i
|
|
43
51
|
const traceparentKey = 'traceparent'
|
|
44
52
|
const tracestateKey = 'tracestate'
|
|
@@ -124,13 +132,6 @@ class TextMapPropagator {
|
|
|
124
132
|
}
|
|
125
133
|
}
|
|
126
134
|
|
|
127
|
-
_encodeOtelBaggageKey (key) {
|
|
128
|
-
let encoded = encodeURIComponent(key)
|
|
129
|
-
encoded = encoded.replaceAll('(', '%28')
|
|
130
|
-
encoded = encoded.replaceAll(')', '%29')
|
|
131
|
-
return encoded
|
|
132
|
-
}
|
|
133
|
-
|
|
134
135
|
_injectBaggageItems (spanContext, carrier) {
|
|
135
136
|
if (this._config.legacyBaggageEnabled) {
|
|
136
137
|
const baggageItems = spanContext?._baggageItems
|
|
@@ -145,7 +146,12 @@ class TextMapPropagator {
|
|
|
145
146
|
continue
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
|
|
149
|
+
let headerValue = String(baggageItems[key])
|
|
150
|
+
// Avoid Node throwing ERR_INVALID_CHAR when setting header values (e.g. newline from decoded OTEL baggage).
|
|
151
|
+
if (invalidHeaderValueCharExpr.test(headerValue)) {
|
|
152
|
+
headerValue = encodeURIComponent(headerValue)
|
|
153
|
+
}
|
|
154
|
+
carrier[headerName] = headerValue
|
|
149
155
|
}
|
|
150
156
|
}
|
|
151
157
|
}
|
|
@@ -157,7 +163,13 @@ class TextMapPropagator {
|
|
|
157
163
|
const baggageItems = getAllBaggageItems()
|
|
158
164
|
if (!baggageItems) return
|
|
159
165
|
for (const [key, value] of Object.entries(baggageItems)) {
|
|
160
|
-
const
|
|
166
|
+
const baggageKey = String(key).trim()
|
|
167
|
+
if (!baggageKey || !baggageTokenExpr.test(baggageKey)) continue
|
|
168
|
+
|
|
169
|
+
// Do not trim values. If callers include leading/trailing whitespace, it must be percent-encoded.
|
|
170
|
+
// W3C list-member allows optional properties after ';'.
|
|
171
|
+
// https://www.w3.org/TR/baggage/#header-content
|
|
172
|
+
const item = `${baggageKey}=${encodeURIComponent(String(value))},`
|
|
161
173
|
itemCounter += 1
|
|
162
174
|
byteCounter += Buffer.byteLength(item)
|
|
163
175
|
|
|
@@ -640,13 +652,6 @@ class TextMapPropagator {
|
|
|
640
652
|
}
|
|
641
653
|
}
|
|
642
654
|
|
|
643
|
-
_decodeOtelBaggageKey (key) {
|
|
644
|
-
let decoded = decodeURIComponent(key)
|
|
645
|
-
decoded = decoded.replaceAll('%28', '(')
|
|
646
|
-
decoded = decoded.replaceAll('%29', ')')
|
|
647
|
-
return decoded
|
|
648
|
-
}
|
|
649
|
-
|
|
650
655
|
_extractLegacyBaggageItems (carrier, spanContext) {
|
|
651
656
|
if (this._config.legacyBaggageEnabled) {
|
|
652
657
|
Object.keys(carrier).forEach(key => {
|
|
@@ -668,19 +673,38 @@ class TextMapPropagator {
|
|
|
668
673
|
? undefined
|
|
669
674
|
: new Set(this._config.baggageTagKeys.split(','))
|
|
670
675
|
for (const keyValue of baggages) {
|
|
671
|
-
if (!keyValue
|
|
676
|
+
if (!keyValue) continue
|
|
677
|
+
|
|
678
|
+
// Per W3C baggage, list-members can contain optional properties after `;`.
|
|
679
|
+
// Example: key=value;prop=1;prop2
|
|
680
|
+
// https://www.w3.org/TR/baggage/#header-content
|
|
681
|
+
const semicolonIdx = keyValue.indexOf(';')
|
|
682
|
+
const member = (semicolonIdx === -1 ? keyValue : keyValue.slice(0, semicolonIdx)).trim()
|
|
683
|
+
if (!member) continue
|
|
684
|
+
|
|
685
|
+
const eqIdx = member.indexOf('=')
|
|
686
|
+
if (eqIdx === -1) {
|
|
672
687
|
tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
|
|
673
688
|
removeAllBaggageItems()
|
|
674
689
|
return
|
|
675
690
|
}
|
|
676
|
-
|
|
677
|
-
key =
|
|
678
|
-
value =
|
|
679
|
-
|
|
691
|
+
|
|
692
|
+
const key = member.slice(0, eqIdx).trim()
|
|
693
|
+
let value = member.slice(eqIdx + 1).trim()
|
|
694
|
+
|
|
695
|
+
if (!baggageTokenExpr.test(key) || !value) {
|
|
680
696
|
tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
|
|
681
697
|
removeAllBaggageItems()
|
|
682
698
|
return
|
|
683
699
|
}
|
|
700
|
+
try {
|
|
701
|
+
value = decodeURIComponent(value)
|
|
702
|
+
} catch {
|
|
703
|
+
tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
|
|
704
|
+
removeAllBaggageItems()
|
|
705
|
+
return
|
|
706
|
+
}
|
|
707
|
+
|
|
684
708
|
if (spanContext && (tagAllKeys || keysToSpanTag?.has(key))) {
|
|
685
709
|
spanContext._trace.tags['baggage.' + key] = value
|
|
686
710
|
}
|
|
@@ -12,18 +12,18 @@ const runtimeMetrics = require('../runtime_metrics')
|
|
|
12
12
|
const log = require('../log')
|
|
13
13
|
const { storage } = require('../../../datadog-core')
|
|
14
14
|
const telemetryMetrics = require('../telemetry/metrics')
|
|
15
|
-
const {
|
|
15
|
+
const { getValueFromEnvSources } = require('../config/helper')
|
|
16
16
|
const SpanContext = require('./span_context')
|
|
17
17
|
|
|
18
18
|
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
|
|
19
19
|
|
|
20
|
-
const DD_TRACE_EXPERIMENTAL_STATE_TRACKING =
|
|
21
|
-
const DD_TRACE_EXPERIMENTAL_SPAN_COUNTS =
|
|
20
|
+
const DD_TRACE_EXPERIMENTAL_STATE_TRACKING = getValueFromEnvSources('DD_TRACE_EXPERIMENTAL_STATE_TRACKING')
|
|
21
|
+
const DD_TRACE_EXPERIMENTAL_SPAN_COUNTS = getValueFromEnvSources('DD_TRACE_EXPERIMENTAL_SPAN_COUNTS')
|
|
22
22
|
|
|
23
23
|
const unfinishedRegistry = createRegistry('unfinished')
|
|
24
24
|
const finishedRegistry = createRegistry('finished')
|
|
25
25
|
|
|
26
|
-
const OTEL_ENABLED = !!
|
|
26
|
+
const OTEL_ENABLED = !!getValueFromEnvSources('DD_TRACE_OTEL_ENABLED')
|
|
27
27
|
const ALLOWED = new Set(['string', 'number', 'boolean'])
|
|
28
28
|
|
|
29
29
|
const integrationCounters = {
|