dd-trace 5.96.0 → 5.97.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/index.d.ts +34 -0
- package/package.json +9 -7
- package/packages/datadog-esbuild/index.js +20 -9
- package/packages/datadog-instrumentations/src/child_process.js +7 -17
- package/packages/datadog-instrumentations/src/crypto.js +1 -2
- package/packages/datadog-instrumentations/src/cucumber.js +4 -1
- package/packages/datadog-instrumentations/src/cypress-config.js +324 -0
- package/packages/datadog-instrumentations/src/cypress.js +86 -4
- package/packages/datadog-instrumentations/src/dns.js +1 -2
- package/packages/datadog-instrumentations/src/express.js +4 -4
- package/packages/datadog-instrumentations/src/fs.js +27 -29
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
- package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
- package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
- package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
- package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
- package/packages/datadog-instrumentations/src/http/client.js +2 -3
- package/packages/datadog-instrumentations/src/http/server.js +2 -5
- package/packages/datadog-instrumentations/src/http2/client.js +1 -3
- package/packages/datadog-instrumentations/src/http2/server.js +1 -3
- package/packages/datadog-instrumentations/src/jest.js +13 -4
- package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +4 -1
- package/packages/datadog-instrumentations/src/net.js +2 -8
- package/packages/datadog-instrumentations/src/pino.js +1 -1
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +1 -2
- package/packages/datadog-instrumentations/src/selenium.js +4 -1
- package/packages/datadog-instrumentations/src/sequelize.js +1 -1
- package/packages/datadog-instrumentations/src/url.js +1 -3
- package/packages/datadog-instrumentations/src/vitest.js +5 -1
- package/packages/datadog-instrumentations/src/vm.js +1 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +4 -3
- package/packages/datadog-plugin-cucumber/src/index.js +7 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +57 -5
- package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +4 -2
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
- package/packages/datadog-plugin-mocha/src/index.js +5 -2
- package/packages/datadog-plugin-next/src/index.js +2 -14
- package/packages/datadog-plugin-openai/src/services.js +1 -0
- package/packages/datadog-webpack/index.js +3 -3
- package/packages/dd-trace/index.js +12 -10
- package/packages/dd-trace/src/agent/url.js +2 -2
- package/packages/dd-trace/src/aiguard/sdk.js +4 -0
- package/packages/dd-trace/src/appsec/blocking.js +3 -0
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config.js +1 -0
- package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/config/defaults.js +316 -146
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
- package/packages/dd-trace/src/config/helper.js +59 -10
- package/packages/dd-trace/src/config/index.js +569 -1505
- package/packages/dd-trace/src/config/parsers.js +256 -0
- package/packages/dd-trace/src/config/remote_config.js +59 -2
- package/packages/dd-trace/src/config/supported-configurations.json +350 -433
- package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
- package/packages/dd-trace/src/crashtracking/index.js +1 -7
- package/packages/dd-trace/src/debugger/index.js +1 -1
- package/packages/dd-trace/src/dogstatsd.js +12 -9
- package/packages/dd-trace/src/encode/0.4.js +1 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
- package/packages/dd-trace/src/exporters/common/request.js +9 -0
- package/packages/dd-trace/src/exporters/common/writer.js +12 -2
- package/packages/dd-trace/src/heap_snapshots.js +3 -0
- package/packages/dd-trace/src/index.js +5 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
- package/packages/dd-trace/src/llmobs/index.js +4 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
- package/packages/dd-trace/src/llmobs/sdk.js +12 -8
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +9 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
- package/packages/dd-trace/src/log/index.js +26 -55
- package/packages/dd-trace/src/log/writer.js +7 -19
- package/packages/dd-trace/src/noop/proxy.js +8 -0
- package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
- package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
- package/packages/dd-trace/src/plugin_manager.js +8 -6
- package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
- package/packages/dd-trace/src/plugins/plugin.js +7 -4
- package/packages/dd-trace/src/process-tags/index.js +3 -0
- package/packages/dd-trace/src/profiler.js +27 -2
- package/packages/dd-trace/src/profiling/config.js +73 -241
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
- package/packages/dd-trace/src/profiling/profiler.js +56 -44
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
- package/packages/dd-trace/src/propagation-hash/index.js +2 -1
- package/packages/dd-trace/src/proxy.js +32 -3
- package/packages/dd-trace/src/remote_config/index.js +3 -0
- package/packages/dd-trace/src/require-package-json.js +8 -4
- package/packages/dd-trace/src/ritm.js +58 -26
- package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -0
- package/packages/dd-trace/src/sampler.js +1 -1
- package/packages/dd-trace/src/standalone/index.js +3 -0
- package/packages/dd-trace/src/telemetry/index.js +2 -3
- package/packages/dd-trace/src/telemetry/send-data.js +5 -19
- package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
- package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
- package/packages/dd-trace/src/util.js +0 -9
|
@@ -5,1685 +5,749 @@ const os = require('node:os')
|
|
|
5
5
|
const { URL } = require('node:url')
|
|
6
6
|
const path = require('node:path')
|
|
7
7
|
|
|
8
|
+
const rfdc = require('../../../../vendor/dist/rfdc')({ proto: false, circles: false })
|
|
8
9
|
const uuid = require('../../../../vendor/dist/crypto-randomuuid') // we need to keep the old uuid dep because of cypress
|
|
9
|
-
|
|
10
10
|
const set = require('../../../datadog-core/src/utils/src/set')
|
|
11
11
|
const { DD_MAJOR } = require('../../../../version')
|
|
12
12
|
const log = require('../log')
|
|
13
|
-
const
|
|
14
|
-
const { isTrue
|
|
13
|
+
const pkg = require('../pkg')
|
|
14
|
+
const { isTrue } = require('../util')
|
|
15
15
|
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
|
|
16
|
-
const
|
|
16
|
+
const telemetry = require('../telemetry')
|
|
17
17
|
const telemetryMetrics = require('../telemetry/metrics')
|
|
18
18
|
const {
|
|
19
19
|
IS_SERVERLESS,
|
|
20
20
|
getIsGCPFunction,
|
|
21
21
|
getIsAzureFunction,
|
|
22
|
-
enableGCPPubSubPushSubscription,
|
|
23
22
|
} = require('../serverless')
|
|
24
23
|
const { ORIGIN_KEY, DATADOG_MINI_AGENT_PATH } = require('../constants')
|
|
25
24
|
const { appendRules } = require('../payload-tagging/config')
|
|
26
25
|
const { getGitMetadataFromGitProperties, removeUserSensitiveInfo, getRemoteOriginURL, resolveGitHeadSHA } =
|
|
27
26
|
require('./git_properties')
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
])
|
|
47
|
-
const VALID_PROPAGATION_STYLES = new Set(['datadog', 'tracecontext', 'b3', 'b3 single header', 'none'])
|
|
48
|
-
const VALID_PROPAGATION_BEHAVIOR_EXTRACT = new Set(['continue', 'restart', 'ignore'])
|
|
49
|
-
const VALID_LOG_LEVELS = new Set(['debug', 'info', 'warn', 'error'])
|
|
50
|
-
const DEFAULT_OTLP_PORT = 4318
|
|
27
|
+
const ConfigBase = require('./config-base')
|
|
28
|
+
const {
|
|
29
|
+
getEnvironmentVariable,
|
|
30
|
+
getEnvironmentVariables,
|
|
31
|
+
getStableConfigSources,
|
|
32
|
+
getValueFromEnvSources,
|
|
33
|
+
} = require('./helper')
|
|
34
|
+
const {
|
|
35
|
+
defaults,
|
|
36
|
+
fallbackConfigurations,
|
|
37
|
+
configurationsTable,
|
|
38
|
+
optionsTable,
|
|
39
|
+
configWithOrigin,
|
|
40
|
+
parseErrors,
|
|
41
|
+
generateTelemetry,
|
|
42
|
+
} = require('./defaults')
|
|
43
|
+
const { transformers } = require('./parsers')
|
|
44
|
+
|
|
51
45
|
const RUNTIME_ID = uuid()
|
|
52
|
-
// eslint-disable-next-line eslint-rules/eslint-process-env -- internal propagation, not user config
|
|
53
|
-
const ROOT_SESSION_ID = process.env.DD_ROOT_JS_SESSION_ID || RUNTIME_ID
|
|
54
|
-
const NAMING_VERSIONS = new Set(['v0', 'v1'])
|
|
55
|
-
const DEFAULT_NAMING_VERSION = 'v0'
|
|
56
46
|
|
|
57
47
|
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
|
|
58
|
-
const changeTracker = {}
|
|
59
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @typedef {'default'
|
|
51
|
+
* | 'code'
|
|
52
|
+
* | 'remote_config'
|
|
53
|
+
* | 'calculated'
|
|
54
|
+
* | 'env_var'
|
|
55
|
+
* | 'local_stable_config'
|
|
56
|
+
* | 'fleet_stable_config'} TelemetrySource
|
|
57
|
+
* @typedef {'remote_config' | 'calculated'} RevertibleTelemetrySource
|
|
58
|
+
* @typedef {import('../../../../index').TracerOptions} TracerOptions
|
|
59
|
+
* @typedef {import('./config-types').ConfigKey} ConfigKey
|
|
60
|
+
* @typedef {import('./config-types').ConfigPath} ConfigPath
|
|
61
|
+
* @typedef {{
|
|
62
|
+
* value: import('./config-types').ConfigPathValue<ConfigPath>,
|
|
63
|
+
* source: TelemetrySource
|
|
64
|
+
* }} TrackedConfigEntry
|
|
65
|
+
* @typedef {{
|
|
66
|
+
* baseValuesByPath: Partial<Record<ConfigPath, TrackedConfigEntry>>,
|
|
67
|
+
* remote_config: Set<ConfigPath>,
|
|
68
|
+
* calculated: Set<ConfigPath>,
|
|
69
|
+
* }} ChangeTracker
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
/** @type {Config | null} */
|
|
60
73
|
let configInstance = null
|
|
61
74
|
|
|
75
|
+
// An entry that is undefined means it is the default value.
|
|
76
|
+
/** @type {Map<ConfigPath, TelemetrySource>} */
|
|
77
|
+
const trackedConfigOrigins = new Map()
|
|
78
|
+
|
|
79
|
+
// ChangeTracker tracks the changes to the config up to programmatic options (code).
|
|
80
|
+
/** @type {ChangeTracker} */
|
|
81
|
+
const changeTracker = {
|
|
82
|
+
baseValuesByPath: {},
|
|
83
|
+
remote_config: new Set(),
|
|
84
|
+
calculated: new Set(),
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {Config} config
|
|
89
|
+
* @param {RevertibleTelemetrySource} source
|
|
90
|
+
*/
|
|
91
|
+
function undo (config, source) {
|
|
92
|
+
for (const name of changeTracker[source]) {
|
|
93
|
+
const entry = changeTracker.baseValuesByPath[name] ?? { source: 'default', value: defaults[name] }
|
|
94
|
+
setAndTrack(config, name, entry.value, undefined, entry.source)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function get (object, path) {
|
|
99
|
+
// Fast path for simple property access.
|
|
100
|
+
if (object[path] !== undefined) {
|
|
101
|
+
return object[path]
|
|
102
|
+
}
|
|
103
|
+
let index = 0
|
|
104
|
+
while (true) {
|
|
105
|
+
const nextIndex = path.indexOf('.', index)
|
|
106
|
+
if (nextIndex === -1) {
|
|
107
|
+
return object[path.slice(index)]
|
|
108
|
+
}
|
|
109
|
+
object = object[path.slice(index, nextIndex)]
|
|
110
|
+
index = nextIndex + 1
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @param {Config} config
|
|
116
|
+
* @template {ConfigPath} TPath
|
|
117
|
+
* @param {TPath} name
|
|
118
|
+
* @param {import('./config-types').ConfigPathValue<TPath>} value
|
|
119
|
+
* @param {unknown} [rawValue]
|
|
120
|
+
* @param {TelemetrySource} [source]
|
|
121
|
+
*/
|
|
122
|
+
function setAndTrack (config, name, value, rawValue = value, source = 'calculated') {
|
|
123
|
+
// envs can not be undefined
|
|
124
|
+
if (value == null) {
|
|
125
|
+
// TODO: This works as before while ignoring undefined programmatic options is not ideal.
|
|
126
|
+
if (source !== 'default') {
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
} else if (source === 'calculated' || source === 'remote_config') {
|
|
130
|
+
if (source === 'calculated' && value === get(config, name)) {
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
changeTracker[source].add(name)
|
|
134
|
+
} else {
|
|
135
|
+
const copy = typeof value === 'object' && value !== null ? rfdc(value) : value
|
|
136
|
+
changeTracker.baseValuesByPath[name] = { value: copy, source }
|
|
137
|
+
}
|
|
138
|
+
set(config, name, value)
|
|
139
|
+
|
|
140
|
+
generateTelemetry(rawValue, source, name)
|
|
141
|
+
if (source === 'default') {
|
|
142
|
+
trackedConfigOrigins.delete(name)
|
|
143
|
+
} else {
|
|
144
|
+
trackedConfigOrigins.set(name, source)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
62
148
|
module.exports = getConfig
|
|
63
149
|
|
|
64
|
-
|
|
150
|
+
// We extend from ConfigBase to make our types work
|
|
151
|
+
class Config extends ConfigBase {
|
|
65
152
|
/**
|
|
66
153
|
* parsed DD_TAGS, usable as a standalone tag set across products
|
|
67
154
|
* @type {Record<string, string>}
|
|
68
155
|
*/
|
|
69
|
-
#parsedDdTags
|
|
70
|
-
#envUnprocessed = {}
|
|
71
|
-
#optsUnprocessed = {}
|
|
72
|
-
#remoteUnprocessed = {}
|
|
73
|
-
#env = {}
|
|
74
|
-
#options = {}
|
|
75
|
-
#remote = {}
|
|
76
|
-
#defaults = {}
|
|
77
|
-
#optionsArg = {}
|
|
78
|
-
#localStableConfig = {}
|
|
79
|
-
#fleetStableConfig = {}
|
|
80
|
-
#calculated = {}
|
|
156
|
+
#parsedDdTags
|
|
81
157
|
|
|
158
|
+
/**
|
|
159
|
+
* @type {Record<string, string>}
|
|
160
|
+
*/
|
|
161
|
+
get parsedDdTags () {
|
|
162
|
+
return this.#parsedDdTags
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param {TracerOptions} [options={}]
|
|
167
|
+
*/
|
|
82
168
|
constructor (options = {}) {
|
|
83
|
-
|
|
84
|
-
const configEnvSources = getStableConfigSources()
|
|
85
|
-
this.stableConfig = {
|
|
86
|
-
fleetEntries: configEnvSources.fleetStableConfig,
|
|
87
|
-
localEntries: configEnvSources.localStableConfig,
|
|
88
|
-
warnings: configEnvSources.stableConfigWarnings,
|
|
89
|
-
}
|
|
90
|
-
}
|
|
169
|
+
super()
|
|
91
170
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
iast: options.iast == null ? options.experimental?.iast : options.iast,
|
|
171
|
+
const configEnvSources = getStableConfigSources()
|
|
172
|
+
this.stableConfig = {
|
|
173
|
+
fleetEntries: configEnvSources.fleetStableConfig ?? {},
|
|
174
|
+
localEntries: configEnvSources.localStableConfig ?? {},
|
|
175
|
+
warnings: configEnvSources.stableConfigWarnings,
|
|
98
176
|
}
|
|
99
177
|
|
|
100
178
|
// Configure the logger first so it can be used to warn about other configs
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.stableConfig?.fleetEntries?.DD_TRACE_LOG_LEVEL,
|
|
110
|
-
this.stableConfig?.localEntries?.DD_TRACE_LOG_LEVEL
|
|
111
|
-
)
|
|
112
|
-
log.use(this.logger)
|
|
113
|
-
log.toggle(this.debug, this.logLevel)
|
|
179
|
+
// TODO: Implement auto buffering of inside of log module before first
|
|
180
|
+
// configure call. That way the logger is always available and the
|
|
181
|
+
// application doesn't need to configure it first and the configuration
|
|
182
|
+
// happens inside of config instead of inside of log module. If the logger
|
|
183
|
+
// is not deactivated, the buffered logs would be discarded. That way stable
|
|
184
|
+
// config warnings can also be logged directly and do not need special
|
|
185
|
+
// handling.
|
|
186
|
+
this.debug = log.configure(options)
|
|
114
187
|
|
|
115
188
|
// Process stable config warnings, if any
|
|
116
189
|
for (const warning of this.stableConfig?.warnings ?? []) {
|
|
117
190
|
log.warn(warning)
|
|
118
191
|
}
|
|
119
192
|
|
|
120
|
-
checkIfBothOtelAndDdEnvVarSet()
|
|
121
|
-
|
|
122
|
-
if (typeof options.appsec === 'boolean') {
|
|
123
|
-
options.appsec = {
|
|
124
|
-
enabled: options.appsec,
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (typeof options.runtimeMetrics === 'boolean') {
|
|
129
|
-
options.runtimeMetrics = {
|
|
130
|
-
enabled: options.runtimeMetrics,
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
this.#defaults = defaults
|
|
135
193
|
this.#applyDefaults()
|
|
136
|
-
|
|
137
|
-
this.#
|
|
138
|
-
this.#
|
|
139
|
-
this.#
|
|
194
|
+
// TODO: Update origin documentation to list all valid sources. Add local_stable_config and fleet_stable_config.
|
|
195
|
+
this.#applyEnvs(getEnvironmentVariables(this.stableConfig.localEntries, true), 'local_stable_config')
|
|
196
|
+
this.#applyEnvs(getEnvironmentVariables(undefined, true), 'env_var')
|
|
197
|
+
this.#applyEnvs(getEnvironmentVariables(this.stableConfig.fleetEntries, true), 'fleet_stable_config')
|
|
198
|
+
|
|
199
|
+
// Experimental options are applied first, so they can be overridden by non-experimental options.
|
|
200
|
+
// TODO: When using programmatic options, check if there is a higher
|
|
201
|
+
// priority name in the same options object. Use the highest priority name.
|
|
202
|
+
const { experimental, ...rest } = options
|
|
203
|
+
if (experimental) {
|
|
204
|
+
// @ts-expect-error - Difficult to type this correctly.
|
|
205
|
+
this.#applyOptions(experimental, 'code', 'experimental')
|
|
206
|
+
}
|
|
207
|
+
this.#applyOptions(rest, 'code')
|
|
140
208
|
this.#applyCalculated()
|
|
141
|
-
this.#merge()
|
|
142
209
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
})
|
|
210
|
+
warnWrongOtelSettings()
|
|
211
|
+
|
|
212
|
+
if (this.gitMetadataEnabled) {
|
|
213
|
+
this.#loadGitMetadata()
|
|
214
|
+
}
|
|
149
215
|
|
|
150
|
-
|
|
216
|
+
parseErrors.clear()
|
|
217
|
+
}
|
|
151
218
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
})
|
|
219
|
+
#applyDefaults () {
|
|
220
|
+
for (const [name, value] of Object.entries(defaults)) {
|
|
221
|
+
set(this, name, value)
|
|
156
222
|
}
|
|
223
|
+
}
|
|
157
224
|
|
|
158
|
-
|
|
159
|
-
|
|
225
|
+
/**
|
|
226
|
+
* @param {import('./helper').TracerEnv} envs
|
|
227
|
+
* @param {'env_var' | 'local_stable_config' | 'fleet_stable_config'} source
|
|
228
|
+
*/
|
|
229
|
+
#applyEnvs (envs, source) {
|
|
230
|
+
for (const [name, value] of Object.entries(envs)) {
|
|
231
|
+
const entry = configurationsTable[name]
|
|
232
|
+
// TracePropagationStyle is a special case. It is a single option that is used to set both inject and extract.
|
|
233
|
+
// TODO: Consider what to do with this later
|
|
234
|
+
if (name === 'DD_TRACE_PROPAGATION_STYLE') {
|
|
235
|
+
if (
|
|
236
|
+
getValueFromEnvSources('DD_TRACE_PROPAGATION_STYLE_INJECT') !== undefined ||
|
|
237
|
+
getValueFromEnvSources('DD_TRACE_PROPAGATION_STYLE_EXTRACT') !== undefined
|
|
238
|
+
) {
|
|
239
|
+
log.warn(
|
|
240
|
+
// eslint-disable-next-line @stylistic/max-len
|
|
241
|
+
'Use either DD_TRACE_PROPAGATION_STYLE or separate DD_TRACE_PROPAGATION_STYLE_INJECT and DD_TRACE_PROPAGATION_STYLE_EXTRACT environment variables'
|
|
242
|
+
)
|
|
243
|
+
continue
|
|
244
|
+
}
|
|
245
|
+
this.#applyEnvs({ DD_TRACE_PROPAGATION_STYLE_INJECT: value, DD_TRACE_PROPAGATION_STYLE_EXTRACT: value }, source)
|
|
246
|
+
continue
|
|
247
|
+
}
|
|
248
|
+
const parsed = entry.parser(value, name, source)
|
|
249
|
+
const transformed = parsed !== undefined && entry.transformer ? entry.transformer(parsed, name, source) : parsed
|
|
250
|
+
const rawValue = transformed !== null && typeof transformed === 'object' ? value : parsed
|
|
251
|
+
setAndTrack(this, entry.property ?? name, transformed, rawValue, source)
|
|
160
252
|
}
|
|
161
253
|
}
|
|
162
254
|
|
|
163
|
-
|
|
164
|
-
|
|
255
|
+
/**
|
|
256
|
+
* @param {TracerOptions} options
|
|
257
|
+
* @param {'code' | 'remote_config'} source
|
|
258
|
+
* @param {string} [root]
|
|
259
|
+
*/
|
|
260
|
+
#applyOptions (options, source, root = '') {
|
|
261
|
+
for (const [name, value] of Object.entries(options)) {
|
|
262
|
+
const fullName = root ? `${root}.${name}` : name
|
|
263
|
+
let entry = optionsTable[fullName]
|
|
264
|
+
if (!entry) {
|
|
265
|
+
// TODO: Fix this by by changing remote config to use env styles.
|
|
266
|
+
if (name !== 'tracing' || source !== 'remote_config') {
|
|
267
|
+
log.warn('Unknown option %s with value %o', fullName, value)
|
|
268
|
+
continue
|
|
269
|
+
}
|
|
270
|
+
// @ts-expect-error - The entry is defined in the configurationsTable.
|
|
271
|
+
entry = configurationsTable.tracing
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (entry.nestedProperties) {
|
|
275
|
+
let matched = false
|
|
276
|
+
if (typeof value === 'object' && value !== null) {
|
|
277
|
+
for (const nestedProperty of entry.nestedProperties) {
|
|
278
|
+
// WARNING: if the property name might be part of the value we look at, this could conflict!
|
|
279
|
+
// Defining an option that receives an object as value may not contain a property that is also
|
|
280
|
+
// potentially a nested property!
|
|
281
|
+
if (Object.hasOwn(value, nestedProperty)) {
|
|
282
|
+
this.#applyOptions(value, source, fullName)
|
|
283
|
+
matched = true
|
|
284
|
+
break
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (matched) {
|
|
289
|
+
continue
|
|
290
|
+
}
|
|
291
|
+
if (entry.option) {
|
|
292
|
+
entry = entry.option
|
|
293
|
+
} else {
|
|
294
|
+
if (fullName === 'tracePropagationStyle') {
|
|
295
|
+
// TracePropagationStyle is special. It is a single option that is used to set both inject and extract.
|
|
296
|
+
// @ts-expect-error - Difficult to type this correctly.
|
|
297
|
+
this.#applyOptions({ inject: value, extract: value }, source, 'tracePropagationStyle')
|
|
298
|
+
} else {
|
|
299
|
+
log.warn('Unknown option %s with value %o', fullName, value)
|
|
300
|
+
}
|
|
301
|
+
continue
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// TODO: Coerce mismatched types to the expected type, if possible. E.g., strings <> numbers
|
|
305
|
+
const transformed = value !== undefined && entry.transformer ? entry.transformer(value, fullName, source) : value
|
|
306
|
+
setAndTrack(this, entry.property, transformed, value, source)
|
|
307
|
+
}
|
|
165
308
|
}
|
|
166
309
|
|
|
167
310
|
/**
|
|
168
311
|
* Set the configuration with remote config settings.
|
|
169
312
|
* Applies remote configuration, recalculates derived values, and merges all configuration sources.
|
|
170
313
|
*
|
|
171
|
-
* @param {
|
|
314
|
+
* @param {TracerOptions|null} options - Configurations received via Remote
|
|
172
315
|
* Config or null to reset all remote configuration
|
|
173
316
|
*/
|
|
174
317
|
setRemoteConfig (options) {
|
|
175
318
|
// Clear all RC-managed fields to ensure previous values don't persist.
|
|
176
319
|
// State is instead managed by the `RCClientLibConfigManager` class
|
|
177
|
-
this
|
|
178
|
-
this.#remoteUnprocessed = {}
|
|
320
|
+
undo(this, 'remote_config')
|
|
179
321
|
|
|
180
322
|
// Special case: if options is null, nothing to apply
|
|
181
323
|
// This happens when all remote configs are removed
|
|
182
324
|
if (options !== null) {
|
|
183
|
-
this.#
|
|
325
|
+
this.#applyOptions(options, 'remote_config')
|
|
184
326
|
}
|
|
185
327
|
|
|
186
328
|
this.#applyCalculated()
|
|
187
|
-
this.#merge()
|
|
188
329
|
}
|
|
189
330
|
|
|
190
|
-
// TODO: Remove the `updateOptions` method. We don't want to support updating the config this way
|
|
191
331
|
/**
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* @deprecated This method should not be used and will be removed in a future version.
|
|
195
|
-
* @param {object} options - Configuration options to apply (same format as tracer init options)
|
|
332
|
+
* @param {ConfigPath} name
|
|
196
333
|
*/
|
|
197
|
-
updateOptions (options) {
|
|
198
|
-
this.#applyOptions(options)
|
|
199
|
-
this.#applyCalculated()
|
|
200
|
-
this.#merge()
|
|
201
|
-
}
|
|
202
|
-
|
|
203
334
|
getOrigin (name) {
|
|
204
|
-
|
|
205
|
-
const value = container[name]
|
|
206
|
-
if (value != null || container === this.#defaults) {
|
|
207
|
-
return origin
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
#getSourcesInOrder () {
|
|
213
|
-
return [
|
|
214
|
-
{ container: this.#remote, origin: 'remote_config', unprocessed: this.#remoteUnprocessed },
|
|
215
|
-
{ container: this.#options, origin: 'code', unprocessed: this.#optsUnprocessed },
|
|
216
|
-
{ container: this.#fleetStableConfig, origin: 'fleet_stable_config' },
|
|
217
|
-
{ container: this.#env, origin: 'env_var', unprocessed: this.#envUnprocessed },
|
|
218
|
-
{ container: this.#localStableConfig, origin: 'local_stable_config' },
|
|
219
|
-
{ container: this.#calculated, origin: 'calculated' },
|
|
220
|
-
{ container: this.#defaults, origin: 'default' },
|
|
221
|
-
]
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
#applyStableConfig (config, obj) {
|
|
225
|
-
this.#applyConfigValues(config, obj, {})
|
|
335
|
+
return trackedConfigOrigins.get(name) ?? 'default'
|
|
226
336
|
}
|
|
227
337
|
|
|
228
|
-
//
|
|
229
|
-
#
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
338
|
+
// Handles values calculated from a mixture of options and env vars
|
|
339
|
+
#applyCalculated () {
|
|
340
|
+
undo(this, 'calculated')
|
|
341
|
+
|
|
342
|
+
if (this.DD_CIVISIBILITY_AGENTLESS_URL ||
|
|
343
|
+
this.url ||
|
|
344
|
+
os.type() !== 'Windows_NT' &&
|
|
345
|
+
!trackedConfigOrigins.has('hostname') &&
|
|
346
|
+
!trackedConfigOrigins.has('port') &&
|
|
347
|
+
!this.DD_CIVISIBILITY_AGENTLESS_ENABLED &&
|
|
348
|
+
fs.existsSync('/var/run/datadog/apm.socket')) {
|
|
349
|
+
setAndTrack(
|
|
350
|
+
this,
|
|
351
|
+
'url',
|
|
352
|
+
new URL(this.DD_CIVISIBILITY_AGENTLESS_URL || this.url || 'unix:///var/run/datadog/apm.socket')
|
|
353
|
+
)
|
|
239
354
|
}
|
|
240
355
|
|
|
241
|
-
if (
|
|
242
|
-
|
|
356
|
+
if (this.isCiVisibility) {
|
|
357
|
+
setAndTrack(this, 'isServiceUserProvided', trackedConfigOrigins.has('service'))
|
|
358
|
+
this.tags[ORIGIN_KEY] = 'ciapp-test'
|
|
243
359
|
}
|
|
244
|
-
|
|
360
|
+
// Compute OTLP logs and metrics URLs to send payloads to the active Datadog Agent
|
|
361
|
+
const agentHostname = this.hostname || /** @type {URL} */ (this.url).hostname
|
|
245
362
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
363
|
+
if (!trackedConfigOrigins.has('dogstatsd.hostname')) {
|
|
364
|
+
setAndTrack(this, 'dogstatsd.hostname', agentHostname)
|
|
365
|
+
}
|
|
366
|
+
// Disable log injection when OTEL logs are enabled
|
|
367
|
+
// OTEL logs and DD log injection are mutually exclusive
|
|
368
|
+
if (this.otelLogsEnabled) {
|
|
369
|
+
setAndTrack(this, 'logInjection', false)
|
|
370
|
+
}
|
|
371
|
+
if (this.otelMetricsEnabled &&
|
|
372
|
+
trackedConfigOrigins.has('OTEL_METRICS_EXPORTER') &&
|
|
373
|
+
this.OTEL_METRICS_EXPORTER === 'none') {
|
|
374
|
+
setAndTrack(this, 'otelMetricsEnabled', false)
|
|
375
|
+
}
|
|
249
376
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
AWS_LAMBDA_FUNCTION_NAME,
|
|
253
|
-
DD_AGENT_HOST,
|
|
254
|
-
DD_AI_GUARD_BLOCK,
|
|
255
|
-
DD_AI_GUARD_ENABLED,
|
|
256
|
-
DD_AI_GUARD_ENDPOINT,
|
|
257
|
-
DD_AI_GUARD_MAX_CONTENT_SIZE,
|
|
258
|
-
DD_AI_GUARD_MAX_MESSAGES_LENGTH,
|
|
259
|
-
DD_AI_GUARD_TIMEOUT,
|
|
260
|
-
DD_API_KEY,
|
|
261
|
-
DD_API_SECURITY_ENABLED,
|
|
262
|
-
DD_API_SECURITY_SAMPLE_DELAY,
|
|
263
|
-
DD_API_SECURITY_ENDPOINT_COLLECTION_ENABLED,
|
|
264
|
-
DD_API_SECURITY_ENDPOINT_COLLECTION_MESSAGE_LIMIT,
|
|
265
|
-
DD_API_SECURITY_DOWNSTREAM_BODY_ANALYSIS_SAMPLE_RATE,
|
|
266
|
-
DD_API_SECURITY_MAX_DOWNSTREAM_REQUEST_BODY_ANALYSIS,
|
|
267
|
-
DD_APM_TRACING_ENABLED,
|
|
268
|
-
DD_APP_KEY,
|
|
269
|
-
DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE,
|
|
270
|
-
DD_APPSEC_COLLECT_ALL_HEADERS,
|
|
271
|
-
DD_APPSEC_ENABLED,
|
|
272
|
-
DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON,
|
|
273
|
-
DD_APPSEC_HEADER_COLLECTION_REDACTION_ENABLED,
|
|
274
|
-
DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML,
|
|
275
|
-
DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON,
|
|
276
|
-
DD_APPSEC_MAX_COLLECTED_HEADERS,
|
|
277
|
-
DD_APPSEC_MAX_STACK_TRACES,
|
|
278
|
-
DD_APPSEC_MAX_STACK_TRACE_DEPTH,
|
|
279
|
-
DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
|
|
280
|
-
DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP,
|
|
281
|
-
DD_APPSEC_RULES,
|
|
282
|
-
DD_APPSEC_SCA_ENABLED,
|
|
283
|
-
DD_APPSEC_STACK_TRACE_ENABLED,
|
|
284
|
-
DD_APPSEC_RASP_ENABLED,
|
|
285
|
-
DD_APPSEC_RASP_COLLECT_REQUEST_BODY,
|
|
286
|
-
DD_APPSEC_TRACE_RATE_LIMIT,
|
|
287
|
-
DD_APPSEC_WAF_TIMEOUT,
|
|
288
|
-
DD_CRASHTRACKING_ENABLED,
|
|
289
|
-
DD_CODE_ORIGIN_FOR_SPANS_ENABLED,
|
|
290
|
-
DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED,
|
|
291
|
-
DD_DATA_STREAMS_ENABLED,
|
|
292
|
-
DD_DBM_PROPAGATION_MODE,
|
|
293
|
-
DD_DBM_INJECT_SQL_BASEHASH,
|
|
294
|
-
DD_DOGSTATSD_HOST,
|
|
295
|
-
DD_DOGSTATSD_PORT,
|
|
296
|
-
DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS,
|
|
297
|
-
DD_DYNAMIC_INSTRUMENTATION_ENABLED,
|
|
298
|
-
DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE,
|
|
299
|
-
DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS,
|
|
300
|
-
DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS,
|
|
301
|
-
DD_DYNAMIC_INSTRUMENTATION_UPLOAD_INTERVAL_SECONDS,
|
|
302
|
-
DD_ENV,
|
|
303
|
-
DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED,
|
|
304
|
-
DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED,
|
|
305
|
-
DD_PROFILING_ENABLED,
|
|
306
|
-
DD_GRPC_CLIENT_ERROR_STATUSES,
|
|
307
|
-
DD_GRPC_SERVER_ERROR_STATUSES,
|
|
308
|
-
DD_HEAP_SNAPSHOT_COUNT,
|
|
309
|
-
DD_HEAP_SNAPSHOT_DESTINATION,
|
|
310
|
-
DD_HEAP_SNAPSHOT_INTERVAL,
|
|
311
|
-
DD_IAST_DB_ROWS_TO_TAINT,
|
|
312
|
-
DD_IAST_DEDUPLICATION_ENABLED,
|
|
313
|
-
DD_IAST_ENABLED,
|
|
314
|
-
DD_IAST_MAX_CONCURRENT_REQUESTS,
|
|
315
|
-
DD_IAST_MAX_CONTEXT_OPERATIONS,
|
|
316
|
-
DD_IAST_REDACTION_ENABLED,
|
|
317
|
-
DD_IAST_REDACTION_NAME_PATTERN,
|
|
318
|
-
DD_IAST_REDACTION_VALUE_PATTERN,
|
|
319
|
-
DD_IAST_REQUEST_SAMPLING,
|
|
320
|
-
DD_IAST_SECURITY_CONTROLS_CONFIGURATION,
|
|
321
|
-
DD_IAST_TELEMETRY_VERBOSITY,
|
|
322
|
-
DD_IAST_STACK_TRACE_ENABLED,
|
|
323
|
-
DD_INJECTION_ENABLED,
|
|
324
|
-
DD_INJECT_FORCE,
|
|
325
|
-
DD_ENABLE_NX_SERVICE_NAME,
|
|
326
|
-
DD_INSTRUMENTATION_TELEMETRY_ENABLED,
|
|
327
|
-
DD_INSTRUMENTATION_CONFIG_ID,
|
|
328
|
-
DD_LOGS_INJECTION,
|
|
329
|
-
DD_LOGS_OTEL_ENABLED,
|
|
330
|
-
DD_METRICS_OTEL_ENABLED,
|
|
331
|
-
DD_LANGCHAIN_SPAN_CHAR_LIMIT,
|
|
332
|
-
DD_LANGCHAIN_SPAN_PROMPT_COMPLETION_SAMPLE_RATE,
|
|
333
|
-
DD_LLMOBS_AGENTLESS_ENABLED,
|
|
334
|
-
DD_LLMOBS_ENABLED,
|
|
335
|
-
DD_LLMOBS_ML_APP,
|
|
336
|
-
DD_OPENAI_LOGS_ENABLED,
|
|
337
|
-
DD_OPENAI_SPAN_CHAR_LIMIT,
|
|
338
|
-
DD_PROFILING_EXPORTERS,
|
|
339
|
-
DD_PROFILING_SOURCE_MAP,
|
|
340
|
-
DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD,
|
|
341
|
-
DD_INSTRUMENTATION_INSTALL_ID,
|
|
342
|
-
DD_INSTRUMENTATION_INSTALL_TIME,
|
|
343
|
-
DD_INSTRUMENTATION_INSTALL_TYPE,
|
|
344
|
-
DD_REMOTE_CONFIGURATION_ENABLED,
|
|
345
|
-
DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS,
|
|
346
|
-
DD_RUNTIME_METRICS_ENABLED,
|
|
347
|
-
DD_RUNTIME_METRICS_EVENT_LOOP_ENABLED,
|
|
348
|
-
DD_RUNTIME_METRICS_GC_ENABLED,
|
|
349
|
-
DD_SERVICE,
|
|
350
|
-
DD_SERVICE_MAPPING,
|
|
351
|
-
DD_SITE,
|
|
352
|
-
DD_SPAN_SAMPLING_RULES,
|
|
353
|
-
DD_SPAN_SAMPLING_RULES_FILE,
|
|
354
|
-
DD_TAGS,
|
|
355
|
-
DD_TELEMETRY_DEBUG,
|
|
356
|
-
DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED,
|
|
357
|
-
DD_TELEMETRY_HEARTBEAT_INTERVAL,
|
|
358
|
-
DD_TELEMETRY_LOG_COLLECTION_ENABLED,
|
|
359
|
-
DD_TELEMETRY_METRICS_ENABLED,
|
|
360
|
-
DD_TEST_TIA_KEEP_COV_CONFIG,
|
|
361
|
-
DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED,
|
|
362
|
-
DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED,
|
|
363
|
-
DD_TRACE_AGENT_PORT,
|
|
364
|
-
DD_TRACE_AGENT_PROTOCOL_VERSION,
|
|
365
|
-
DD_TRACE_AWS_ADD_SPAN_POINTERS,
|
|
366
|
-
DD_TRACE_BAGGAGE_MAX_BYTES,
|
|
367
|
-
DD_TRACE_BAGGAGE_MAX_ITEMS,
|
|
368
|
-
DD_TRACE_BAGGAGE_TAG_KEYS,
|
|
369
|
-
DD_TRACE_CLIENT_IP_ENABLED,
|
|
370
|
-
DD_TRACE_CLIENT_IP_HEADER,
|
|
371
|
-
DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING,
|
|
372
|
-
DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING,
|
|
373
|
-
DD_TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH,
|
|
374
|
-
DD_TRACE_DYNAMODB_TABLE_PRIMARY_KEYS,
|
|
375
|
-
DD_TRACE_ENABLED,
|
|
376
|
-
DD_TRACE_EXPERIMENTAL_EXPORTER,
|
|
377
|
-
DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
|
|
378
|
-
DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED,
|
|
379
|
-
DD_TRACE_GIT_METADATA_ENABLED,
|
|
380
|
-
DD_TRACE_GRAPHQL_ERROR_EXTENSIONS,
|
|
381
|
-
DD_TRACE_HEADER_TAGS,
|
|
382
|
-
DD_TRACE_LEGACY_BAGGAGE_ENABLED,
|
|
383
|
-
DD_TRACE_MEMCACHED_COMMAND_ENABLED,
|
|
384
|
-
DD_TRACE_MIDDLEWARE_TRACING_ENABLED,
|
|
385
|
-
DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP,
|
|
386
|
-
DD_TRACE_PARTIAL_FLUSH_MIN_SPANS,
|
|
387
|
-
DD_TRACE_FLUSH_INTERVAL,
|
|
388
|
-
DD_TRACE_PEER_SERVICE_MAPPING,
|
|
389
|
-
DD_TRACE_PROPAGATION_EXTRACT_FIRST,
|
|
390
|
-
DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT,
|
|
391
|
-
DD_TRACE_PROPAGATION_STYLE,
|
|
392
|
-
DD_TRACE_PROPAGATION_STYLE_INJECT,
|
|
393
|
-
DD_TRACE_PROPAGATION_STYLE_EXTRACT,
|
|
394
|
-
DD_TRACE_RATE_LIMIT,
|
|
395
|
-
DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED,
|
|
396
|
-
DD_TRACE_REPORT_HOSTNAME,
|
|
397
|
-
DD_TRACE_RESOURCE_RENAMING_ENABLED,
|
|
398
|
-
DD_TRACE_SAMPLE_RATE,
|
|
399
|
-
DD_TRACE_SAMPLING_RULES,
|
|
400
|
-
DD_TRACE_SCOPE,
|
|
401
|
-
DD_TRACE_SPAN_ATTRIBUTE_SCHEMA,
|
|
402
|
-
DD_TRACE_SPAN_LEAK_DEBUG,
|
|
403
|
-
DD_TRACE_STARTUP_LOGS,
|
|
404
|
-
DD_TRACE_TAGS,
|
|
405
|
-
DD_TRACE_WEBSOCKET_MESSAGES_ENABLED,
|
|
406
|
-
DD_TRACE_WEBSOCKET_MESSAGES_INHERIT_SAMPLING,
|
|
407
|
-
DD_TRACE_WEBSOCKET_MESSAGES_SEPARATE_TRACES,
|
|
408
|
-
DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
|
|
409
|
-
DD_TRACING_ENABLED,
|
|
410
|
-
DD_VERSION,
|
|
411
|
-
DD_VERTEXAI_SPAN_PROMPT_COMPLETION_SAMPLE_RATE,
|
|
412
|
-
DD_VERTEXAI_SPAN_CHAR_LIMIT,
|
|
413
|
-
DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED,
|
|
414
|
-
DD_TRACE_NATIVE_SPAN_EVENTS,
|
|
415
|
-
OTEL_METRICS_EXPORTER,
|
|
416
|
-
OTEL_PROPAGATORS,
|
|
417
|
-
OTEL_RESOURCE_ATTRIBUTES,
|
|
418
|
-
OTEL_SERVICE_NAME,
|
|
419
|
-
OTEL_TRACES_SAMPLER,
|
|
420
|
-
OTEL_TRACES_SAMPLER_ARG,
|
|
421
|
-
DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED,
|
|
422
|
-
DD_EXPERIMENTAL_FLAGGING_PROVIDER_INITIALIZATION_TIMEOUT_MS,
|
|
423
|
-
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
|
|
424
|
-
OTEL_EXPORTER_OTLP_LOGS_HEADERS,
|
|
425
|
-
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL,
|
|
426
|
-
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
|
|
427
|
-
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,
|
|
428
|
-
OTEL_EXPORTER_OTLP_METRICS_HEADERS,
|
|
429
|
-
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL,
|
|
430
|
-
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
|
|
431
|
-
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
|
|
432
|
-
OTEL_METRIC_EXPORT_TIMEOUT,
|
|
433
|
-
OTEL_EXPORTER_OTLP_PROTOCOL,
|
|
434
|
-
OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
435
|
-
OTEL_EXPORTER_OTLP_HEADERS,
|
|
436
|
-
OTEL_EXPORTER_OTLP_TIMEOUT,
|
|
437
|
-
OTEL_BSP_SCHEDULE_DELAY,
|
|
438
|
-
OTEL_BSP_MAX_EXPORT_BATCH_SIZE,
|
|
439
|
-
OTEL_BSP_MAX_QUEUE_SIZE,
|
|
440
|
-
OTEL_METRIC_EXPORT_INTERVAL,
|
|
441
|
-
NX_TASK_TARGET_PROJECT,
|
|
442
|
-
} = source
|
|
443
|
-
|
|
444
|
-
const tags = {}
|
|
445
|
-
|
|
446
|
-
tagger.add(tags, parseSpaceSeparatedTags(handleOtel(OTEL_RESOURCE_ATTRIBUTES)))
|
|
447
|
-
tagger.add(tags, parseSpaceSeparatedTags(DD_TAGS))
|
|
448
|
-
tagger.add(tags, DD_TRACE_TAGS)
|
|
449
|
-
|
|
450
|
-
Object.assign(this.#parsedDdTags, tags)
|
|
451
|
-
|
|
452
|
-
setString(target, 'apiKey', DD_API_KEY)
|
|
453
|
-
setBoolean(target, 'otelLogsEnabled', DD_LOGS_OTEL_ENABLED)
|
|
454
|
-
// Set OpenTelemetry logs configuration with specific _LOGS_ vars taking precedence over generic _EXPORTERS_ vars
|
|
455
|
-
if (OTEL_EXPORTER_OTLP_ENDPOINT) {
|
|
456
|
-
// Only set if there's a custom URL, otherwise let calc phase handle the default
|
|
457
|
-
setString(target, 'otelUrl', OTEL_EXPORTER_OTLP_ENDPOINT)
|
|
377
|
+
if (this.telemetry.heartbeatInterval) {
|
|
378
|
+
setAndTrack(this, 'telemetry.heartbeatInterval', Math.floor(this.telemetry.heartbeatInterval * 1000))
|
|
458
379
|
}
|
|
459
|
-
if (
|
|
460
|
-
|
|
380
|
+
if (this.telemetry.extendedHeartbeatInterval) {
|
|
381
|
+
setAndTrack(this, 'telemetry.extendedHeartbeatInterval',
|
|
382
|
+
Math.floor(this.telemetry.extendedHeartbeatInterval * 1000))
|
|
461
383
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (otelTimeout !== undefined) {
|
|
468
|
-
target.otelTimeout = otelTimeout
|
|
384
|
+
|
|
385
|
+
// Enable resourceRenamingEnabled when appsec is enabled and only
|
|
386
|
+
// if DD_TRACE_RESOURCE_RENAMING_ENABLED is not explicitly set
|
|
387
|
+
if (!trackedConfigOrigins.has('resourceRenamingEnabled')) {
|
|
388
|
+
setAndTrack(this, 'resourceRenamingEnabled', this.appsec.enabled ?? false)
|
|
469
389
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (otelBatchTimeout !== undefined) {
|
|
474
|
-
target.otelBatchTimeout = otelBatchTimeout
|
|
390
|
+
|
|
391
|
+
if (!trackedConfigOrigins.has('spanComputePeerService') && this.spanAttributeSchema !== 'v0') {
|
|
392
|
+
setAndTrack(this, 'spanComputePeerService', true)
|
|
475
393
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
target,
|
|
482
|
-
'otelMetricsEnabled',
|
|
483
|
-
DD_METRICS_OTEL_ENABLED && isTrue(DD_METRICS_OTEL_ENABLED) && otelMetricsExporterEnabled
|
|
484
|
-
)
|
|
485
|
-
// Set OpenTelemetry metrics configuration with specific _METRICS_ vars
|
|
486
|
-
// taking precedence over generic _EXPORTERS_ vars
|
|
487
|
-
if (OTEL_EXPORTER_OTLP_ENDPOINT || OTEL_EXPORTER_OTLP_METRICS_ENDPOINT) {
|
|
488
|
-
setString(target, 'otelMetricsUrl', OTEL_EXPORTER_OTLP_METRICS_ENDPOINT || target.otelUrl)
|
|
394
|
+
|
|
395
|
+
if (!this.apmTracingEnabled) {
|
|
396
|
+
setAndTrack(this, 'stats.enabled', false)
|
|
397
|
+
} else if (!trackedConfigOrigins.has('stats.enabled')) {
|
|
398
|
+
setAndTrack(this, 'stats.enabled', getIsGCPFunction() || getIsAzureFunction())
|
|
489
399
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
target.otelMetricsExportInterval = nonNegInt(OTEL_METRIC_EXPORT_INTERVAL, 'OTEL_METRIC_EXPORT_INTERVAL', false)
|
|
496
|
-
|
|
497
|
-
// Parse temporality preference (default to DELTA for Datadog)
|
|
498
|
-
if (OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE) {
|
|
499
|
-
const temporalityPref = OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE.toUpperCase()
|
|
500
|
-
if (['DELTA', 'CUMULATIVE', 'LOWMEMORY'].includes(temporalityPref)) {
|
|
501
|
-
setString(target, 'otelMetricsTemporalityPreference', temporalityPref)
|
|
400
|
+
|
|
401
|
+
// TODO: Remove the experimental env vars as a major or deprecate the option?
|
|
402
|
+
if (this.experimental?.b3) {
|
|
403
|
+
if (!this.tracePropagationStyle.inject.includes('b3')) {
|
|
404
|
+
this.tracePropagationStyle.inject.push('b3')
|
|
502
405
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
target,
|
|
506
|
-
'apmTracingEnabled',
|
|
507
|
-
DD_APM_TRACING_ENABLED ??
|
|
508
|
-
(DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED && isFalse(DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED))
|
|
509
|
-
)
|
|
510
|
-
setBoolean(target, 'propagateProcessTags.enabled', DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED)
|
|
511
|
-
setString(target, 'appKey', DD_APP_KEY)
|
|
512
|
-
setBoolean(target, 'appsec.apiSecurity.enabled', DD_API_SECURITY_ENABLED && isTrue(DD_API_SECURITY_ENABLED))
|
|
513
|
-
target['appsec.apiSecurity.sampleDelay'] = maybeFloat(DD_API_SECURITY_SAMPLE_DELAY)
|
|
514
|
-
setBoolean(target, 'appsec.apiSecurity.endpointCollectionEnabled',
|
|
515
|
-
DD_API_SECURITY_ENDPOINT_COLLECTION_ENABLED)
|
|
516
|
-
target['appsec.apiSecurity.endpointCollectionMessageLimit'] =
|
|
517
|
-
maybeInt(DD_API_SECURITY_ENDPOINT_COLLECTION_MESSAGE_LIMIT)
|
|
518
|
-
target['appsec.blockedTemplateGraphql'] = maybeFile(DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON)
|
|
519
|
-
target['appsec.blockedTemplateHtml'] = maybeFile(DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML)
|
|
520
|
-
unprocessedTarget['appsec.blockedTemplateHtml'] = DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML
|
|
521
|
-
target['appsec.blockedTemplateJson'] = maybeFile(DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON)
|
|
522
|
-
unprocessedTarget['appsec.blockedTemplateJson'] = DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON
|
|
523
|
-
setBoolean(target, 'appsec.enabled', DD_APPSEC_ENABLED)
|
|
524
|
-
setString(target, 'appsec.eventTracking.mode', DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE)
|
|
525
|
-
// TODO appsec.extendedHeadersCollection are deprecated, to delete in a major
|
|
526
|
-
setBoolean(target, 'appsec.extendedHeadersCollection.enabled', DD_APPSEC_COLLECT_ALL_HEADERS)
|
|
527
|
-
setBoolean(
|
|
528
|
-
target,
|
|
529
|
-
'appsec.extendedHeadersCollection.redaction',
|
|
530
|
-
DD_APPSEC_HEADER_COLLECTION_REDACTION_ENABLED
|
|
531
|
-
)
|
|
532
|
-
target['appsec.extendedHeadersCollection.maxHeaders'] = maybeInt(DD_APPSEC_MAX_COLLECTED_HEADERS)
|
|
533
|
-
unprocessedTarget['appsec.extendedHeadersCollection.maxHeaders'] = DD_APPSEC_MAX_COLLECTED_HEADERS
|
|
534
|
-
setString(target, 'appsec.obfuscatorKeyRegex', DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP)
|
|
535
|
-
setString(target, 'appsec.obfuscatorValueRegex', DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP)
|
|
536
|
-
setBoolean(target, 'appsec.rasp.enabled', DD_APPSEC_RASP_ENABLED)
|
|
537
|
-
// TODO Deprecated, to delete in a major
|
|
538
|
-
setBoolean(target, 'appsec.rasp.bodyCollection', DD_APPSEC_RASP_COLLECT_REQUEST_BODY)
|
|
539
|
-
target['appsec.rateLimit'] = maybeInt(DD_APPSEC_TRACE_RATE_LIMIT)
|
|
540
|
-
unprocessedTarget['appsec.rateLimit'] = DD_APPSEC_TRACE_RATE_LIMIT
|
|
541
|
-
setString(target, 'appsec.rules', DD_APPSEC_RULES)
|
|
542
|
-
// DD_APPSEC_SCA_ENABLED is never used locally, but only sent to the backend
|
|
543
|
-
setBoolean(target, 'appsec.sca.enabled', DD_APPSEC_SCA_ENABLED)
|
|
544
|
-
setBoolean(target, 'appsec.stackTrace.enabled', DD_APPSEC_STACK_TRACE_ENABLED)
|
|
545
|
-
target['appsec.stackTrace.maxDepth'] = maybeInt(DD_APPSEC_MAX_STACK_TRACE_DEPTH)
|
|
546
|
-
unprocessedTarget['appsec.stackTrace.maxDepth'] = DD_APPSEC_MAX_STACK_TRACE_DEPTH
|
|
547
|
-
target['appsec.stackTrace.maxStackTraces'] = maybeInt(DD_APPSEC_MAX_STACK_TRACES)
|
|
548
|
-
unprocessedTarget['appsec.stackTrace.maxStackTraces'] = DD_APPSEC_MAX_STACK_TRACES
|
|
549
|
-
target['appsec.wafTimeout'] = maybeInt(DD_APPSEC_WAF_TIMEOUT)
|
|
550
|
-
unprocessedTarget['appsec.wafTimeout'] = DD_APPSEC_WAF_TIMEOUT
|
|
551
|
-
target['appsec.apiSecurity.downstreamBodyAnalysisSampleRate'] =
|
|
552
|
-
maybeFloat(DD_API_SECURITY_DOWNSTREAM_BODY_ANALYSIS_SAMPLE_RATE)
|
|
553
|
-
target['appsec.apiSecurity.maxDownstreamRequestBodyAnalysis'] =
|
|
554
|
-
maybeInt(DD_API_SECURITY_MAX_DOWNSTREAM_REQUEST_BODY_ANALYSIS)
|
|
555
|
-
target.baggageMaxBytes = DD_TRACE_BAGGAGE_MAX_BYTES
|
|
556
|
-
target.baggageMaxItems = DD_TRACE_BAGGAGE_MAX_ITEMS
|
|
557
|
-
setArray(target, 'baggageTagKeys', DD_TRACE_BAGGAGE_TAG_KEYS)
|
|
558
|
-
setBoolean(target, 'clientIpEnabled', DD_TRACE_CLIENT_IP_ENABLED)
|
|
559
|
-
setString(target, 'clientIpHeader', DD_TRACE_CLIENT_IP_HEADER?.toLowerCase())
|
|
560
|
-
if (DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING || DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING) {
|
|
561
|
-
if (DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING) {
|
|
562
|
-
setBoolean(target, 'cloudPayloadTagging.requestsEnabled', true)
|
|
406
|
+
if (!this.tracePropagationStyle.extract.includes('b3')) {
|
|
407
|
+
this.tracePropagationStyle.extract.push('b3')
|
|
563
408
|
}
|
|
564
|
-
if (
|
|
565
|
-
|
|
409
|
+
if (!this.tracePropagationStyle.inject.includes('b3 single header')) {
|
|
410
|
+
this.tracePropagationStyle.inject.push('b3 single header')
|
|
566
411
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
)
|
|
571
|
-
|
|
572
|
-
if (DD_TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH) {
|
|
573
|
-
target['cloudPayloadTagging.maxDepth'] = maybeInt(DD_TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH)
|
|
574
|
-
}
|
|
575
|
-
setBoolean(target, 'crashtracking.enabled', DD_CRASHTRACKING_ENABLED)
|
|
576
|
-
setBoolean(target, 'codeOriginForSpans.enabled', DD_CODE_ORIGIN_FOR_SPANS_ENABLED)
|
|
577
|
-
setBoolean(
|
|
578
|
-
target,
|
|
579
|
-
'codeOriginForSpans.experimental.exit_spans.enabled',
|
|
580
|
-
DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED
|
|
581
|
-
)
|
|
582
|
-
setString(target, 'dbmPropagationMode', DD_DBM_PROPAGATION_MODE)
|
|
583
|
-
setBoolean(target, 'dbm.injectSqlBaseHash', DD_DBM_INJECT_SQL_BASEHASH)
|
|
584
|
-
setString(target, 'dogstatsd.hostname', DD_DOGSTATSD_HOST)
|
|
585
|
-
setString(target, 'dogstatsd.port', DD_DOGSTATSD_PORT)
|
|
586
|
-
setBoolean(target, 'dsmEnabled', DD_DATA_STREAMS_ENABLED)
|
|
587
|
-
target['dynamicInstrumentation.captureTimeoutMs'] = maybeInt(DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS)
|
|
588
|
-
unprocessedTarget['dynamicInstrumentation.captureTimeoutMs'] = DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS
|
|
589
|
-
setBoolean(target, 'dynamicInstrumentation.enabled', DD_DYNAMIC_INSTRUMENTATION_ENABLED)
|
|
590
|
-
setString(target, 'dynamicInstrumentation.probeFile', DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE)
|
|
591
|
-
setArray(target, 'dynamicInstrumentation.redactedIdentifiers',
|
|
592
|
-
DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS)
|
|
593
|
-
setArray(
|
|
594
|
-
target,
|
|
595
|
-
'dynamicInstrumentation.redactionExcludedIdentifiers',
|
|
596
|
-
DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS
|
|
597
|
-
)
|
|
598
|
-
target['dynamicInstrumentation.uploadIntervalSeconds'] =
|
|
599
|
-
maybeFloat(DD_DYNAMIC_INSTRUMENTATION_UPLOAD_INTERVAL_SECONDS)
|
|
600
|
-
unprocessedTarget['dynamicInstrumentation.uploadInterval'] = DD_DYNAMIC_INSTRUMENTATION_UPLOAD_INTERVAL_SECONDS
|
|
601
|
-
setString(target, 'env', DD_ENV || tags.env)
|
|
602
|
-
setBoolean(
|
|
603
|
-
target,
|
|
604
|
-
'experimental.flaggingProvider.enabled',
|
|
605
|
-
DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED
|
|
606
|
-
)
|
|
607
|
-
if (DD_EXPERIMENTAL_FLAGGING_PROVIDER_INITIALIZATION_TIMEOUT_MS != null) {
|
|
608
|
-
target['experimental.flaggingProvider.initializationTimeoutMs'] =
|
|
609
|
-
maybeInt(DD_EXPERIMENTAL_FLAGGING_PROVIDER_INITIALIZATION_TIMEOUT_MS)
|
|
412
|
+
if (!this.tracePropagationStyle.extract.includes('b3 single header')) {
|
|
413
|
+
this.tracePropagationStyle.extract.push('b3 single header')
|
|
414
|
+
}
|
|
415
|
+
setAndTrack(this, 'tracePropagationStyle.inject', this.tracePropagationStyle.inject)
|
|
416
|
+
setAndTrack(this, 'tracePropagationStyle.extract', this.tracePropagationStyle.extract)
|
|
610
417
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
setString(target, 'experimental.aiguard.endpoint', DD_AI_GUARD_ENDPOINT)
|
|
615
|
-
target['experimental.aiguard.maxContentSize'] = maybeInt(DD_AI_GUARD_MAX_CONTENT_SIZE)
|
|
616
|
-
unprocessedTarget['experimental.aiguard.maxContentSize'] = DD_AI_GUARD_MAX_CONTENT_SIZE
|
|
617
|
-
target['experimental.aiguard.maxMessagesLength'] = maybeInt(DD_AI_GUARD_MAX_MESSAGES_LENGTH)
|
|
618
|
-
unprocessedTarget['experimental.aiguard.maxMessagesLength'] = DD_AI_GUARD_MAX_MESSAGES_LENGTH
|
|
619
|
-
target['experimental.aiguard.timeout'] = maybeInt(DD_AI_GUARD_TIMEOUT)
|
|
620
|
-
unprocessedTarget['experimental.aiguard.timeout'] = DD_AI_GUARD_TIMEOUT
|
|
621
|
-
setBoolean(target, 'experimental.enableGetRumData', DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED)
|
|
622
|
-
setString(target, 'experimental.exporter', DD_TRACE_EXPERIMENTAL_EXPORTER)
|
|
623
|
-
if (AWS_LAMBDA_FUNCTION_NAME && !fs.existsSync(DATADOG_MINI_AGENT_PATH)) {
|
|
624
|
-
target.flushInterval = 0
|
|
625
|
-
} else if (DD_TRACE_FLUSH_INTERVAL) {
|
|
626
|
-
target.flushInterval = maybeInt(DD_TRACE_FLUSH_INTERVAL)
|
|
418
|
+
|
|
419
|
+
if (getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') && !fs.existsSync(DATADOG_MINI_AGENT_PATH)) {
|
|
420
|
+
setAndTrack(this, 'flushInterval', 0)
|
|
627
421
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
setIntegerRangeSet(target, 'grpc.server.error.statuses', DD_GRPC_SERVER_ERROR_STATUSES)
|
|
633
|
-
setArray(target, 'headerTags', DD_TRACE_HEADER_TAGS)
|
|
634
|
-
target['heapSnapshot.count'] = maybeInt(DD_HEAP_SNAPSHOT_COUNT)
|
|
635
|
-
setString(target, 'heapSnapshot.destination', DD_HEAP_SNAPSHOT_DESTINATION)
|
|
636
|
-
target['heapSnapshot.interval'] = maybeInt(DD_HEAP_SNAPSHOT_INTERVAL)
|
|
637
|
-
setString(target, 'hostname', DD_AGENT_HOST)
|
|
638
|
-
target['iast.dbRowsToTaint'] = maybeInt(DD_IAST_DB_ROWS_TO_TAINT)
|
|
639
|
-
setBoolean(target, 'iast.deduplicationEnabled', DD_IAST_DEDUPLICATION_ENABLED)
|
|
640
|
-
setBoolean(target, 'iast.enabled', DD_IAST_ENABLED)
|
|
641
|
-
target['iast.maxConcurrentRequests'] = maybeInt(DD_IAST_MAX_CONCURRENT_REQUESTS)
|
|
642
|
-
unprocessedTarget['iast.maxConcurrentRequests'] = DD_IAST_MAX_CONCURRENT_REQUESTS
|
|
643
|
-
target['iast.maxContextOperations'] = maybeInt(DD_IAST_MAX_CONTEXT_OPERATIONS)
|
|
644
|
-
unprocessedTarget['iast.maxContextOperations'] = DD_IAST_MAX_CONTEXT_OPERATIONS
|
|
645
|
-
setBoolean(target, 'iast.redactionEnabled', DD_IAST_REDACTION_ENABLED && !isFalse(DD_IAST_REDACTION_ENABLED))
|
|
646
|
-
setString(target, 'iast.redactionNamePattern', DD_IAST_REDACTION_NAME_PATTERN)
|
|
647
|
-
setString(target, 'iast.redactionValuePattern', DD_IAST_REDACTION_VALUE_PATTERN)
|
|
648
|
-
const iastRequestSampling = maybeInt(DD_IAST_REQUEST_SAMPLING)
|
|
649
|
-
if (iastRequestSampling !== undefined && iastRequestSampling > -1 && iastRequestSampling < 101) {
|
|
650
|
-
target['iast.requestSampling'] = iastRequestSampling
|
|
422
|
+
|
|
423
|
+
if (!trackedConfigOrigins.has('apmTracingEnabled') &&
|
|
424
|
+
trackedConfigOrigins.has('experimental.appsec.standalone.enabled')) {
|
|
425
|
+
setAndTrack(this, 'apmTracingEnabled', !this.experimental.appsec.standalone.enabled)
|
|
651
426
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
setString(target, 'installSignature.type', DD_INSTRUMENTATION_INSTALL_TYPE)
|
|
659
|
-
// TODO: Why is DD_INJECTION_ENABLED a comma separated list?
|
|
660
|
-
setArray(target, 'injectionEnabled', DD_INJECTION_ENABLED)
|
|
661
|
-
if (DD_INJECTION_ENABLED !== undefined) {
|
|
662
|
-
setString(target, 'instrumentationSource', DD_INJECTION_ENABLED ? 'ssi' : 'manual')
|
|
427
|
+
|
|
428
|
+
if (this.cloudPayloadTagging?.request || this.cloudPayloadTagging?.response) {
|
|
429
|
+
setAndTrack(this, 'cloudPayloadTagging.rules', appendRules(
|
|
430
|
+
this.cloudPayloadTagging.request,
|
|
431
|
+
this.cloudPayloadTagging.response
|
|
432
|
+
))
|
|
663
433
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
setBoolean(target, 'gcpPubSubPushSubscriptionEnabled', enableGCPPubSubPushSubscription())
|
|
668
|
-
target['langchain.spanCharLimit'] = maybeInt(DD_LANGCHAIN_SPAN_CHAR_LIMIT)
|
|
669
|
-
target['langchain.spanPromptCompletionSampleRate'] = maybeFloat(DD_LANGCHAIN_SPAN_PROMPT_COMPLETION_SAMPLE_RATE)
|
|
670
|
-
setBoolean(target, 'legacyBaggageEnabled', DD_TRACE_LEGACY_BAGGAGE_ENABLED)
|
|
671
|
-
setBoolean(target, 'llmobs.agentlessEnabled', DD_LLMOBS_AGENTLESS_ENABLED)
|
|
672
|
-
setBoolean(target, 'llmobs.enabled', DD_LLMOBS_ENABLED)
|
|
673
|
-
setString(target, 'llmobs.mlApp', DD_LLMOBS_ML_APP)
|
|
674
|
-
setBoolean(target, 'logInjection', DD_LOGS_INJECTION)
|
|
675
|
-
// Requires an accompanying DD_APM_OBFUSCATION_MEMCACHED_KEEP_COMMAND=true in the agent
|
|
676
|
-
setBoolean(target, 'memcachedCommandEnabled', DD_TRACE_MEMCACHED_COMMAND_ENABLED)
|
|
677
|
-
setBoolean(target, 'middlewareTracingEnabled', DD_TRACE_MIDDLEWARE_TRACING_ENABLED)
|
|
678
|
-
setBoolean(target, 'openAiLogsEnabled', DD_OPENAI_LOGS_ENABLED)
|
|
679
|
-
target['openai.spanCharLimit'] = maybeInt(DD_OPENAI_SPAN_CHAR_LIMIT)
|
|
680
|
-
unprocessedTarget.openaiSpanCharLimit = DD_OPENAI_SPAN_CHAR_LIMIT
|
|
681
|
-
if (DD_TRACE_PEER_SERVICE_MAPPING) {
|
|
682
|
-
target.peerServiceMapping = Object.fromEntries(
|
|
683
|
-
DD_TRACE_PEER_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
|
|
684
|
-
)
|
|
685
|
-
unprocessedTarget.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
|
|
434
|
+
|
|
435
|
+
if (this.injectionEnabled) {
|
|
436
|
+
setAndTrack(this, 'instrumentationSource', 'ssi')
|
|
686
437
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
setString(target, 'profiling.exporters', DD_PROFILING_EXPORTERS)
|
|
691
|
-
setBoolean(target, 'profiling.sourceMap', DD_PROFILING_SOURCE_MAP && !isFalse(DD_PROFILING_SOURCE_MAP))
|
|
692
|
-
if (DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD) {
|
|
693
|
-
// This is only used in testing to not have to wait 30s
|
|
694
|
-
target['profiling.longLivedThreshold'] = Number(DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD)
|
|
438
|
+
|
|
439
|
+
if (!trackedConfigOrigins.has('runtimeMetrics.enabled') && this.OTEL_METRICS_EXPORTER === 'none') {
|
|
440
|
+
setAndTrack(this, 'runtimeMetrics.enabled', false)
|
|
695
441
|
}
|
|
696
442
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
setBoolean(target, 'remoteConfig.enabled', DD_REMOTE_CONFIGURATION_ENABLED)
|
|
700
|
-
target['remoteConfig.pollInterval'] = maybeFloat(DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS)
|
|
701
|
-
unprocessedTarget['remoteConfig.pollInterval'] = DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS
|
|
702
|
-
setBoolean(target, 'reportHostname', DD_TRACE_REPORT_HOSTNAME)
|
|
703
|
-
if (DD_TRACE_RESOURCE_RENAMING_ENABLED !== undefined) {
|
|
704
|
-
setBoolean(target, 'resourceRenamingEnabled', DD_TRACE_RESOURCE_RENAMING_ENABLED)
|
|
443
|
+
if (!trackedConfigOrigins.has('sampleRate') && trackedConfigOrigins.has('OTEL_TRACES_SAMPLER')) {
|
|
444
|
+
setAndTrack(this, 'sampleRate', getFromOtelSamplerMap(this.OTEL_TRACES_SAMPLER, this.OTEL_TRACES_SAMPLER_ARG))
|
|
705
445
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
setBoolean(target, 'runtimeMetrics.gc', DD_RUNTIME_METRICS_GC_ENABLED)
|
|
714
|
-
setBoolean(target, 'runtimeMetricsRuntimeId', DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED)
|
|
715
|
-
setArray(target, 'sampler.spanSamplingRules', reformatSpanSamplingRules(
|
|
716
|
-
maybeJsonFile(DD_SPAN_SAMPLING_RULES_FILE) ??
|
|
717
|
-
safeJsonParse(DD_SPAN_SAMPLING_RULES)
|
|
718
|
-
))
|
|
719
|
-
setUnit(
|
|
720
|
-
target,
|
|
721
|
-
'sampleRate',
|
|
722
|
-
DD_TRACE_SAMPLE_RATE || getFromOtelSamplerMap(OTEL_TRACES_SAMPLER, OTEL_TRACES_SAMPLER_ARG)
|
|
723
|
-
)
|
|
724
|
-
target['sampler.rateLimit'] = DD_TRACE_RATE_LIMIT
|
|
725
|
-
setSamplingRule(target, 'sampler.rules', safeJsonParse(DD_TRACE_SAMPLING_RULES))
|
|
726
|
-
unprocessedTarget['sampler.rules'] = DD_TRACE_SAMPLING_RULES
|
|
727
|
-
setString(target, 'scope', DD_TRACE_SCOPE)
|
|
728
|
-
// Priority:
|
|
729
|
-
// DD_SERVICE > tags.service > OTEL_SERVICE_NAME > NX_TASK_TARGET_PROJECT (if DD_ENABLE_NX_SERVICE_NAME) > default
|
|
730
|
-
let serviceName = DD_SERVICE || tags.service || OTEL_SERVICE_NAME
|
|
731
|
-
let isServiceNameInferred
|
|
732
|
-
if (!serviceName && NX_TASK_TARGET_PROJECT) {
|
|
733
|
-
if (isTrue(DD_ENABLE_NX_SERVICE_NAME)) {
|
|
734
|
-
isServiceNameInferred = true
|
|
735
|
-
serviceName = NX_TASK_TARGET_PROJECT
|
|
736
|
-
} else if (DD_MAJOR < 6) {
|
|
737
|
-
// Warn about v6 behavior change for Nx projects
|
|
738
|
-
log.warn(
|
|
739
|
-
// eslint-disable-next-line @stylistic/max-len
|
|
740
|
-
'NX_TASK_TARGET_PROJECT is set but no service name was configured. In v6, NX_TASK_TARGET_PROJECT will be used as the default service name. Set DD_ENABLE_NX_SERVICE_NAME=true to opt-in to this behavior now, or set a service name explicitly.'
|
|
741
|
-
)
|
|
446
|
+
|
|
447
|
+
if (this.DD_SPAN_SAMPLING_RULES_FILE) {
|
|
448
|
+
try {
|
|
449
|
+
// TODO: Should we log a warning in case this is defined next to spanSamplingRules?
|
|
450
|
+
setAndTrack(this, 'spanSamplingRules', transformers.toCamelCase(JSON.parse(this.DD_SPAN_SAMPLING_RULES_FILE)))
|
|
451
|
+
} catch (error) {
|
|
452
|
+
log.warn('Error reading span sampling rules file %s; %o', this.DD_SPAN_SAMPLING_RULES_FILE, error)
|
|
742
453
|
}
|
|
743
454
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
setString(target, 'site', DD_SITE)
|
|
752
|
-
if (DD_TRACE_SPAN_ATTRIBUTE_SCHEMA) {
|
|
753
|
-
setString(target, 'spanAttributeSchema', validateNamingVersion(DD_TRACE_SPAN_ATTRIBUTE_SCHEMA))
|
|
754
|
-
unprocessedTarget.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
|
|
755
|
-
}
|
|
756
|
-
// 0: disabled, 1: logging, 2: garbage collection + logging
|
|
757
|
-
target.spanLeakDebug = maybeInt(DD_TRACE_SPAN_LEAK_DEBUG)
|
|
758
|
-
setBoolean(target, 'spanRemoveIntegrationFromService', DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED)
|
|
759
|
-
setBoolean(target, 'startupLogs', DD_TRACE_STARTUP_LOGS)
|
|
760
|
-
setTags(target, 'tags', tags)
|
|
761
|
-
target.tagsHeaderMaxLength = DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH
|
|
762
|
-
setBoolean(target, 'telemetry.enabled', DD_INSTRUMENTATION_TELEMETRY_ENABLED)
|
|
763
|
-
setString(target, 'instrumentation_config_id', DD_INSTRUMENTATION_CONFIG_ID)
|
|
764
|
-
setBoolean(target, 'telemetry.debug', DD_TELEMETRY_DEBUG)
|
|
765
|
-
setBoolean(target, 'telemetry.dependencyCollection', DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED)
|
|
766
|
-
target['telemetry.heartbeatInterval'] = maybeInt(Math.floor(DD_TELEMETRY_HEARTBEAT_INTERVAL * 1000))
|
|
767
|
-
unprocessedTarget['telemetry.heartbeatInterval'] = DD_TELEMETRY_HEARTBEAT_INTERVAL
|
|
768
|
-
setBoolean(target, 'telemetry.logCollection', DD_TELEMETRY_LOG_COLLECTION_ENABLED)
|
|
769
|
-
setBoolean(target, 'telemetry.metrics', DD_TELEMETRY_METRICS_ENABLED)
|
|
770
|
-
setBoolean(target, 'isKeepingCoverageConfiguration', DD_TEST_TIA_KEEP_COV_CONFIG)
|
|
771
|
-
setBoolean(target, 'traceId128BitGenerationEnabled', DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
|
|
772
|
-
setBoolean(target, 'traceId128BitLoggingEnabled', DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
|
|
773
|
-
warnIfPropagationStyleConflict(
|
|
774
|
-
DD_TRACE_PROPAGATION_STYLE,
|
|
775
|
-
DD_TRACE_PROPAGATION_STYLE_INJECT,
|
|
776
|
-
DD_TRACE_PROPAGATION_STYLE_EXTRACT
|
|
777
|
-
)
|
|
778
|
-
if (DD_TRACE_PROPAGATION_STYLE !== undefined) {
|
|
779
|
-
setArray(target, 'tracePropagationStyle.inject', normalizePropagationStyle(DD_TRACE_PROPAGATION_STYLE))
|
|
780
|
-
setArray(target, 'tracePropagationStyle.extract', normalizePropagationStyle(DD_TRACE_PROPAGATION_STYLE))
|
|
781
|
-
}
|
|
782
|
-
if (DD_TRACE_PROPAGATION_STYLE_INJECT !== undefined) {
|
|
783
|
-
setArray(target, 'tracePropagationStyle.inject',
|
|
784
|
-
normalizePropagationStyle(DD_TRACE_PROPAGATION_STYLE_INJECT))
|
|
455
|
+
|
|
456
|
+
// All sampler options are tracked as individual values. No need to track the sampler object as a whole.
|
|
457
|
+
this.sampler = {
|
|
458
|
+
rules: this.samplingRules,
|
|
459
|
+
rateLimit: this.rateLimit,
|
|
460
|
+
sampleRate: this.sampleRate,
|
|
461
|
+
spanSamplingRules: this.spanSamplingRules,
|
|
785
462
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
463
|
+
|
|
464
|
+
// For LLMObs, we want to auto enable it when other llmobs options are defined.
|
|
465
|
+
if (!this.llmobs.enabled &&
|
|
466
|
+
!trackedConfigOrigins.has('llmobs.enabled') &&
|
|
467
|
+
(trackedConfigOrigins.has('llmobs.agentlessEnabled') ||
|
|
468
|
+
trackedConfigOrigins.has('llmobs.mlApp'))) {
|
|
469
|
+
setAndTrack(this, 'llmobs.enabled', true)
|
|
789
470
|
}
|
|
790
|
-
|
|
791
|
-
if (
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
471
|
+
|
|
472
|
+
if (this.OTEL_RESOURCE_ATTRIBUTES) {
|
|
473
|
+
for (const [key, value] of Object.entries(this.OTEL_RESOURCE_ATTRIBUTES)) {
|
|
474
|
+
// Not replacing existing tags keeps the order of the tags as before.
|
|
475
|
+
if (!this.tags[key]) {
|
|
476
|
+
this.tags[key] = value
|
|
477
|
+
}
|
|
478
|
+
}
|
|
797
479
|
}
|
|
798
|
-
if (
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
setBoolean(target, 'tracePropagationStyle.otelPropagators',
|
|
807
|
-
useDdStyle ? false : !!OTEL_PROPAGATORS)
|
|
808
|
-
|
|
809
|
-
// Use OTEL_PROPAGATORS if no DD-specific vars are set
|
|
810
|
-
if (!useDdStyle && OTEL_PROPAGATORS) {
|
|
811
|
-
const otelStyles = normalizePropagationStyle(OTEL_PROPAGATORS)
|
|
812
|
-
// Validate OTEL propagators
|
|
813
|
-
for (const style of otelStyles || []) {
|
|
814
|
-
if (!VALID_PROPAGATION_STYLES.has(style)) {
|
|
815
|
-
log.warn('unexpected value %s for OTEL_PROPAGATORS environment variable', style)
|
|
816
|
-
getCounter('otel.env.invalid', 'DD_TRACE_PROPAGATION_STYLE', 'OTEL_PROPAGATORS').inc()
|
|
480
|
+
if (this.DD_TRACE_TAGS) {
|
|
481
|
+
// TODO: This is a hack to keep the order of the tags as before.
|
|
482
|
+
// That hack is not sufficient, since it does not handle other cases where the tags are set by the user.
|
|
483
|
+
if (trackedConfigOrigins.get('tags') === 'code') {
|
|
484
|
+
for (const [key, value] of Object.entries(this.DD_TRACE_TAGS)) {
|
|
485
|
+
// Not replacing existing tags keeps the order of the tags as before.
|
|
486
|
+
if (!this.tags[key]) {
|
|
487
|
+
this.tags[key] = value
|
|
817
488
|
}
|
|
818
489
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
setArray(target, 'tracePropagationStyle.inject', otelStyles)
|
|
822
|
-
setArray(target, 'tracePropagationStyle.extract', otelStyles)
|
|
823
|
-
}
|
|
490
|
+
} else {
|
|
491
|
+
Object.assign(this.tags, this.DD_TRACE_TAGS)
|
|
824
492
|
}
|
|
825
493
|
}
|
|
826
|
-
setBoolean(target, 'traceWebsocketMessagesEnabled', DD_TRACE_WEBSOCKET_MESSAGES_ENABLED)
|
|
827
|
-
setBoolean(target, 'traceWebsocketMessagesInheritSampling', DD_TRACE_WEBSOCKET_MESSAGES_INHERIT_SAMPLING)
|
|
828
|
-
setBoolean(target, 'traceWebsocketMessagesSeparateTraces', DD_TRACE_WEBSOCKET_MESSAGES_SEPARATE_TRACES)
|
|
829
|
-
setBoolean(target, 'tracing', DD_TRACING_ENABLED)
|
|
830
|
-
setString(target, 'version', DD_VERSION || tags.version)
|
|
831
|
-
setBoolean(target, 'inferredProxyServicesEnabled', DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED)
|
|
832
|
-
setBoolean(target, 'trace.aws.addSpanPointers', DD_TRACE_AWS_ADD_SPAN_POINTERS)
|
|
833
|
-
setString(target, 'trace.dynamoDb.tablePrimaryKeys', DD_TRACE_DYNAMODB_TABLE_PRIMARY_KEYS)
|
|
834
|
-
setArray(target, 'graphqlErrorExtensions', DD_TRACE_GRAPHQL_ERROR_EXTENSIONS)
|
|
835
|
-
setBoolean(target, 'trace.nativeSpanEvents', DD_TRACE_NATIVE_SPAN_EVENTS)
|
|
836
|
-
target['vertexai.spanPromptCompletionSampleRate'] = maybeFloat(DD_VERTEXAI_SPAN_PROMPT_COMPLETION_SAMPLE_RATE)
|
|
837
|
-
target['vertexai.spanCharLimit'] = maybeInt(DD_VERTEXAI_SPAN_CHAR_LIMIT)
|
|
838
|
-
}
|
|
839
494
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
const tags = {}
|
|
843
|
-
|
|
844
|
-
options = this.#optionsArg = { ingestion: {}, ...options, ...opts }
|
|
845
|
-
|
|
846
|
-
tagger.add(tags, options.tags)
|
|
847
|
-
|
|
848
|
-
setBoolean(opts, 'apmTracingEnabled', options.apmTracingEnabled ??
|
|
849
|
-
(options.experimental?.appsec?.standalone && !options.experimental.appsec.standalone.enabled)
|
|
850
|
-
)
|
|
851
|
-
setBoolean(opts, 'appsec.apiSecurity.enabled', options.appsec?.apiSecurity?.enabled)
|
|
852
|
-
setBoolean(opts, 'appsec.apiSecurity.endpointCollectionEnabled',
|
|
853
|
-
options.appsec?.apiSecurity?.endpointCollectionEnabled)
|
|
854
|
-
opts['appsec.apiSecurity.endpointCollectionMessageLimit'] =
|
|
855
|
-
maybeInt(options.appsec?.apiSecurity?.endpointCollectionMessageLimit)
|
|
856
|
-
opts['appsec.blockedTemplateGraphql'] = maybeFile(options.appsec?.blockedTemplateGraphql)
|
|
857
|
-
opts['appsec.blockedTemplateHtml'] = maybeFile(options.appsec?.blockedTemplateHtml)
|
|
858
|
-
this.#optsUnprocessed['appsec.blockedTemplateHtml'] = options.appsec?.blockedTemplateHtml
|
|
859
|
-
opts['appsec.blockedTemplateJson'] = maybeFile(options.appsec?.blockedTemplateJson)
|
|
860
|
-
this.#optsUnprocessed['appsec.blockedTemplateJson'] = options.appsec?.blockedTemplateJson
|
|
861
|
-
setBoolean(opts, 'appsec.enabled', options.appsec?.enabled)
|
|
862
|
-
setString(opts, 'appsec.eventTracking.mode', options.appsec?.eventTracking?.mode)
|
|
863
|
-
setBoolean(
|
|
864
|
-
opts,
|
|
865
|
-
'appsec.extendedHeadersCollection.enabled',
|
|
866
|
-
options.appsec?.extendedHeadersCollection?.enabled
|
|
867
|
-
)
|
|
868
|
-
setBoolean(
|
|
869
|
-
opts,
|
|
870
|
-
'appsec.extendedHeadersCollection.redaction',
|
|
871
|
-
options.appsec?.extendedHeadersCollection?.redaction
|
|
872
|
-
)
|
|
873
|
-
opts['appsec.extendedHeadersCollection.maxHeaders'] = options.appsec?.extendedHeadersCollection?.maxHeaders
|
|
874
|
-
setString(opts, 'appsec.obfuscatorKeyRegex', options.appsec?.obfuscatorKeyRegex)
|
|
875
|
-
setString(opts, 'appsec.obfuscatorValueRegex', options.appsec?.obfuscatorValueRegex)
|
|
876
|
-
setBoolean(opts, 'appsec.rasp.enabled', options.appsec?.rasp?.enabled)
|
|
877
|
-
setBoolean(opts, 'appsec.rasp.bodyCollection', options.appsec?.rasp?.bodyCollection)
|
|
878
|
-
opts['appsec.rateLimit'] = maybeInt(options.appsec?.rateLimit)
|
|
879
|
-
this.#optsUnprocessed['appsec.rateLimit'] = options.appsec?.rateLimit
|
|
880
|
-
setString(opts, 'appsec.rules', options.appsec?.rules)
|
|
881
|
-
setBoolean(opts, 'appsec.stackTrace.enabled', options.appsec?.stackTrace?.enabled)
|
|
882
|
-
opts['appsec.stackTrace.maxDepth'] = maybeInt(options.appsec?.stackTrace?.maxDepth)
|
|
883
|
-
this.#optsUnprocessed['appsec.stackTrace.maxDepth'] = options.appsec?.stackTrace?.maxDepth
|
|
884
|
-
opts['appsec.stackTrace.maxStackTraces'] = maybeInt(options.appsec?.stackTrace?.maxStackTraces)
|
|
885
|
-
this.#optsUnprocessed['appsec.stackTrace.maxStackTraces'] = options.appsec?.stackTrace?.maxStackTraces
|
|
886
|
-
opts['appsec.wafTimeout'] = maybeInt(options.appsec?.wafTimeout)
|
|
887
|
-
this.#optsUnprocessed['appsec.wafTimeout'] = options.appsec?.wafTimeout
|
|
888
|
-
setBoolean(opts, 'clientIpEnabled', options.clientIpEnabled)
|
|
889
|
-
setString(opts, 'clientIpHeader', options.clientIpHeader?.toLowerCase())
|
|
890
|
-
if (options.cloudPayloadTagging?.request || options.cloudPayloadTagging?.response) {
|
|
891
|
-
if (options.cloudPayloadTagging.request) {
|
|
892
|
-
setBoolean(opts, 'cloudPayloadTagging.requestsEnabled', true)
|
|
893
|
-
}
|
|
894
|
-
if (options.cloudPayloadTagging.response) {
|
|
895
|
-
setBoolean(opts, 'cloudPayloadTagging.responsesEnabled', true)
|
|
896
|
-
}
|
|
897
|
-
opts['cloudPayloadTagging.rules'] = appendRules(
|
|
898
|
-
splitJSONPathRules(options.cloudPayloadTagging.request),
|
|
899
|
-
splitJSONPathRules(options.cloudPayloadTagging.response)
|
|
900
|
-
)
|
|
901
|
-
}
|
|
902
|
-
if (options.cloudPayloadTagging?.requestsEnabled !== undefined) {
|
|
903
|
-
setBoolean(opts, 'cloudPayloadTagging.requestsEnabled', options.cloudPayloadTagging.requestsEnabled)
|
|
904
|
-
}
|
|
905
|
-
if (options.cloudPayloadTagging?.responsesEnabled !== undefined) {
|
|
906
|
-
setBoolean(opts, 'cloudPayloadTagging.responsesEnabled', options.cloudPayloadTagging.responsesEnabled)
|
|
907
|
-
}
|
|
908
|
-
opts['cloudPayloadTagging.maxDepth'] = maybeInt(options.cloudPayloadTagging?.maxDepth)
|
|
909
|
-
opts.baggageMaxBytes = options.baggageMaxBytes
|
|
910
|
-
opts.baggageMaxItems = options.baggageMaxItems
|
|
911
|
-
setArray(opts, 'baggageTagKeys', options.baggageTagKeys)
|
|
912
|
-
setBoolean(opts, 'codeOriginForSpans.enabled', options.codeOriginForSpans?.enabled)
|
|
913
|
-
setBoolean(
|
|
914
|
-
opts,
|
|
915
|
-
'codeOriginForSpans.experimental.exit_spans.enabled',
|
|
916
|
-
options.codeOriginForSpans?.experimental?.exit_spans?.enabled
|
|
917
|
-
)
|
|
918
|
-
setString(opts, 'dbmPropagationMode', options.dbmPropagationMode)
|
|
919
|
-
setBoolean(opts, 'dbm.injectSqlBaseHash', options.dbm?.injectSqlBaseHash)
|
|
920
|
-
if (options.dogstatsd) {
|
|
921
|
-
setString(opts, 'dogstatsd.hostname', options.dogstatsd.hostname)
|
|
922
|
-
setString(opts, 'dogstatsd.port', options.dogstatsd.port)
|
|
495
|
+
if (!this.#parsedDdTags) {
|
|
496
|
+
this.#parsedDdTags = rfdc(this.tags)
|
|
923
497
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
setBoolean(opts, 'dynamicInstrumentation.enabled', options.dynamicInstrumentation?.enabled)
|
|
928
|
-
setString(opts, 'dynamicInstrumentation.probeFile', options.dynamicInstrumentation?.probeFile)
|
|
929
|
-
setArray(
|
|
930
|
-
opts,
|
|
931
|
-
'dynamicInstrumentation.redactedIdentifiers',
|
|
932
|
-
options.dynamicInstrumentation?.redactedIdentifiers
|
|
933
|
-
)
|
|
934
|
-
setArray(
|
|
935
|
-
opts,
|
|
936
|
-
'dynamicInstrumentation.redactionExcludedIdentifiers',
|
|
937
|
-
options.dynamicInstrumentation?.redactionExcludedIdentifiers
|
|
938
|
-
)
|
|
939
|
-
opts['dynamicInstrumentation.uploadIntervalSeconds'] =
|
|
940
|
-
maybeFloat(options.dynamicInstrumentation?.uploadIntervalSeconds)
|
|
941
|
-
this.#optsUnprocessed['dynamicInstrumentation.uploadIntervalSeconds'] =
|
|
942
|
-
options.dynamicInstrumentation?.uploadIntervalSeconds
|
|
943
|
-
setString(opts, 'env', options.env || tags.env)
|
|
944
|
-
setBoolean(opts, 'experimental.aiguard.block', options.experimental?.aiguard?.block)
|
|
945
|
-
setBoolean(opts, 'experimental.aiguard.enabled', options.experimental?.aiguard?.enabled)
|
|
946
|
-
setString(opts, 'experimental.aiguard.endpoint', options.experimental?.aiguard?.endpoint)
|
|
947
|
-
opts['experimental.aiguard.maxMessagesLength'] = maybeInt(options.experimental?.aiguard?.maxMessagesLength)
|
|
948
|
-
this.#optsUnprocessed['experimental.aiguard.maxMessagesLength'] = options.experimental?.aiguard?.maxMessagesLength
|
|
949
|
-
opts['experimental.aiguard.maxContentSize'] = maybeInt(options.experimental?.aiguard?.maxContentSize)
|
|
950
|
-
this.#optsUnprocessed['experimental.aiguard.maxContentSize'] = options.experimental?.aiguard?.maxContentSize
|
|
951
|
-
opts['experimental.aiguard.timeout'] = maybeInt(options.experimental?.aiguard?.timeout)
|
|
952
|
-
this.#optsUnprocessed['experimental.aiguard.timeout'] = options.experimental?.aiguard?.timeout
|
|
953
|
-
setBoolean(opts, 'experimental.enableGetRumData', options.experimental?.enableGetRumData)
|
|
954
|
-
setString(opts, 'experimental.exporter', options.experimental?.exporter)
|
|
955
|
-
setBoolean(opts, 'experimental.flaggingProvider.enabled', options.experimental?.flaggingProvider?.enabled)
|
|
956
|
-
opts['experimental.flaggingProvider.initializationTimeoutMs'] = maybeInt(
|
|
957
|
-
options.experimental?.flaggingProvider?.initializationTimeoutMs
|
|
958
|
-
)
|
|
959
|
-
this.#optsUnprocessed['experimental.flaggingProvider.initializationTimeoutMs'] =
|
|
960
|
-
options.experimental?.flaggingProvider?.initializationTimeoutMs
|
|
961
|
-
opts.flushInterval = maybeInt(options.flushInterval)
|
|
962
|
-
this.#optsUnprocessed.flushInterval = options.flushInterval
|
|
963
|
-
opts.flushMinSpans = maybeInt(options.flushMinSpans)
|
|
964
|
-
this.#optsUnprocessed.flushMinSpans = options.flushMinSpans
|
|
965
|
-
setArray(opts, 'headerTags', options.headerTags)
|
|
966
|
-
setString(opts, 'hostname', options.hostname)
|
|
967
|
-
opts['iast.dbRowsToTaint'] = maybeInt(options.iast?.dbRowsToTaint)
|
|
968
|
-
setBoolean(opts, 'iast.deduplicationEnabled', options.iast && options.iast.deduplicationEnabled)
|
|
969
|
-
setBoolean(opts, 'iast.enabled',
|
|
970
|
-
options.iast && (options.iast === true || options.iast.enabled === true))
|
|
971
|
-
opts['iast.maxConcurrentRequests'] = maybeInt(options.iast?.maxConcurrentRequests)
|
|
972
|
-
this.#optsUnprocessed['iast.maxConcurrentRequests'] = options.iast?.maxConcurrentRequests
|
|
973
|
-
opts['iast.maxContextOperations'] = maybeInt(options.iast?.maxContextOperations)
|
|
974
|
-
this.#optsUnprocessed['iast.maxContextOperations'] = options.iast?.maxContextOperations
|
|
975
|
-
setBoolean(opts, 'iast.redactionEnabled', options.iast?.redactionEnabled)
|
|
976
|
-
setString(opts, 'iast.redactionNamePattern', options.iast?.redactionNamePattern)
|
|
977
|
-
setString(opts, 'iast.redactionValuePattern', options.iast?.redactionValuePattern)
|
|
978
|
-
const iastRequestSampling = maybeInt(options.iast?.requestSampling)
|
|
979
|
-
if (iastRequestSampling !== undefined && iastRequestSampling > -1 && iastRequestSampling < 101) {
|
|
980
|
-
opts['iast.requestSampling'] = iastRequestSampling
|
|
981
|
-
this.#optsUnprocessed['iast.requestSampling'] = options.iast?.requestSampling
|
|
982
|
-
}
|
|
983
|
-
if (DD_MAJOR < 6) {
|
|
984
|
-
opts['iast.securityControlsConfiguration'] = options.iast?.securityControlsConfiguration
|
|
498
|
+
|
|
499
|
+
if (!this.env && this.tags.env !== undefined) {
|
|
500
|
+
setAndTrack(this, 'env', this.tags.env)
|
|
985
501
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
setBoolean(opts, 'llmobs.agentlessEnabled', options.llmobs?.agentlessEnabled)
|
|
991
|
-
setString(opts, 'llmobs.mlApp', options.llmobs?.mlApp)
|
|
992
|
-
setBoolean(opts, 'logInjection', options.logInjection)
|
|
993
|
-
opts.lookup = options.lookup
|
|
994
|
-
setBoolean(opts, 'middlewareTracingEnabled', options.middlewareTracingEnabled)
|
|
995
|
-
setBoolean(opts, 'openAiLogsEnabled', options.openAiLogsEnabled)
|
|
996
|
-
opts.peerServiceMapping = options.peerServiceMapping
|
|
997
|
-
setBoolean(opts, 'plugins', options.plugins)
|
|
998
|
-
setString(opts, 'port', options.port)
|
|
999
|
-
const strProfiling = String(options.profiling)
|
|
1000
|
-
if (['true', 'false', 'auto'].includes(strProfiling)) {
|
|
1001
|
-
setString(opts, 'profiling.enabled', strProfiling)
|
|
502
|
+
|
|
503
|
+
if (!this.version) {
|
|
504
|
+
setAndTrack(this, 'version', this.tags.version || pkg.version)
|
|
505
|
+
this.tags.version ??= pkg.version
|
|
1002
506
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
this
|
|
507
|
+
|
|
508
|
+
let isServiceNameInferred = false
|
|
509
|
+
if (!trackedConfigOrigins.has('service')) {
|
|
510
|
+
if (this.tags.service) {
|
|
511
|
+
setAndTrack(this, 'service', this.tags.service)
|
|
512
|
+
} else {
|
|
513
|
+
const NX_TASK_TARGET_PROJECT = getEnvironmentVariable('NX_TASK_TARGET_PROJECT')
|
|
514
|
+
if (NX_TASK_TARGET_PROJECT) {
|
|
515
|
+
if (this.DD_ENABLE_NX_SERVICE_NAME) {
|
|
516
|
+
setAndTrack(this, 'service', NX_TASK_TARGET_PROJECT)
|
|
517
|
+
isServiceNameInferred = true
|
|
518
|
+
} else if (DD_MAJOR < 6) {
|
|
519
|
+
log.warn(
|
|
520
|
+
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
521
|
+
'NX_TASK_TARGET_PROJECT is set but no service name was configured. In v6, NX_TASK_TARGET_PROJECT will ' +
|
|
522
|
+
'be used as the default service name. Set DD_ENABLE_NX_SERVICE_NAME=true to opt-in to this behavior ' +
|
|
523
|
+
'now, or set a service name explicitly.'
|
|
524
|
+
)
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (!this.service) {
|
|
530
|
+
const serverlessName = IS_SERVERLESS
|
|
531
|
+
? (
|
|
532
|
+
getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') ||
|
|
533
|
+
getEnvironmentVariable('FUNCTION_NAME') || // Google Cloud Function Name set by deprecated runtimes
|
|
534
|
+
getEnvironmentVariable('K_SERVICE') || // Google Cloud Function Name set by newer runtimes
|
|
535
|
+
getEnvironmentVariable('WEBSITE_SITE_NAME') // set by Azure Functions
|
|
536
|
+
)
|
|
537
|
+
: undefined
|
|
538
|
+
|
|
539
|
+
setAndTrack(this, 'service', serverlessName || pkg.name || 'node')
|
|
540
|
+
this.tags.service ??= /** @type {string} */ (this.service)
|
|
541
|
+
isServiceNameInferred = true
|
|
542
|
+
}
|
|
1007
543
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
setArray(opts, 'sampler.spanSamplingRules', reformatSpanSamplingRules(options.spanSamplingRules))
|
|
1014
|
-
setUnit(opts, 'sampleRate', options.sampleRate ?? options.ingestion.sampleRate)
|
|
1015
|
-
opts['sampler.rateLimit'] = maybeInt(options.rateLimit ?? options.ingestion.rateLimit)
|
|
1016
|
-
setSamplingRule(opts, 'sampler.rules', options.samplingRules)
|
|
1017
|
-
const optService = options.service || tags.service
|
|
1018
|
-
setString(opts, 'service', optService)
|
|
1019
|
-
if (optService) {
|
|
1020
|
-
setBoolean(opts, 'isServiceNameInferred', false)
|
|
544
|
+
setAndTrack(this, 'isServiceNameInferred', isServiceNameInferred)
|
|
545
|
+
|
|
546
|
+
// Add missing tags, in case they are defined otherwise.
|
|
547
|
+
if (this.service) {
|
|
548
|
+
this.tags.service = this.service
|
|
1021
549
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
if (options.spanAttributeSchema) {
|
|
1025
|
-
setString(opts, 'spanAttributeSchema', validateNamingVersion(options.spanAttributeSchema))
|
|
1026
|
-
this.#optsUnprocessed.spanAttributeSchema = options.spanAttributeSchema
|
|
550
|
+
if (this.env) {
|
|
551
|
+
this.tags.env = this.env
|
|
1027
552
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
setTags(opts, 'tags', tags)
|
|
1031
|
-
setBoolean(opts, 'traceId128BitGenerationEnabled', options.traceId128BitGenerationEnabled)
|
|
1032
|
-
setBoolean(opts, 'traceId128BitLoggingEnabled', options.traceId128BitLoggingEnabled)
|
|
1033
|
-
setBoolean(opts, 'traceWebsocketMessagesEnabled', options.traceWebsocketMessagesEnabled)
|
|
1034
|
-
setBoolean(opts, 'traceWebsocketMessagesInheritSampling', options.traceWebsocketMessagesInheritSampling)
|
|
1035
|
-
setBoolean(opts, 'traceWebsocketMessagesSeparateTraces', options.traceWebsocketMessagesSeparateTraces)
|
|
1036
|
-
setString(opts, 'version', options.version || tags.version)
|
|
1037
|
-
setBoolean(opts, 'inferredProxyServicesEnabled', options.inferredProxyServicesEnabled)
|
|
1038
|
-
setBoolean(opts, 'graphqlErrorExtensions', options.graphqlErrorExtensions)
|
|
1039
|
-
setBoolean(opts, 'trace.nativeSpanEvents', options.trace?.nativeSpanEvents)
|
|
1040
|
-
if (options.tracePropagationStyle) {
|
|
1041
|
-
setArray(opts, 'tracePropagationStyle.inject',
|
|
1042
|
-
normalizePropagationStyle(options.tracePropagationStyle.inject ?? options.tracePropagationStyle))
|
|
1043
|
-
setArray(opts, 'tracePropagationStyle.extract',
|
|
1044
|
-
normalizePropagationStyle(options.tracePropagationStyle.extract ?? options.tracePropagationStyle))
|
|
553
|
+
if (this.version) {
|
|
554
|
+
this.tags.version = this.version
|
|
1045
555
|
}
|
|
556
|
+
this.tags['runtime-id'] = RUNTIME_ID
|
|
1046
557
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
if (this.#env['llmobs.enabled'] == null && options.llmobs) {
|
|
1052
|
-
setBoolean(opts, 'llmobs.enabled', true)
|
|
558
|
+
if (IS_SERVERLESS) {
|
|
559
|
+
setAndTrack(this, 'telemetry.enabled', false)
|
|
560
|
+
setAndTrack(this, 'crashtracking.enabled', false)
|
|
561
|
+
setAndTrack(this, 'remoteConfig.enabled', false)
|
|
1053
562
|
}
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
#isCiVisibility () {
|
|
1057
|
-
return this.#optionsArg.isCiVisibility ?? this.#defaults.isCiVisibility
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
#getHostname () {
|
|
1061
|
-
const DD_CIVISIBILITY_AGENTLESS_URL = getEnv('DD_CIVISIBILITY_AGENTLESS_URL')
|
|
1062
|
-
const url = DD_CIVISIBILITY_AGENTLESS_URL
|
|
1063
|
-
? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
|
|
1064
|
-
: getAgentUrl(this.#getTraceAgentUrl(), this.#optionsArg)
|
|
1065
|
-
const DD_AGENT_HOST = this.#optionsArg.hostname ??
|
|
1066
|
-
getEnv('DD_AGENT_HOST') ??
|
|
1067
|
-
defaults.hostname
|
|
1068
|
-
return DD_AGENT_HOST || url?.hostname
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
#getSpanComputePeerService () {
|
|
1072
|
-
const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
|
|
1073
|
-
this.#optionsArg.spanAttributeSchema ??
|
|
1074
|
-
getEnv('DD_TRACE_SPAN_ATTRIBUTE_SCHEMA')
|
|
1075
|
-
)
|
|
1076
|
-
|
|
1077
|
-
const peerServiceSet = (
|
|
1078
|
-
this.#optionsArg.hasOwnProperty('spanComputePeerService') ||
|
|
1079
|
-
getEnv('DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED') !== undefined
|
|
1080
|
-
)
|
|
1081
|
-
const peerServiceValue = this.#optionsArg.spanComputePeerService ??
|
|
1082
|
-
getEnv('DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED')
|
|
1083
|
-
|
|
1084
|
-
const spanComputePeerService = (
|
|
1085
|
-
DD_TRACE_SPAN_ATTRIBUTE_SCHEMA === 'v0'
|
|
1086
|
-
// In v0, peer service is computed only if it is explicitly set to true
|
|
1087
|
-
? peerServiceSet && isTrue(peerServiceValue)
|
|
1088
|
-
// In >v0, peer service is false only if it is explicitly set to false
|
|
1089
|
-
: (peerServiceSet ? !isFalse(peerServiceValue) : true)
|
|
1090
|
-
)
|
|
1091
|
-
|
|
1092
|
-
return spanComputePeerService
|
|
1093
|
-
}
|
|
1094
563
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
this
|
|
1098
|
-
|
|
1099
|
-
return apmTracingEnabled && (
|
|
1100
|
-
this.#optionsArg.stats ??
|
|
1101
|
-
getEnv('DD_TRACE_STATS_COMPUTATION_ENABLED') ??
|
|
1102
|
-
(getIsGCPFunction() || getIsAzureFunction())
|
|
1103
|
-
)
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
#getTraceAgentUrl () {
|
|
1107
|
-
return this.#optionsArg.url ??
|
|
1108
|
-
getEnv('DD_TRACE_AGENT_URL') ??
|
|
1109
|
-
null
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
// handles values calculated from a mixture of options and env vars
|
|
1113
|
-
#applyCalculated () {
|
|
1114
|
-
const calc = this.#calculated
|
|
1115
|
-
|
|
1116
|
-
const DD_CIVISIBILITY_AGENTLESS_URL = getEnv('DD_CIVISIBILITY_AGENTLESS_URL')
|
|
1117
|
-
|
|
1118
|
-
calc.url = DD_CIVISIBILITY_AGENTLESS_URL
|
|
1119
|
-
? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
|
|
1120
|
-
: getAgentUrl(this.#getTraceAgentUrl(), this.#optionsArg)
|
|
564
|
+
// TODO: Should this unconditionally be disabled?
|
|
565
|
+
if (getEnvironmentVariable('JEST_WORKER_ID') && !trackedConfigOrigins.has('telemetry.enabled')) {
|
|
566
|
+
setAndTrack(this, 'telemetry.enabled', false)
|
|
567
|
+
}
|
|
1121
568
|
|
|
1122
569
|
// Experimental agentless APM span intake
|
|
1123
570
|
// When enabled, sends spans directly to Datadog intake without an agent
|
|
1124
|
-
|
|
571
|
+
// TODO: Replace this with a proper configuration
|
|
572
|
+
const agentlessEnabled = isTrue(getEnvironmentVariable('_DD_APM_TRACING_AGENTLESS_ENABLED'))
|
|
1125
573
|
if (agentlessEnabled) {
|
|
1126
|
-
|
|
1127
|
-
// Disable rate limiting - server-side sampling will be used
|
|
1128
|
-
calc['sampler.rateLimit'] = -1
|
|
574
|
+
setAndTrack(this, 'experimental.exporter', 'agentless')
|
|
1129
575
|
// Disable client-side stats computation
|
|
1130
|
-
|
|
576
|
+
setAndTrack(this, 'stats.enabled', false)
|
|
1131
577
|
// Enable hostname reporting
|
|
1132
|
-
|
|
578
|
+
setAndTrack(this, 'reportHostname', true)
|
|
579
|
+
// Disable rate limiting - server-side sampling will be used
|
|
580
|
+
setAndTrack(this, 'sampler.rateLimit', -1)
|
|
1133
581
|
// Clear sampling rules - server-side sampling handles this
|
|
1134
|
-
|
|
582
|
+
setAndTrack(this, 'sampler.rules', [])
|
|
1135
583
|
// Agentless intake only accepts 64-bit trace IDs; disable 128-bit generation
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
if (this.#isCiVisibility()) {
|
|
1140
|
-
setBoolean(calc, 'isEarlyFlakeDetectionEnabled',
|
|
1141
|
-
getEnv('DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED') ?? true)
|
|
1142
|
-
setBoolean(calc, 'isFlakyTestRetriesEnabled', getEnv('DD_CIVISIBILITY_FLAKY_RETRY_ENABLED') ?? true)
|
|
1143
|
-
calc.flakyTestRetriesCount = maybeInt(getEnv('DD_CIVISIBILITY_FLAKY_RETRY_COUNT')) ?? 5
|
|
1144
|
-
setBoolean(calc, 'isIntelligentTestRunnerEnabled', isTrue(isCiVisibilityItrEnabled()))
|
|
1145
|
-
setBoolean(calc, 'isManualApiEnabled', !isFalse(getEnv('DD_CIVISIBILITY_MANUAL_API_ENABLED')))
|
|
1146
|
-
setString(calc, 'ciVisibilityTestSessionName', getEnv('DD_TEST_SESSION_NAME'))
|
|
1147
|
-
setBoolean(calc, 'ciVisAgentlessLogSubmissionEnabled',
|
|
1148
|
-
isTrue(getEnv('DD_AGENTLESS_LOG_SUBMISSION_ENABLED')))
|
|
1149
|
-
setBoolean(calc, 'isTestDynamicInstrumentationEnabled',
|
|
1150
|
-
!isFalse(getEnv('DD_TEST_FAILED_TEST_REPLAY_ENABLED')))
|
|
1151
|
-
setBoolean(calc, 'isServiceUserProvided', !!this.#env.service)
|
|
1152
|
-
setBoolean(calc, 'isTestManagementEnabled', !isFalse(getEnv('DD_TEST_MANAGEMENT_ENABLED')))
|
|
1153
|
-
calc.testManagementAttemptToFixRetries = maybeInt(getEnv('DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES')) ?? 20
|
|
1154
|
-
setBoolean(calc, 'isImpactedTestsEnabled',
|
|
1155
|
-
!isFalse(getEnv('DD_CIVISIBILITY_IMPACTED_TESTS_DETECTION_ENABLED')))
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
// Disable log injection when OTEL logs are enabled
|
|
1159
|
-
// OTEL logs and DD log injection are mutually exclusive
|
|
1160
|
-
if (this.#env.otelLogsEnabled) {
|
|
1161
|
-
setBoolean(calc, 'logInjection', false)
|
|
584
|
+
if (!trackedConfigOrigins.has('traceId128BitGenerationEnabled')) {
|
|
585
|
+
setAndTrack(this, 'traceId128BitGenerationEnabled', false)
|
|
586
|
+
}
|
|
1162
587
|
}
|
|
1163
588
|
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
calc.otelLogsUrl = `http://${agentHostname}:${DEFAULT_OTLP_PORT}`
|
|
1169
|
-
calc.otelMetricsUrl = `http://${agentHostname}:${DEFAULT_OTLP_PORT}/v1/metrics`
|
|
1170
|
-
calc.otelUrl = `http://${agentHostname}:${DEFAULT_OTLP_PORT}`
|
|
1171
|
-
calc['telemetry.heartbeatInterval'] = maybeInt(Math.floor(this.#defaults['telemetry.heartbeatInterval'] * 1000))
|
|
1172
|
-
|
|
1173
|
-
setBoolean(calc, 'isGitUploadEnabled',
|
|
1174
|
-
calc.isIntelligentTestRunnerEnabled && !isFalse(getEnv('DD_CIVISIBILITY_GIT_UPLOAD_ENABLED')))
|
|
1175
|
-
|
|
1176
|
-
// Enable resourceRenamingEnabled when appsec is enabled and only
|
|
1177
|
-
// if DD_TRACE_RESOURCE_RENAMING_ENABLED is not explicitly set
|
|
1178
|
-
if (this.#env.resourceRenamingEnabled === undefined) {
|
|
1179
|
-
const appsecEnabled = this.#options['appsec.enabled'] ?? this.#env['appsec.enabled']
|
|
1180
|
-
if (appsecEnabled) {
|
|
1181
|
-
setBoolean(calc, 'resourceRenamingEnabled', true)
|
|
589
|
+
// Apply all fallbacks to the calculated config.
|
|
590
|
+
for (const [configName, alias] of fallbackConfigurations) {
|
|
591
|
+
if (!trackedConfigOrigins.has(configName) && trackedConfigOrigins.has(alias)) {
|
|
592
|
+
setAndTrack(this, configName, this[alias])
|
|
1182
593
|
}
|
|
1183
594
|
}
|
|
1184
595
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
if (defaultPropagationStyle.length > 2) {
|
|
1189
|
-
// b3 was added, so update defaults to include it
|
|
1190
|
-
// This will only be used if no other source (options, env, stable config) set the value
|
|
1191
|
-
calc['tracePropagationStyle.inject'] = defaultPropagationStyle
|
|
1192
|
-
calc['tracePropagationStyle.extract'] = defaultPropagationStyle
|
|
596
|
+
const DEFAULT_OTLP_PORT = '4318'
|
|
597
|
+
if (!this.otelLogsUrl) {
|
|
598
|
+
setAndTrack(this, 'otelLogsUrl', `http://${agentHostname}:${DEFAULT_OTLP_PORT}`)
|
|
1193
599
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
/**
|
|
1197
|
-
* Applies remote configuration options from APM_TRACING configs.
|
|
1198
|
-
*
|
|
1199
|
-
* @param {import('./remote_config').RemoteConfigOptions} options - Configurations received via Remote Config
|
|
1200
|
-
*/
|
|
1201
|
-
#applyRemoteConfig (options) {
|
|
1202
|
-
const opts = this.#remote
|
|
1203
|
-
|
|
1204
|
-
setBoolean(opts, 'dynamicInstrumentation.enabled', options.dynamic_instrumentation_enabled)
|
|
1205
|
-
setBoolean(opts, 'codeOriginForSpans.enabled', options.code_origin_enabled)
|
|
1206
|
-
setUnit(opts, 'sampleRate', options.tracing_sampling_rate)
|
|
1207
|
-
setBoolean(opts, 'logInjection', options.log_injection_enabled)
|
|
1208
|
-
setBoolean(opts, 'tracing', options.tracing_enabled)
|
|
1209
|
-
this.#remoteUnprocessed['sampler.rules'] = options.tracing_sampling_rules
|
|
1210
|
-
setSamplingRule(opts, 'sampler.rules', reformatTagsFromRC(options.tracing_sampling_rules))
|
|
1211
|
-
|
|
1212
|
-
opts.headerTags = options.tracing_header_tags?.map(tag => {
|
|
1213
|
-
return tag.tag_name ? `${tag.header}:${tag.tag_name}` : tag.header
|
|
1214
|
-
})
|
|
1215
|
-
|
|
1216
|
-
const tags = {}
|
|
1217
|
-
tagger.add(tags, options.tracing_tags)
|
|
1218
|
-
if (Object.keys(tags).length) {
|
|
1219
|
-
tags['runtime-id'] = RUNTIME_ID
|
|
600
|
+
if (!this.otelMetricsUrl) {
|
|
601
|
+
setAndTrack(this, 'otelMetricsUrl', `http://${agentHostname}:${DEFAULT_OTLP_PORT}/v1/metrics`)
|
|
1220
602
|
}
|
|
1221
|
-
setTags(opts, 'tags', tags)
|
|
1222
|
-
}
|
|
1223
603
|
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
604
|
+
if (process.platform === 'win32') {
|
|
605
|
+
// OOM monitoring does not work properly on Windows, so it will be disabled.
|
|
606
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED')
|
|
607
|
+
// Profiler sampling contexts are not available on Windows, so features
|
|
608
|
+
// depending on those (code hotspots and endpoint collection) need to be disabled on Windows.
|
|
609
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_CODEHOTSPOTS_ENABLED')
|
|
610
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_ENDPOINT_COLLECTION_ENABLED')
|
|
611
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_CPU_ENABLED')
|
|
612
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_TIMELINE_ENABLED')
|
|
613
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED')
|
|
1229
614
|
}
|
|
1230
615
|
|
|
1231
|
-
|
|
1232
|
-
|
|
616
|
+
// Single tags update is tracked as a calculated value.
|
|
617
|
+
setAndTrack(this, 'tags', this.tags)
|
|
1233
618
|
|
|
1234
|
-
|
|
1235
|
-
changeTracker[name][origin] = value
|
|
1236
|
-
changes.push({
|
|
1237
|
-
name,
|
|
1238
|
-
value: unprocessedValue || value,
|
|
1239
|
-
origin,
|
|
1240
|
-
})
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
// TODO: Report origin changes and errors to telemetry.
|
|
1245
|
-
// TODO: Deeply merge configurations.
|
|
1246
|
-
// TODO: Move change tracking to telemetry.
|
|
1247
|
-
// for telemetry reporting, `name`s in `containers` need to be keys from:
|
|
1248
|
-
// https://github.com/DataDog/dd-go/blob/prod/trace/apps/tracer-telemetry-intake/telemetry-payload/static/config_norm_rules.json
|
|
1249
|
-
#merge () {
|
|
1250
|
-
const changes = []
|
|
1251
|
-
const sources = this.#getSourcesInOrder()
|
|
1252
|
-
|
|
1253
|
-
for (const name of Object.keys(this.#defaults)) {
|
|
1254
|
-
// Use reverse order for merge (lowest priority first)
|
|
1255
|
-
for (let i = sources.length - 1; i >= 0; i--) {
|
|
1256
|
-
const { container, origin, unprocessed } = sources[i]
|
|
1257
|
-
const value = container[name]
|
|
1258
|
-
if (value != null || container === this.#defaults) {
|
|
1259
|
-
this.#setAndTrackChange({
|
|
1260
|
-
name,
|
|
1261
|
-
value,
|
|
1262
|
-
origin,
|
|
1263
|
-
unprocessedValue: unprocessed?.[name],
|
|
1264
|
-
changes,
|
|
1265
|
-
})
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
}
|
|
1269
|
-
this.sampler.sampleRate = this.sampleRate
|
|
1270
|
-
updateConfig(changes, this)
|
|
619
|
+
telemetry.updateConfig([...configWithOrigin.values()], this)
|
|
1271
620
|
}
|
|
1272
621
|
|
|
622
|
+
// TODO: Move outside of config. This is unrelated to the config system.
|
|
1273
623
|
#loadGitMetadata () {
|
|
1274
|
-
//
|
|
1275
|
-
this.repositoryUrl = removeUserSensitiveInfo(
|
|
1276
|
-
|
|
1277
|
-
)
|
|
1278
|
-
this.commitSHA = getEnv('DD_GIT_COMMIT_SHA') ?? this.tags[GIT_COMMIT_SHA]
|
|
624
|
+
// Try to read Git metadata from the environment variables
|
|
625
|
+
this.repositoryUrl = removeUserSensitiveInfo(this.DD_GIT_REPOSITORY_URL ?? this.tags[GIT_REPOSITORY_URL])
|
|
626
|
+
this.commitSHA = this.DD_GIT_COMMIT_SHA ?? this.tags[GIT_COMMIT_SHA]
|
|
1279
627
|
|
|
1280
|
-
//
|
|
628
|
+
// Otherwise, try to read Git metadata from the git.properties file
|
|
1281
629
|
if (!this.repositoryUrl || !this.commitSHA) {
|
|
1282
|
-
const DD_GIT_PROPERTIES_FILE =
|
|
630
|
+
const DD_GIT_PROPERTIES_FILE = this.DD_GIT_PROPERTIES_FILE
|
|
1283
631
|
const gitPropertiesFile = DD_GIT_PROPERTIES_FILE ?? `${process.cwd()}/git.properties`
|
|
1284
|
-
let gitPropertiesString
|
|
1285
632
|
try {
|
|
1286
|
-
gitPropertiesString = fs.readFileSync(gitPropertiesFile, 'utf8')
|
|
1287
|
-
|
|
633
|
+
const gitPropertiesString = fs.readFileSync(gitPropertiesFile, 'utf8')
|
|
634
|
+
const { commitSHA, repositoryUrl } = getGitMetadataFromGitProperties(gitPropertiesString)
|
|
635
|
+
this.commitSHA ??= commitSHA
|
|
636
|
+
this.repositoryUrl ??= repositoryUrl
|
|
637
|
+
} catch (error) {
|
|
1288
638
|
// Only log error if the user has set a git.properties path
|
|
1289
639
|
if (DD_GIT_PROPERTIES_FILE) {
|
|
1290
|
-
log.error('Error reading DD_GIT_PROPERTIES_FILE: %s', gitPropertiesFile,
|
|
640
|
+
log.error('Error reading DD_GIT_PROPERTIES_FILE: %s', gitPropertiesFile, error)
|
|
1291
641
|
}
|
|
1292
642
|
}
|
|
1293
|
-
if (gitPropertiesString) {
|
|
1294
|
-
const { commitSHA, repositoryUrl } = getGitMetadataFromGitProperties(gitPropertiesString)
|
|
1295
|
-
this.commitSHA = this.commitSHA || commitSHA
|
|
1296
|
-
this.repositoryUrl = this.repositoryUrl || repositoryUrl
|
|
1297
|
-
}
|
|
1298
643
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
} catch (e) {
|
|
1312
|
-
// Only log error if the user has set a .git/ path
|
|
1313
|
-
if (DD_GIT_FOLDER_PATH) {
|
|
1314
|
-
log.error('Error reading git config: %s', gitConfigPath, e)
|
|
1315
|
-
}
|
|
644
|
+
|
|
645
|
+
// Otherwise, try to read Git metadata from the .git/ folder
|
|
646
|
+
const DD_GIT_FOLDER_PATH = this.DD_GIT_FOLDER_PATH
|
|
647
|
+
const gitFolderPath = DD_GIT_FOLDER_PATH ?? path.join(process.cwd(), '.git')
|
|
648
|
+
|
|
649
|
+
if (!this.repositoryUrl) {
|
|
650
|
+
// Try to read git config (repository URL)
|
|
651
|
+
const gitConfigPath = path.join(gitFolderPath, 'config')
|
|
652
|
+
try {
|
|
653
|
+
const gitConfigContent = fs.readFileSync(gitConfigPath, 'utf8')
|
|
654
|
+
if (gitConfigContent) {
|
|
655
|
+
this.repositoryUrl = getRemoteOriginURL(gitConfigContent)
|
|
1316
656
|
}
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
if (gitHeadSha) {
|
|
1322
|
-
this.commitSHA = gitHeadSha
|
|
657
|
+
} catch (error) {
|
|
658
|
+
// Only log error if the user has set a .git/ path
|
|
659
|
+
if (DD_GIT_FOLDER_PATH) {
|
|
660
|
+
log.error('Error reading git config: %s', gitConfigPath, error)
|
|
1323
661
|
}
|
|
1324
662
|
}
|
|
1325
663
|
}
|
|
664
|
+
// Try to read git HEAD (commit SHA)
|
|
665
|
+
this.commitSHA ??= resolveGitHeadSHA(gitFolderPath)
|
|
1326
666
|
}
|
|
1327
667
|
}
|
|
1328
668
|
|
|
1329
|
-
function getCounter (event, ddVar, otelVar) {
|
|
1330
|
-
const counters = TELEMETRY_COUNTERS.get(event)
|
|
1331
|
-
const tags = []
|
|
1332
|
-
const ddVarPrefix = 'config_datadog:'
|
|
1333
|
-
const otelVarPrefix = 'config_opentelemetry:'
|
|
1334
|
-
if (ddVar) {
|
|
1335
|
-
ddVar = ddVarPrefix + ddVar.toLowerCase()
|
|
1336
|
-
tags.push(ddVar)
|
|
1337
|
-
}
|
|
1338
|
-
if (otelVar) {
|
|
1339
|
-
otelVar = otelVarPrefix + otelVar.toLowerCase()
|
|
1340
|
-
tags.push(otelVar)
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
if (!(otelVar in counters)) counters[otelVar] = {}
|
|
1344
|
-
|
|
1345
|
-
const counter = tracerMetrics.count(event, tags)
|
|
1346
|
-
counters[otelVar][ddVar] = counter
|
|
1347
|
-
return counter
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
function getFromOtelSamplerMap (otelTracesSampler, otelTracesSamplerArg) {
|
|
1351
|
-
const OTEL_TRACES_SAMPLER_MAPPING = {
|
|
1352
|
-
always_on: '1.0',
|
|
1353
|
-
always_off: '0.0',
|
|
1354
|
-
traceidratio: otelTracesSamplerArg,
|
|
1355
|
-
parentbased_always_on: '1.0',
|
|
1356
|
-
parentbased_always_off: '0.0',
|
|
1357
|
-
parentbased_traceidratio: otelTracesSamplerArg,
|
|
1358
|
-
}
|
|
1359
|
-
return OTEL_TRACES_SAMPLER_MAPPING[otelTracesSampler]
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
669
|
/**
|
|
1363
|
-
*
|
|
1364
|
-
* @param {
|
|
1365
|
-
* @param {string} [value] - The value of the environment variable
|
|
1366
|
-
* @returns {boolean} - True if the value is valid, false otherwise
|
|
670
|
+
* @param {Config} config
|
|
671
|
+
* @param {ConfigKey} envVar
|
|
1367
672
|
*/
|
|
1368
|
-
function
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
case 'OTEL_PROPAGATORS':
|
|
1376
|
-
case 'OTEL_RESOURCE_ATTRIBUTES':
|
|
1377
|
-
case 'OTEL_SERVICE_NAME':
|
|
1378
|
-
return typeof value !== 'string'
|
|
1379
|
-
case 'OTEL_TRACES_SAMPLER':
|
|
1380
|
-
return getFromOtelSamplerMap(value, getEnv('OTEL_TRACES_SAMPLER_ARG')) === undefined
|
|
1381
|
-
case 'OTEL_TRACES_SAMPLER_ARG':
|
|
1382
|
-
return Number.isNaN(Number.parseFloat(value))
|
|
1383
|
-
case 'OTEL_SDK_DISABLED':
|
|
1384
|
-
return value.toLowerCase() !== 'true' && value.toLowerCase() !== 'false'
|
|
1385
|
-
case 'OTEL_TRACES_EXPORTER':
|
|
1386
|
-
case 'OTEL_METRICS_EXPORTER':
|
|
1387
|
-
case 'OTEL_LOGS_EXPORTER':
|
|
1388
|
-
return value.toLowerCase() !== 'none'
|
|
1389
|
-
default:
|
|
1390
|
-
return true
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
function checkIfBothOtelAndDdEnvVarSet () {
|
|
1395
|
-
for (const [otelEnvVar, ddEnvVar] of OTEL_DD_ENV_MAPPING) {
|
|
1396
|
-
const otelValue = getEnv(otelEnvVar)
|
|
1397
|
-
|
|
1398
|
-
if (ddEnvVar && getEnv(ddEnvVar) && otelValue) {
|
|
1399
|
-
log.warn('both %s and %s environment variables are set', ddEnvVar, otelEnvVar)
|
|
1400
|
-
getCounter('otel.env.hiding', ddEnvVar, otelEnvVar).inc()
|
|
673
|
+
function deactivateIfEnabledAndWarnOnWindows (config, envVar) {
|
|
674
|
+
if (config[envVar]) {
|
|
675
|
+
const source = trackedConfigOrigins.get(envVar)
|
|
676
|
+
setAndTrack(config, envVar, false)
|
|
677
|
+
// TODO: Should we log even for default values?
|
|
678
|
+
if (source) {
|
|
679
|
+
log.warn('%s is not supported on Windows. Deactivating. (source: %s)', envVar, source)
|
|
1401
680
|
}
|
|
1402
|
-
|
|
1403
|
-
if (isInvalidOtelEnvironmentVariable(otelEnvVar, otelValue)) {
|
|
1404
|
-
log.warn('unexpected value %s for %s environment variable', otelValue, otelEnvVar)
|
|
1405
|
-
getCounter('otel.env.invalid', ddEnvVar, otelEnvVar).inc()
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
function maybeFile (filepath) {
|
|
1411
|
-
if (!filepath) return
|
|
1412
|
-
try {
|
|
1413
|
-
return fs.readFileSync(filepath, 'utf8')
|
|
1414
|
-
} catch (e) {
|
|
1415
|
-
log.error('Error reading file %s', filepath, e)
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
function maybeJsonFile (filepath) {
|
|
1420
|
-
const file = maybeFile(filepath)
|
|
1421
|
-
if (!file) return
|
|
1422
|
-
try {
|
|
1423
|
-
return JSON.parse(file)
|
|
1424
|
-
} catch (e) {
|
|
1425
|
-
log.error('Error parsing JSON file %s', filepath, e)
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
function safeJsonParse (input) {
|
|
1430
|
-
try {
|
|
1431
|
-
return JSON.parse(input)
|
|
1432
|
-
} catch {}
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
function validateNamingVersion (versionString) {
|
|
1436
|
-
if (!versionString) {
|
|
1437
|
-
return DEFAULT_NAMING_VERSION
|
|
1438
|
-
}
|
|
1439
|
-
if (!NAMING_VERSIONS.has(versionString)) {
|
|
1440
|
-
log.warn('Unexpected input for config.spanAttributeSchema, picked default', DEFAULT_NAMING_VERSION)
|
|
1441
|
-
return DEFAULT_NAMING_VERSION
|
|
1442
681
|
}
|
|
1443
|
-
return versionString
|
|
1444
682
|
}
|
|
1445
683
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
*
|
|
1451
|
-
* @param {string | string[]} input
|
|
1452
|
-
*/
|
|
1453
|
-
function splitJSONPathRules (input) {
|
|
1454
|
-
if (!input || input === '$') return
|
|
1455
|
-
if (Array.isArray(input)) return input
|
|
1456
|
-
if (input === 'all') return []
|
|
1457
|
-
return input.split(',')
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
|
-
// Shallow clone with property name remapping
|
|
1461
|
-
function remapify (input, mappings) {
|
|
1462
|
-
if (!input) return
|
|
1463
|
-
const output = {}
|
|
1464
|
-
for (const [key, value] of Object.entries(input)) {
|
|
1465
|
-
output[key in mappings ? mappings[key] : key] = value
|
|
1466
|
-
}
|
|
1467
|
-
return output
|
|
1468
|
-
}
|
|
1469
|
-
|
|
1470
|
-
/**
|
|
1471
|
-
* Normalizes propagation style values to a lowercase array.
|
|
1472
|
-
* Handles both string (comma-separated) and array inputs.
|
|
1473
|
-
*/
|
|
1474
|
-
function normalizePropagationStyle (value) {
|
|
1475
|
-
if (Array.isArray(value)) {
|
|
1476
|
-
return value.map(v => v.toLowerCase())
|
|
1477
|
-
}
|
|
1478
|
-
if (typeof value === 'string') {
|
|
1479
|
-
return value.split(',')
|
|
1480
|
-
.filter(v => v !== '')
|
|
1481
|
-
.map(v => v.trim().toLowerCase())
|
|
1482
|
-
}
|
|
1483
|
-
if (value !== undefined) {
|
|
1484
|
-
log.warn('Unexpected input for config.tracePropagationStyle')
|
|
684
|
+
function increaseCounter (event, ddVar, otelVar) {
|
|
685
|
+
const tags = []
|
|
686
|
+
if (ddVar) {
|
|
687
|
+
tags.push(`config_datadog:${ddVar.toLowerCase()}`)
|
|
1485
688
|
}
|
|
689
|
+
tags.push(`config_opentelemetry:${otelVar.toLowerCase()}`)
|
|
690
|
+
tracerMetrics.count(event, tags).inc()
|
|
1486
691
|
}
|
|
1487
692
|
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
// eslint-disable-next-line @stylistic/max-len
|
|
1495
|
-
'Use either the DD_TRACE_PROPAGATION_STYLE environment variable or separate DD_TRACE_PROPAGATION_STYLE_INJECT and DD_TRACE_PROPAGATION_STYLE_EXTRACT environment variables'
|
|
1496
|
-
)
|
|
693
|
+
function getFromOtelSamplerMap (otelTracesSampler, otelTracesSamplerArg) {
|
|
694
|
+
const OTEL_TRACES_SAMPLER_MAPPING = {
|
|
695
|
+
always_on: 1,
|
|
696
|
+
always_off: 0,
|
|
697
|
+
parentbased_always_on: 1,
|
|
698
|
+
parentbased_always_off: 0,
|
|
1497
699
|
}
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
|
-
function reformatSpanSamplingRules (rules) {
|
|
1501
|
-
if (!rules) return rules
|
|
1502
|
-
return rules.map(rule => {
|
|
1503
|
-
return remapify(rule, {
|
|
1504
|
-
sample_rate: 'sampleRate',
|
|
1505
|
-
max_per_second: 'maxPerSecond',
|
|
1506
|
-
})
|
|
1507
|
-
})
|
|
1508
|
-
}
|
|
1509
700
|
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
getEnv('DD_TRACE_EXPERIMENTAL_B3_ENABLED')
|
|
1514
|
-
const defaultPropagationStyle = ['datadog', 'tracecontext']
|
|
1515
|
-
if (isTrue(DD_TRACE_B3_ENABLED)) {
|
|
1516
|
-
defaultPropagationStyle.push('b3', 'b3 single header')
|
|
701
|
+
const result = OTEL_TRACES_SAMPLER_MAPPING[otelTracesSampler] ?? otelTracesSamplerArg
|
|
702
|
+
if (result === undefined) {
|
|
703
|
+
increaseCounter('otel.env.invalid', 'DD_TRACE_SAMPLE_RATE', 'OTEL_TRACES_SAMPLER')
|
|
1517
704
|
}
|
|
1518
|
-
return
|
|
705
|
+
return result
|
|
1519
706
|
}
|
|
1520
707
|
|
|
1521
|
-
function
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
708
|
+
function warnWrongOtelSettings () {
|
|
709
|
+
// This mostly works for non-aliased environment variables only.
|
|
710
|
+
// TODO: Adjust this to work across all sources.
|
|
711
|
+
for (const [otelEnvVar, ddEnvVar, key] of [
|
|
712
|
+
// eslint-disable-next-line eslint-rules/eslint-env-aliases
|
|
713
|
+
['OTEL_LOG_LEVEL', 'DD_TRACE_LOG_LEVEL', 'logLevel'],
|
|
714
|
+
// eslint-disable-next-line eslint-rules/eslint-env-aliases
|
|
715
|
+
['OTEL_PROPAGATORS', 'DD_TRACE_PROPAGATION_STYLE'],
|
|
716
|
+
// eslint-disable-next-line eslint-rules/eslint-env-aliases
|
|
717
|
+
['OTEL_SERVICE_NAME', 'DD_SERVICE', 'service'],
|
|
718
|
+
['OTEL_TRACES_SAMPLER', 'DD_TRACE_SAMPLE_RATE'],
|
|
719
|
+
['OTEL_TRACES_SAMPLER_ARG', 'DD_TRACE_SAMPLE_RATE'],
|
|
720
|
+
['OTEL_TRACES_EXPORTER', 'DD_TRACE_ENABLED'],
|
|
721
|
+
['OTEL_METRICS_EXPORTER', 'DD_RUNTIME_METRICS_ENABLED'],
|
|
722
|
+
['OTEL_RESOURCE_ATTRIBUTES', 'DD_TAGS'],
|
|
723
|
+
['OTEL_SDK_DISABLED', 'DD_TRACE_OTEL_ENABLED'],
|
|
724
|
+
['OTEL_LOGS_EXPORTER'],
|
|
725
|
+
]) {
|
|
726
|
+
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
727
|
+
const envs = process.env
|
|
728
|
+
const otelSource = trackedConfigOrigins.get(/** @type {ConfigPath} */ (key ?? otelEnvVar))
|
|
729
|
+
const otelEnvValue = envs[otelEnvVar]
|
|
730
|
+
if (otelEnvValue) {
|
|
731
|
+
if (envs[ddEnvVar]) {
|
|
732
|
+
log.warn('Conflicting %s and %s environment variables are set for %s', ddEnvVar, otelEnvVar, otelSource)
|
|
733
|
+
increaseCounter('otel.env.hiding', ddEnvVar, otelEnvVar)
|
|
1531
734
|
}
|
|
1532
|
-
rule.tags = reformattedTags
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
return samplingRules
|
|
1536
|
-
}
|
|
1537
|
-
|
|
1538
|
-
function setBoolean (obj, name, value) {
|
|
1539
|
-
if (value === undefined || value === null) {
|
|
1540
|
-
obj[name] = value
|
|
1541
|
-
} else if (isTrue(value)) {
|
|
1542
|
-
obj[name] = true
|
|
1543
|
-
} else if (isFalse(value)) {
|
|
1544
|
-
obj[name] = false
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
function setUnit (obj, name, value) {
|
|
1549
|
-
if (value === null || value === undefined) {
|
|
1550
|
-
obj[name] = value
|
|
1551
|
-
return
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
value = Number.parseFloat(value)
|
|
1555
|
-
|
|
1556
|
-
if (!Number.isNaN(value)) {
|
|
1557
|
-
// TODO: Ignore out of range values instead of normalizing them.
|
|
1558
|
-
obj[name] = Math.min(Math.max(value, 0), 1)
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
function setArray (obj, name, value) {
|
|
1563
|
-
if (value == null) {
|
|
1564
|
-
obj[name] = null
|
|
1565
|
-
return
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
if (typeof value === 'string') {
|
|
1569
|
-
value = value.split(',').map(item => {
|
|
1570
|
-
// Trim each item and remove whitespace around the colon
|
|
1571
|
-
const [key, val] = item.split(':').map(part => part.trim())
|
|
1572
|
-
return val === undefined ? key : `${key}:${val}`
|
|
1573
|
-
})
|
|
1574
|
-
}
|
|
1575
735
|
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
obj[name] = null
|
|
1584
|
-
return
|
|
1585
|
-
}
|
|
1586
|
-
value = value.split(',')
|
|
1587
|
-
const result = []
|
|
1588
|
-
|
|
1589
|
-
for (const val of value) {
|
|
1590
|
-
if (val.includes('-')) {
|
|
1591
|
-
const [start, end] = val.split('-').map(Number)
|
|
1592
|
-
for (let i = start; i <= end; i++) {
|
|
1593
|
-
result.push(i)
|
|
736
|
+
// eslint-disable-next-line eslint-rules/eslint-env-aliases
|
|
737
|
+
const invalidOtelValue = otelEnvVar === 'OTEL_PROPAGATORS'
|
|
738
|
+
? trackedConfigOrigins.get(/** @type {ConfigPath} */ ('tracePropagationStyle.inject')) !== otelSource &&
|
|
739
|
+
!envs[ddEnvVar]
|
|
740
|
+
: !otelSource
|
|
741
|
+
if (invalidOtelValue) {
|
|
742
|
+
increaseCounter('otel.env.invalid', ddEnvVar, otelEnvVar)
|
|
1594
743
|
}
|
|
1595
|
-
} else {
|
|
1596
|
-
result.push(Number(val))
|
|
1597
744
|
}
|
|
1598
745
|
}
|
|
1599
|
-
obj[name] = result
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1602
|
-
function setSamplingRule (obj, name, value) {
|
|
1603
|
-
if (value == null) {
|
|
1604
|
-
obj[name] = null
|
|
1605
|
-
return
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
|
-
if (typeof value === 'string') {
|
|
1609
|
-
value = value.split(',')
|
|
1610
|
-
}
|
|
1611
|
-
|
|
1612
|
-
if (Array.isArray(value)) {
|
|
1613
|
-
value = value.map(rule => {
|
|
1614
|
-
return remapify(rule, {
|
|
1615
|
-
sample_rate: 'sampleRate',
|
|
1616
|
-
})
|
|
1617
|
-
})
|
|
1618
|
-
obj[name] = value
|
|
1619
|
-
}
|
|
1620
|
-
}
|
|
1621
|
-
|
|
1622
|
-
function setString (obj, name, value) {
|
|
1623
|
-
obj[name] = value ? String(value) : undefined // unset for empty strings
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
function setTags (obj, name, value) {
|
|
1627
|
-
if (!value || Object.keys(value).length === 0) {
|
|
1628
|
-
obj[name] = null
|
|
1629
|
-
return
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
obj[name] = value
|
|
1633
|
-
}
|
|
1634
|
-
|
|
1635
|
-
function handleOtel (tagString) {
|
|
1636
|
-
return tagString
|
|
1637
|
-
?.replace(/(^|,)deployment\.environment=/, '$1env:')
|
|
1638
|
-
.replace(/(^|,)service\.name=/, '$1service:')
|
|
1639
|
-
.replace(/(^|,)service\.version=/, '$1version:')
|
|
1640
|
-
.replaceAll('=', ':')
|
|
1641
|
-
}
|
|
1642
|
-
|
|
1643
|
-
function parseSpaceSeparatedTags (tagString) {
|
|
1644
|
-
if (tagString && !tagString.includes(',')) {
|
|
1645
|
-
tagString = tagString.replaceAll(/\s+/g, ',')
|
|
1646
|
-
}
|
|
1647
|
-
return tagString
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
|
-
function maybeInt (number) {
|
|
1651
|
-
const parsed = Number.parseInt(number)
|
|
1652
|
-
return Number.isNaN(parsed) ? undefined : parsed
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
function maybeFloat (number) {
|
|
1656
|
-
const parsed = Number.parseFloat(number)
|
|
1657
|
-
return Number.isNaN(parsed) ? undefined : parsed
|
|
1658
|
-
}
|
|
1659
|
-
|
|
1660
|
-
function nonNegInt (value, envVarName, allowZero = true) {
|
|
1661
|
-
if (value === undefined) return
|
|
1662
|
-
const parsed = Number.parseInt(value)
|
|
1663
|
-
if (Number.isNaN(parsed) || parsed < 0 || (parsed === 0 && !allowZero)) {
|
|
1664
|
-
log.warn('Invalid value %d for %s. Using default value.', parsed, envVarName)
|
|
1665
|
-
return
|
|
1666
|
-
}
|
|
1667
|
-
return parsed
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
|
-
function getAgentUrl (url, options) {
|
|
1671
|
-
if (url) return new URL(url)
|
|
1672
|
-
|
|
1673
|
-
if (os.type() === 'Windows_NT') return
|
|
1674
|
-
|
|
1675
|
-
if (
|
|
1676
|
-
!options.hostname &&
|
|
1677
|
-
!options.port &&
|
|
1678
|
-
!getEnv('DD_AGENT_HOST') &&
|
|
1679
|
-
!getEnv('DD_TRACE_AGENT_PORT') &&
|
|
1680
|
-
!isTrue(getEnv('DD_CIVISIBILITY_AGENTLESS_ENABLED')) &&
|
|
1681
|
-
fs.existsSync('/var/run/datadog/apm.socket')
|
|
1682
|
-
) {
|
|
1683
|
-
return new URL('unix:///var/run/datadog/apm.socket')
|
|
1684
|
-
}
|
|
1685
746
|
}
|
|
1686
747
|
|
|
748
|
+
/**
|
|
749
|
+
* @param {TracerOptions} [options]
|
|
750
|
+
*/
|
|
1687
751
|
function getConfig (options) {
|
|
1688
752
|
if (!configInstance) {
|
|
1689
753
|
configInstance = new Config(options)
|