dd-trace 5.96.0 → 5.98.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 +60 -2
- 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 +69 -4
- package/packages/datadog-instrumentations/src/cypress-config.js +318 -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 +117 -16
- package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +12 -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/redis.js +12 -6
- 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 +5 -4
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
- package/packages/datadog-plugin-cucumber/src/index.js +13 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +166 -6
- package/packages/datadog-plugin-cypress/src/index.js +59 -2
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
- package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +10 -2
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +10 -2
- 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-mongodb-core/src/index.js +3 -3
- package/packages/datadog-plugin-mysql/src/index.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +10 -16
- package/packages/datadog-plugin-openai/src/services.js +1 -0
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/datadog-plugin-tedious/src/index.js +1 -1
- package/packages/datadog-plugin-ws/src/close.js +1 -1
- package/packages/datadog-plugin-ws/src/receiver.js +1 -1
- 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 +26 -22
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
- package/packages/dd-trace/src/appsec/blocking.js +64 -33
- 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/appsec/sdk/set_user.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
- 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 +315 -146
- package/packages/dd-trace/src/config/generated-config-types.d.ts +9 -1
- package/packages/dd-trace/src/config/helper.js +59 -10
- package/packages/dd-trace/src/config/index.js +587 -1496
- 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 +406 -432
- package/packages/dd-trace/src/constants.js +1 -0
- 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/devtools_client/snapshot/processor.js +5 -2
- 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 +8 -7
- package/packages/dd-trace/src/encode/span-stats.js +4 -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 +20 -59
- 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/openfeature/remote_config.js +6 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
- 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/opentelemetry/otlp/otlp_http_exporter_base.js +17 -2
- package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
- package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
- package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +75 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +66 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +332 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
- package/packages/dd-trace/src/opentracing/tracer.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/log_plugin.js +3 -0
- package/packages/dd-trace/src/plugins/plugin.js +11 -13
- package/packages/dd-trace/src/plugins/storage.js +2 -2
- package/packages/dd-trace/src/plugins/tracing.js +22 -5
- package/packages/dd-trace/src/plugins/util/test.js +2 -0
- package/packages/dd-trace/src/plugins/util/web.js +6 -88
- 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 +78 -109
- 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 +40 -6
- 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 +18 -11
- package/packages/dd-trace/src/sampler.js +1 -1
- package/packages/dd-trace/src/service-naming/index.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
- package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +17 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +11 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
- package/packages/dd-trace/src/span_stats.js +5 -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/tracer.js +2 -2
- package/packages/dd-trace/src/util.js +0 -9
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
- package/vendor/dist/protobufjs/index.js +1 -1
- package/packages/dd-trace/src/log/utils.js +0 -16
|
@@ -5,1685 +5,776 @@ 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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
['OTEL_LOGS_EXPORTER', undefined],
|
|
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
|
+
} = require('./helper')
|
|
33
|
+
const {
|
|
34
|
+
defaults,
|
|
35
|
+
fallbackConfigurations,
|
|
36
|
+
configurationsTable,
|
|
37
|
+
optionsTable,
|
|
38
|
+
configWithOrigin,
|
|
39
|
+
parseErrors,
|
|
40
|
+
generateTelemetry,
|
|
41
|
+
} = require('./defaults')
|
|
42
|
+
const { transformers } = require('./parsers')
|
|
43
|
+
|
|
51
44
|
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
45
|
|
|
57
46
|
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
|
|
58
|
-
const changeTracker = {}
|
|
59
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @typedef {'default'
|
|
50
|
+
* | 'code'
|
|
51
|
+
* | 'remote_config'
|
|
52
|
+
* | 'calculated'
|
|
53
|
+
* | 'env_var'
|
|
54
|
+
* | 'local_stable_config'
|
|
55
|
+
* | 'fleet_stable_config'} TelemetrySource
|
|
56
|
+
* @typedef {'remote_config' | 'calculated'} RevertibleTelemetrySource
|
|
57
|
+
* @typedef {import('../../../../index').TracerOptions} TracerOptions
|
|
58
|
+
* @typedef {import('./config-types').ConfigKey} ConfigKey
|
|
59
|
+
* @typedef {import('./config-types').ConfigPath} ConfigPath
|
|
60
|
+
* @typedef {{
|
|
61
|
+
* value: import('./config-types').ConfigPathValue<ConfigPath>,
|
|
62
|
+
* source: TelemetrySource
|
|
63
|
+
* }} TrackedConfigEntry
|
|
64
|
+
* @typedef {{
|
|
65
|
+
* baseValuesByPath: Partial<Record<ConfigPath, TrackedConfigEntry>>,
|
|
66
|
+
* remote_config: Set<ConfigPath>,
|
|
67
|
+
* calculated: Set<ConfigPath>,
|
|
68
|
+
* }} ChangeTracker
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/** @type {Config | null} */
|
|
60
72
|
let configInstance = null
|
|
61
73
|
|
|
74
|
+
// An entry that is undefined means it is the default value.
|
|
75
|
+
/** @type {Map<ConfigPath, TelemetrySource>} */
|
|
76
|
+
const trackedConfigOrigins = new Map()
|
|
77
|
+
|
|
78
|
+
// ChangeTracker tracks the changes to the config up to programmatic options (code).
|
|
79
|
+
/** @type {ChangeTracker} */
|
|
80
|
+
const changeTracker = {
|
|
81
|
+
baseValuesByPath: {},
|
|
82
|
+
remote_config: new Set(),
|
|
83
|
+
calculated: new Set(),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param {Config} config
|
|
88
|
+
* @param {RevertibleTelemetrySource} source
|
|
89
|
+
*/
|
|
90
|
+
function undo (config, source) {
|
|
91
|
+
for (const name of changeTracker[source]) {
|
|
92
|
+
const entry = changeTracker.baseValuesByPath[name] ?? { source: 'default', value: defaults[name] }
|
|
93
|
+
setAndTrack(config, name, entry.value, undefined, entry.source)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function get (object, path) {
|
|
98
|
+
// Fast path for simple property access.
|
|
99
|
+
if (object[path] !== undefined) {
|
|
100
|
+
return object[path]
|
|
101
|
+
}
|
|
102
|
+
let index = 0
|
|
103
|
+
while (true) {
|
|
104
|
+
const nextIndex = path.indexOf('.', index)
|
|
105
|
+
if (nextIndex === -1) {
|
|
106
|
+
return object[path.slice(index)]
|
|
107
|
+
}
|
|
108
|
+
object = object[path.slice(index, nextIndex)]
|
|
109
|
+
index = nextIndex + 1
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @param {Config} config
|
|
115
|
+
* @template {ConfigPath} TPath
|
|
116
|
+
* @param {TPath} name
|
|
117
|
+
* @param {import('./config-types').ConfigPathValue<TPath>} value
|
|
118
|
+
* @param {unknown} [rawValue]
|
|
119
|
+
* @param {TelemetrySource} [source]
|
|
120
|
+
*/
|
|
121
|
+
function setAndTrack (config, name, value, rawValue = value, source = 'calculated') {
|
|
122
|
+
// envs can not be undefined
|
|
123
|
+
if (value == null) {
|
|
124
|
+
// TODO: This works as before while ignoring undefined programmatic options is not ideal.
|
|
125
|
+
if (source !== 'default') {
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
} else if (source === 'calculated' || source === 'remote_config') {
|
|
129
|
+
if (source === 'calculated' && value === get(config, name)) {
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
changeTracker[source].add(name)
|
|
133
|
+
} else {
|
|
134
|
+
const copy = typeof value === 'object' && value !== null ? rfdc(value) : value
|
|
135
|
+
changeTracker.baseValuesByPath[name] = { value: copy, source }
|
|
136
|
+
}
|
|
137
|
+
set(config, name, value)
|
|
138
|
+
|
|
139
|
+
generateTelemetry(rawValue, source, name)
|
|
140
|
+
if (source === 'default') {
|
|
141
|
+
trackedConfigOrigins.delete(name)
|
|
142
|
+
} else {
|
|
143
|
+
trackedConfigOrigins.set(name, source)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
62
147
|
module.exports = getConfig
|
|
63
148
|
|
|
64
|
-
|
|
149
|
+
// We extend from ConfigBase to make our types work
|
|
150
|
+
class Config extends ConfigBase {
|
|
65
151
|
/**
|
|
66
152
|
* parsed DD_TAGS, usable as a standalone tag set across products
|
|
67
153
|
* @type {Record<string, string>}
|
|
68
154
|
*/
|
|
69
|
-
#parsedDdTags
|
|
70
|
-
#envUnprocessed = {}
|
|
71
|
-
#optsUnprocessed = {}
|
|
72
|
-
#remoteUnprocessed = {}
|
|
73
|
-
#env = {}
|
|
74
|
-
#options = {}
|
|
75
|
-
#remote = {}
|
|
76
|
-
#defaults = {}
|
|
77
|
-
#optionsArg = {}
|
|
78
|
-
#localStableConfig = {}
|
|
79
|
-
#fleetStableConfig = {}
|
|
80
|
-
#calculated = {}
|
|
155
|
+
#parsedDdTags
|
|
81
156
|
|
|
157
|
+
/**
|
|
158
|
+
* @type {Record<string, string>}
|
|
159
|
+
*/
|
|
160
|
+
get parsedDdTags () {
|
|
161
|
+
return this.#parsedDdTags
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @param {TracerOptions} [options={}]
|
|
166
|
+
*/
|
|
82
167
|
constructor (options = {}) {
|
|
83
|
-
|
|
84
|
-
const configEnvSources = getStableConfigSources()
|
|
85
|
-
this.stableConfig = {
|
|
86
|
-
fleetEntries: configEnvSources.fleetStableConfig,
|
|
87
|
-
localEntries: configEnvSources.localStableConfig,
|
|
88
|
-
warnings: configEnvSources.stableConfigWarnings,
|
|
89
|
-
}
|
|
90
|
-
}
|
|
168
|
+
super()
|
|
91
169
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
iast: options.iast == null ? options.experimental?.iast : options.iast,
|
|
170
|
+
const configEnvSources = getStableConfigSources()
|
|
171
|
+
this.stableConfig = {
|
|
172
|
+
fleetEntries: configEnvSources.fleetStableConfig ?? {},
|
|
173
|
+
localEntries: configEnvSources.localStableConfig ?? {},
|
|
174
|
+
warnings: configEnvSources.stableConfigWarnings,
|
|
98
175
|
}
|
|
99
176
|
|
|
100
177
|
// 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)
|
|
178
|
+
// TODO: Implement auto buffering of inside of log module before first
|
|
179
|
+
// configure call. That way the logger is always available and the
|
|
180
|
+
// application doesn't need to configure it first and the configuration
|
|
181
|
+
// happens inside of config instead of inside of log module. If the logger
|
|
182
|
+
// is not deactivated, the buffered logs would be discarded. That way stable
|
|
183
|
+
// config warnings can also be logged directly and do not need special
|
|
184
|
+
// handling.
|
|
185
|
+
this.debug = log.configure(options)
|
|
114
186
|
|
|
115
187
|
// Process stable config warnings, if any
|
|
116
188
|
for (const warning of this.stableConfig?.warnings ?? []) {
|
|
117
189
|
log.warn(warning)
|
|
118
190
|
}
|
|
119
191
|
|
|
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
192
|
this.#applyDefaults()
|
|
136
|
-
|
|
137
|
-
this.#
|
|
138
|
-
this.#
|
|
139
|
-
this.#
|
|
193
|
+
// TODO: Update origin documentation to list all valid sources. Add local_stable_config and fleet_stable_config.
|
|
194
|
+
this.#applyEnvs(getEnvironmentVariables(this.stableConfig.localEntries, true), 'local_stable_config')
|
|
195
|
+
this.#applyEnvs(getEnvironmentVariables(undefined, true), 'env_var')
|
|
196
|
+
this.#applyEnvs(getEnvironmentVariables(this.stableConfig.fleetEntries, true), 'fleet_stable_config')
|
|
197
|
+
|
|
198
|
+
// Experimental options are applied first, so they can be overridden by non-experimental options.
|
|
199
|
+
// TODO: When using programmatic options, check if there is a higher
|
|
200
|
+
// priority name in the same options object. Use the highest priority name.
|
|
201
|
+
const { experimental, ...rest } = options
|
|
202
|
+
if (experimental) {
|
|
203
|
+
// @ts-expect-error - Difficult to type this correctly.
|
|
204
|
+
this.#applyOptions(experimental, 'code', 'experimental')
|
|
205
|
+
}
|
|
206
|
+
this.#applyOptions(rest, 'code')
|
|
140
207
|
this.#applyCalculated()
|
|
141
|
-
this.#merge()
|
|
142
208
|
|
|
143
|
-
|
|
144
|
-
service: this.service,
|
|
145
|
-
env: this.env,
|
|
146
|
-
version: this.version,
|
|
147
|
-
'runtime-id': RUNTIME_ID,
|
|
148
|
-
})
|
|
209
|
+
warnWrongOtelSettings()
|
|
149
210
|
|
|
150
|
-
this.
|
|
211
|
+
if (this.gitMetadataEnabled) {
|
|
212
|
+
this.#loadGitMetadata()
|
|
213
|
+
}
|
|
151
214
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
215
|
+
parseErrors.clear()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#applyDefaults () {
|
|
219
|
+
for (const [name, value] of Object.entries(defaults)) {
|
|
220
|
+
set(this, name, value)
|
|
156
221
|
}
|
|
222
|
+
}
|
|
157
223
|
|
|
158
|
-
|
|
159
|
-
|
|
224
|
+
/**
|
|
225
|
+
* @param {import('./helper').TracerEnv} envs
|
|
226
|
+
* @param {'env_var' | 'local_stable_config' | 'fleet_stable_config'} source
|
|
227
|
+
*/
|
|
228
|
+
#applyEnvs (envs, source) {
|
|
229
|
+
for (const [name, value] of Object.entries(envs)) {
|
|
230
|
+
const entry = configurationsTable[name]
|
|
231
|
+
const parsed = entry.parser(value, name, source)
|
|
232
|
+
const transformed = parsed !== undefined && entry.transformer ? entry.transformer(parsed, name, source) : parsed
|
|
233
|
+
const rawValue = transformed !== null && typeof transformed === 'object' ? value : parsed
|
|
234
|
+
setAndTrack(this, entry.property ?? name, transformed, rawValue, source)
|
|
160
235
|
}
|
|
161
236
|
}
|
|
162
237
|
|
|
163
|
-
|
|
164
|
-
|
|
238
|
+
/**
|
|
239
|
+
* @param {TracerOptions} options
|
|
240
|
+
* @param {'code' | 'remote_config'} source
|
|
241
|
+
* @param {string} [root]
|
|
242
|
+
*/
|
|
243
|
+
#applyOptions (options, source, root = '') {
|
|
244
|
+
for (const [name, value] of Object.entries(options)) {
|
|
245
|
+
const fullName = root ? `${root}.${name}` : name
|
|
246
|
+
let entry = optionsTable[fullName]
|
|
247
|
+
if (!entry) {
|
|
248
|
+
// TODO: Fix this by by changing remote config to use env styles.
|
|
249
|
+
if (name !== 'tracing' || source !== 'remote_config') {
|
|
250
|
+
log.warn('Unknown option %s with value %o', fullName, value)
|
|
251
|
+
continue
|
|
252
|
+
}
|
|
253
|
+
// @ts-expect-error - The entry is defined in the configurationsTable.
|
|
254
|
+
entry = configurationsTable.tracing
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (entry.nestedProperties) {
|
|
258
|
+
let matched = false
|
|
259
|
+
if (typeof value === 'object' && value !== null) {
|
|
260
|
+
for (const nestedProperty of entry.nestedProperties) {
|
|
261
|
+
// WARNING: if the property name might be part of the value we look at, this could conflict!
|
|
262
|
+
// Defining an option that receives an object as value may not contain a property that is also
|
|
263
|
+
// potentially a nested property!
|
|
264
|
+
if (Object.hasOwn(value, nestedProperty)) {
|
|
265
|
+
this.#applyOptions(value, source, fullName)
|
|
266
|
+
matched = true
|
|
267
|
+
break
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (matched) {
|
|
272
|
+
continue
|
|
273
|
+
}
|
|
274
|
+
if (entry.option) {
|
|
275
|
+
entry = entry.option
|
|
276
|
+
} else {
|
|
277
|
+
if (fullName === 'tracePropagationStyle') {
|
|
278
|
+
// TracePropagationStyle is special. It is a single option that is used to set both inject and extract.
|
|
279
|
+
// TODO: Consider what to do with this later
|
|
280
|
+
// @ts-expect-error - Difficult to type this correctly.
|
|
281
|
+
this.#applyOptions({ inject: value, extract: value }, source, 'tracePropagationStyle')
|
|
282
|
+
} else {
|
|
283
|
+
log.warn('Unknown option %s with value %o', fullName, value)
|
|
284
|
+
}
|
|
285
|
+
continue
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// TODO: Coerce mismatched types to the expected type, if possible. E.g., strings <> numbers
|
|
289
|
+
const transformed = value !== undefined && entry.transformer ? entry.transformer(value, fullName, source) : value
|
|
290
|
+
setAndTrack(this, entry.property, transformed, value, source)
|
|
291
|
+
}
|
|
165
292
|
}
|
|
166
293
|
|
|
167
294
|
/**
|
|
168
295
|
* Set the configuration with remote config settings.
|
|
169
296
|
* Applies remote configuration, recalculates derived values, and merges all configuration sources.
|
|
170
297
|
*
|
|
171
|
-
* @param {
|
|
298
|
+
* @param {TracerOptions|null} options - Configurations received via Remote
|
|
172
299
|
* Config or null to reset all remote configuration
|
|
173
300
|
*/
|
|
174
301
|
setRemoteConfig (options) {
|
|
175
302
|
// Clear all RC-managed fields to ensure previous values don't persist.
|
|
176
303
|
// State is instead managed by the `RCClientLibConfigManager` class
|
|
177
|
-
this
|
|
178
|
-
this.#remoteUnprocessed = {}
|
|
304
|
+
undo(this, 'remote_config')
|
|
179
305
|
|
|
180
306
|
// Special case: if options is null, nothing to apply
|
|
181
307
|
// This happens when all remote configs are removed
|
|
182
308
|
if (options !== null) {
|
|
183
|
-
this.#
|
|
309
|
+
this.#applyOptions(options, 'remote_config')
|
|
184
310
|
}
|
|
185
311
|
|
|
186
312
|
this.#applyCalculated()
|
|
187
|
-
this.#merge()
|
|
188
313
|
}
|
|
189
314
|
|
|
190
|
-
// TODO: Remove the `updateOptions` method. We don't want to support updating the config this way
|
|
191
315
|
/**
|
|
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)
|
|
316
|
+
* @param {ConfigPath} name
|
|
196
317
|
*/
|
|
197
|
-
updateOptions (options) {
|
|
198
|
-
this.#applyOptions(options)
|
|
199
|
-
this.#applyCalculated()
|
|
200
|
-
this.#merge()
|
|
201
|
-
}
|
|
202
|
-
|
|
203
318
|
getOrigin (name) {
|
|
204
|
-
|
|
205
|
-
const value = container[name]
|
|
206
|
-
if (value != null || container === this.#defaults) {
|
|
207
|
-
return origin
|
|
208
|
-
}
|
|
209
|
-
}
|
|
319
|
+
return trackedConfigOrigins.get(name) ?? 'default'
|
|
210
320
|
}
|
|
211
321
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
322
|
+
// Handles values calculated from a mixture of options and env vars
|
|
323
|
+
#applyCalculated () {
|
|
324
|
+
undo(this, 'calculated')
|
|
325
|
+
|
|
326
|
+
if (this.DD_CIVISIBILITY_AGENTLESS_URL ||
|
|
327
|
+
this.url ||
|
|
328
|
+
os.type() !== 'Windows_NT' &&
|
|
329
|
+
!trackedConfigOrigins.has('hostname') &&
|
|
330
|
+
!trackedConfigOrigins.has('port') &&
|
|
331
|
+
!this.DD_CIVISIBILITY_AGENTLESS_ENABLED &&
|
|
332
|
+
fs.existsSync('/var/run/datadog/apm.socket')) {
|
|
333
|
+
setAndTrack(
|
|
334
|
+
this,
|
|
335
|
+
'url',
|
|
336
|
+
new URL(this.DD_CIVISIBILITY_AGENTLESS_URL || this.url || 'unix:///var/run/datadog/apm.socket')
|
|
337
|
+
)
|
|
338
|
+
}
|
|
223
339
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
340
|
+
if (this.isCiVisibility) {
|
|
341
|
+
setAndTrack(this, 'isServiceUserProvided', trackedConfigOrigins.has('service'))
|
|
342
|
+
this.tags[ORIGIN_KEY] = 'ciapp-test'
|
|
343
|
+
}
|
|
344
|
+
// Compute OTLP logs and metrics URLs to send payloads to the active Datadog Agent
|
|
345
|
+
const agentHostname = this.hostname || /** @type {URL} */ (this.url).hostname
|
|
227
346
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
347
|
+
if (!trackedConfigOrigins.has('dogstatsd.hostname')) {
|
|
348
|
+
setAndTrack(this, 'dogstatsd.hostname', agentHostname)
|
|
349
|
+
}
|
|
350
|
+
// Disable log injection when OTEL logs are enabled
|
|
351
|
+
// OTEL logs and DD log injection are mutually exclusive
|
|
352
|
+
if (this.otelLogsEnabled) {
|
|
353
|
+
setAndTrack(this, 'logInjection', false)
|
|
354
|
+
}
|
|
355
|
+
if (this.otelMetricsEnabled &&
|
|
356
|
+
trackedConfigOrigins.has('OTEL_METRICS_EXPORTER') &&
|
|
357
|
+
this.OTEL_METRICS_EXPORTER === 'none') {
|
|
358
|
+
setAndTrack(this, 'otelMetricsEnabled', false)
|
|
359
|
+
}
|
|
231
360
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
361
|
+
const otelTracesEnabled = trackedConfigOrigins.has('OTEL_TRACES_EXPORTER') &&
|
|
362
|
+
this.OTEL_TRACES_EXPORTER === 'otlp'
|
|
363
|
+
if (this.protocolVersion && this.protocolVersion !== '0.4' && otelTracesEnabled) {
|
|
364
|
+
log.warn('DD_TRACE_AGENT_PROTOCOL_VERSION is set, disabling OTLP traces export')
|
|
365
|
+
setAndTrack(this, 'otelTracesEnabled', false)
|
|
237
366
|
} else {
|
|
238
|
-
|
|
367
|
+
setAndTrack(this, 'otelTracesEnabled', otelTracesEnabled)
|
|
239
368
|
}
|
|
240
369
|
|
|
241
|
-
if (
|
|
242
|
-
|
|
370
|
+
if (this.otelTracesProtocol && this.otelTracesProtocol !== 'http/json') {
|
|
371
|
+
log.warn(
|
|
372
|
+
'OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=%s is not yet supported; only http/json is currently implemented',
|
|
373
|
+
this.otelTracesProtocol
|
|
374
|
+
)
|
|
375
|
+
setAndTrack(this, 'otelTracesProtocol', 'http/json')
|
|
243
376
|
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
#applyEnvironment () {
|
|
247
|
-
this.#applyConfigValues(getEnvironmentVariables(), this.#env, this.#envUnprocessed)
|
|
248
|
-
}
|
|
249
377
|
|
|
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)
|
|
378
|
+
if (this.telemetry.heartbeatInterval) {
|
|
379
|
+
setAndTrack(this, 'telemetry.heartbeatInterval', Math.floor(this.telemetry.heartbeatInterval * 1000))
|
|
458
380
|
}
|
|
459
|
-
if (
|
|
460
|
-
|
|
381
|
+
if (this.telemetry.extendedHeartbeatInterval) {
|
|
382
|
+
setAndTrack(this, 'telemetry.extendedHeartbeatInterval',
|
|
383
|
+
Math.floor(this.telemetry.extendedHeartbeatInterval * 1000))
|
|
461
384
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (otelTimeout !== undefined) {
|
|
468
|
-
target.otelTimeout = otelTimeout
|
|
385
|
+
|
|
386
|
+
// Enable resourceRenamingEnabled when appsec is enabled and only
|
|
387
|
+
// if DD_TRACE_RESOURCE_RENAMING_ENABLED is not explicitly set
|
|
388
|
+
if (!trackedConfigOrigins.has('resourceRenamingEnabled')) {
|
|
389
|
+
setAndTrack(this, 'resourceRenamingEnabled', this.appsec.enabled ?? false)
|
|
469
390
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (otelBatchTimeout !== undefined) {
|
|
474
|
-
target.otelBatchTimeout = otelBatchTimeout
|
|
391
|
+
|
|
392
|
+
if (!trackedConfigOrigins.has('spanComputePeerService') && this.spanAttributeSchema !== 'v0') {
|
|
393
|
+
setAndTrack(this, 'spanComputePeerService', true)
|
|
475
394
|
}
|
|
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)
|
|
395
|
+
|
|
396
|
+
if (!this.apmTracingEnabled) {
|
|
397
|
+
setAndTrack(this, 'stats.enabled', false)
|
|
398
|
+
} else if (!trackedConfigOrigins.has('stats.enabled')) {
|
|
399
|
+
setAndTrack(this, 'stats.enabled', getIsGCPFunction() || getIsAzureFunction())
|
|
489
400
|
}
|
|
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)
|
|
401
|
+
|
|
402
|
+
// TODO: Remove the experimental env vars as a major or deprecate the option?
|
|
403
|
+
if (this.experimental?.b3) {
|
|
404
|
+
if (!this.tracePropagationStyle.inject.includes('b3')) {
|
|
405
|
+
this.tracePropagationStyle.inject.push('b3')
|
|
502
406
|
}
|
|
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)
|
|
407
|
+
if (!this.tracePropagationStyle.extract.includes('b3')) {
|
|
408
|
+
this.tracePropagationStyle.extract.push('b3')
|
|
563
409
|
}
|
|
564
|
-
if (
|
|
565
|
-
|
|
410
|
+
if (!this.tracePropagationStyle.inject.includes('b3 single header')) {
|
|
411
|
+
this.tracePropagationStyle.inject.push('b3 single header')
|
|
566
412
|
}
|
|
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)
|
|
610
|
-
}
|
|
611
|
-
setBoolean(target, 'traceEnabled', DD_TRACE_ENABLED)
|
|
612
|
-
setBoolean(target, 'experimental.aiguard.block', DD_AI_GUARD_BLOCK)
|
|
613
|
-
setBoolean(target, 'experimental.aiguard.enabled', DD_AI_GUARD_ENABLED)
|
|
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)
|
|
413
|
+
if (!this.tracePropagationStyle.extract.includes('b3 single header')) {
|
|
414
|
+
this.tracePropagationStyle.extract.push('b3 single header')
|
|
415
|
+
}
|
|
416
|
+
setAndTrack(this, 'tracePropagationStyle.inject', this.tracePropagationStyle.inject)
|
|
417
|
+
setAndTrack(this, 'tracePropagationStyle.extract', this.tracePropagationStyle.extract)
|
|
627
418
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
setIntegerRangeSet(target, 'grpc.client.error.statuses', DD_GRPC_CLIENT_ERROR_STATUSES)
|
|
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
|
|
419
|
+
|
|
420
|
+
if (getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') && !fs.existsSync(DATADOG_MINI_AGENT_PATH)) {
|
|
421
|
+
setAndTrack(this, 'flushInterval', 0)
|
|
651
422
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
setString(target, 'installSignature.id', DD_INSTRUMENTATION_INSTALL_ID)
|
|
657
|
-
setString(target, 'installSignature.time', DD_INSTRUMENTATION_INSTALL_TIME)
|
|
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')
|
|
423
|
+
|
|
424
|
+
if (!trackedConfigOrigins.has('apmTracingEnabled') &&
|
|
425
|
+
trackedConfigOrigins.has('experimental.appsec.standalone.enabled')) {
|
|
426
|
+
setAndTrack(this, 'apmTracingEnabled', !this.experimental.appsec.standalone.enabled)
|
|
663
427
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
|
428
|
+
|
|
429
|
+
if (this.cloudPayloadTagging?.request || this.cloudPayloadTagging?.response) {
|
|
430
|
+
setAndTrack(this, 'cloudPayloadTagging.rules', appendRules(
|
|
431
|
+
this.cloudPayloadTagging.request,
|
|
432
|
+
this.cloudPayloadTagging.response
|
|
433
|
+
))
|
|
686
434
|
}
|
|
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)
|
|
435
|
+
|
|
436
|
+
if (this.injectionEnabled) {
|
|
437
|
+
setAndTrack(this, 'instrumentationSource', 'ssi')
|
|
695
438
|
}
|
|
696
439
|
|
|
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)
|
|
440
|
+
if (!trackedConfigOrigins.has('runtimeMetrics.enabled') && this.OTEL_METRICS_EXPORTER === 'none') {
|
|
441
|
+
setAndTrack(this, 'runtimeMetrics.enabled', false)
|
|
705
442
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
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
|
-
)
|
|
443
|
+
|
|
444
|
+
if (!trackedConfigOrigins.has('sampleRate')) {
|
|
445
|
+
const effectiveSampler = (trackedConfigOrigins.has('OTEL_TRACES_EXPORTER') &&
|
|
446
|
+
this.OTEL_TRACES_EXPORTER === 'otlp' &&
|
|
447
|
+
!trackedConfigOrigins.has('OTEL_TRACES_SAMPLER'))
|
|
448
|
+
? 'parentbased_always_on'
|
|
449
|
+
: this.OTEL_TRACES_SAMPLER
|
|
450
|
+
if (effectiveSampler && (trackedConfigOrigins.has('OTEL_TRACES_SAMPLER') ||
|
|
451
|
+
trackedConfigOrigins.has('OTEL_TRACES_EXPORTER'))) {
|
|
452
|
+
setAndTrack(this, 'sampleRate', getFromOtelSamplerMap(effectiveSampler, this.OTEL_TRACES_SAMPLER_ARG))
|
|
742
453
|
}
|
|
743
454
|
}
|
|
744
|
-
|
|
745
|
-
if (
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
)
|
|
750
|
-
|
|
751
|
-
|
|
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))
|
|
455
|
+
|
|
456
|
+
if (this.DD_SPAN_SAMPLING_RULES_FILE) {
|
|
457
|
+
try {
|
|
458
|
+
// TODO: Should we log a warning in case this is defined next to spanSamplingRules?
|
|
459
|
+
setAndTrack(this, 'spanSamplingRules', transformers.toCamelCase(JSON.parse(this.DD_SPAN_SAMPLING_RULES_FILE)))
|
|
460
|
+
} catch (error) {
|
|
461
|
+
log.warn('Error reading span sampling rules file %s; %o', this.DD_SPAN_SAMPLING_RULES_FILE, error)
|
|
462
|
+
}
|
|
781
463
|
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
464
|
+
|
|
465
|
+
// All sampler options are tracked as individual values. No need to track the sampler object as a whole.
|
|
466
|
+
this.sampler = {
|
|
467
|
+
rules: this.samplingRules,
|
|
468
|
+
rateLimit: this.rateLimit,
|
|
469
|
+
sampleRate: this.sampleRate,
|
|
470
|
+
spanSamplingRules: this.spanSamplingRules,
|
|
785
471
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
472
|
+
|
|
473
|
+
// For LLMObs, we want to auto enable it when other llmobs options are defined.
|
|
474
|
+
if (!this.llmobs.enabled &&
|
|
475
|
+
!trackedConfigOrigins.has('llmobs.enabled') &&
|
|
476
|
+
(trackedConfigOrigins.has('llmobs.agentlessEnabled') ||
|
|
477
|
+
trackedConfigOrigins.has('llmobs.mlApp'))) {
|
|
478
|
+
setAndTrack(this, 'llmobs.enabled', true)
|
|
789
479
|
}
|
|
790
|
-
|
|
791
|
-
if (
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
480
|
+
|
|
481
|
+
if (this.OTEL_RESOURCE_ATTRIBUTES) {
|
|
482
|
+
for (const [key, value] of Object.entries(this.OTEL_RESOURCE_ATTRIBUTES)) {
|
|
483
|
+
// Not replacing existing tags keeps the order of the tags as before.
|
|
484
|
+
if (!this.tags[key]) {
|
|
485
|
+
this.tags[key] = value
|
|
486
|
+
}
|
|
487
|
+
}
|
|
797
488
|
}
|
|
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()
|
|
489
|
+
if (this.DD_TRACE_TAGS) {
|
|
490
|
+
// TODO: This is a hack to keep the order of the tags as before.
|
|
491
|
+
// That hack is not sufficient, since it does not handle other cases where the tags are set by the user.
|
|
492
|
+
if (trackedConfigOrigins.get('tags') === 'code') {
|
|
493
|
+
for (const [key, value] of Object.entries(this.DD_TRACE_TAGS)) {
|
|
494
|
+
// Not replacing existing tags keeps the order of the tags as before.
|
|
495
|
+
if (!this.tags[key]) {
|
|
496
|
+
this.tags[key] = value
|
|
817
497
|
}
|
|
818
498
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
setArray(target, 'tracePropagationStyle.inject', otelStyles)
|
|
822
|
-
setArray(target, 'tracePropagationStyle.extract', otelStyles)
|
|
823
|
-
}
|
|
499
|
+
} else {
|
|
500
|
+
Object.assign(this.tags, this.DD_TRACE_TAGS)
|
|
824
501
|
}
|
|
825
502
|
}
|
|
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
503
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
504
|
+
if (!this.#parsedDdTags) {
|
|
505
|
+
this.#parsedDdTags = rfdc(this.tags)
|
|
506
|
+
}
|
|
843
507
|
|
|
844
|
-
|
|
508
|
+
if (!this.env && this.tags.env !== undefined) {
|
|
509
|
+
setAndTrack(this, 'env', this.tags.env)
|
|
510
|
+
}
|
|
845
511
|
|
|
846
|
-
|
|
512
|
+
if (!this.version) {
|
|
513
|
+
setAndTrack(this, 'version', this.tags.version || pkg.version)
|
|
514
|
+
this.tags.version ??= pkg.version
|
|
515
|
+
}
|
|
847
516
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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)
|
|
517
|
+
let isServiceNameInferred = false
|
|
518
|
+
if (!trackedConfigOrigins.has('service')) {
|
|
519
|
+
if (this.tags.service) {
|
|
520
|
+
setAndTrack(this, 'service', this.tags.service)
|
|
521
|
+
} else {
|
|
522
|
+
const NX_TASK_TARGET_PROJECT = getEnvironmentVariable('NX_TASK_TARGET_PROJECT')
|
|
523
|
+
if (NX_TASK_TARGET_PROJECT) {
|
|
524
|
+
if (this.DD_ENABLE_NX_SERVICE_NAME) {
|
|
525
|
+
setAndTrack(this, 'service', NX_TASK_TARGET_PROJECT)
|
|
526
|
+
isServiceNameInferred = true
|
|
527
|
+
} else if (DD_MAJOR < 6) {
|
|
528
|
+
log.warn(
|
|
529
|
+
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
530
|
+
'NX_TASK_TARGET_PROJECT is set but no service name was configured. In v6, NX_TASK_TARGET_PROJECT will ' +
|
|
531
|
+
'be used as the default service name. Set DD_ENABLE_NX_SERVICE_NAME=true to opt-in to this behavior ' +
|
|
532
|
+
'now, or set a service name explicitly.'
|
|
533
|
+
)
|
|
534
|
+
}
|
|
535
|
+
}
|
|
893
536
|
}
|
|
894
|
-
|
|
895
|
-
|
|
537
|
+
|
|
538
|
+
if (!this.service) {
|
|
539
|
+
const serverlessName = IS_SERVERLESS
|
|
540
|
+
? (
|
|
541
|
+
getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') ||
|
|
542
|
+
getEnvironmentVariable('FUNCTION_NAME') || // Google Cloud Function Name set by deprecated runtimes
|
|
543
|
+
getEnvironmentVariable('K_SERVICE') || // Google Cloud Function Name set by newer runtimes
|
|
544
|
+
getEnvironmentVariable('WEBSITE_SITE_NAME') // set by Azure Functions
|
|
545
|
+
)
|
|
546
|
+
: undefined
|
|
547
|
+
|
|
548
|
+
setAndTrack(this, 'service', serverlessName || pkg.name || 'node')
|
|
549
|
+
this.tags.service ??= /** @type {string} */ (this.service)
|
|
550
|
+
isServiceNameInferred = true
|
|
896
551
|
}
|
|
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)
|
|
923
|
-
}
|
|
924
|
-
setBoolean(opts, 'dsmEnabled', options.dsmEnabled)
|
|
925
|
-
opts['dynamicInstrumentation.captureTimeoutMs'] = maybeInt(options.dynamicInstrumentation?.captureTimeoutMs)
|
|
926
|
-
this.#optsUnprocessed['dynamicInstrumentation.captureTimeoutMs'] = options.dynamicInstrumentation?.captureTimeoutMs
|
|
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
|
|
985
|
-
}
|
|
986
|
-
setBoolean(opts, 'iast.stackTrace.enabled', options.iast?.stackTrace?.enabled)
|
|
987
|
-
setString(opts, 'iast.telemetryVerbosity', options.iast && options.iast.telemetryVerbosity)
|
|
988
|
-
setBoolean(opts, 'isCiVisibility', options.isCiVisibility)
|
|
989
|
-
setBoolean(opts, 'legacyBaggageEnabled', options.legacyBaggageEnabled)
|
|
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)
|
|
1002
552
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
setBoolean(opts, 'runtimeMetrics.gc', options.runtimeMetrics?.gc)
|
|
1012
|
-
setBoolean(opts, 'runtimeMetricsRuntimeId', options.runtimeMetricsRuntimeId)
|
|
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)
|
|
553
|
+
|
|
554
|
+
// This should not be tracked.
|
|
555
|
+
// TODO: Consider moving this outside of the config.
|
|
556
|
+
set(this, 'isServiceNameInferred', isServiceNameInferred)
|
|
557
|
+
|
|
558
|
+
// Add missing tags, in case they are defined otherwise.
|
|
559
|
+
if (this.service) {
|
|
560
|
+
this.tags.service = this.service
|
|
1021
561
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
if (options.spanAttributeSchema) {
|
|
1025
|
-
setString(opts, 'spanAttributeSchema', validateNamingVersion(options.spanAttributeSchema))
|
|
1026
|
-
this.#optsUnprocessed.spanAttributeSchema = options.spanAttributeSchema
|
|
562
|
+
if (this.env) {
|
|
563
|
+
this.tags.env = this.env
|
|
1027
564
|
}
|
|
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))
|
|
565
|
+
if (this.version) {
|
|
566
|
+
this.tags.version = this.version
|
|
1045
567
|
}
|
|
568
|
+
this.tags['runtime-id'] = RUNTIME_ID
|
|
1046
569
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
if (this.#env['llmobs.enabled'] == null && options.llmobs) {
|
|
1052
|
-
setBoolean(opts, 'llmobs.enabled', true)
|
|
570
|
+
if (IS_SERVERLESS) {
|
|
571
|
+
setAndTrack(this, 'telemetry.enabled', false)
|
|
572
|
+
setAndTrack(this, 'crashtracking.enabled', false)
|
|
573
|
+
setAndTrack(this, 'remoteConfig.enabled', false)
|
|
1053
574
|
}
|
|
1054
|
-
}
|
|
1055
575
|
|
|
1056
|
-
|
|
1057
|
-
|
|
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
|
-
|
|
1095
|
-
#isTraceStatsComputationEnabled () {
|
|
1096
|
-
const apmTracingEnabled = this.#options.apmTracingEnabled !== false &&
|
|
1097
|
-
this.#env.apmTracingEnabled !== false
|
|
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)
|
|
576
|
+
// TODO: Should this unconditionally be disabled?
|
|
577
|
+
if (getEnvironmentVariable('JEST_WORKER_ID') && !trackedConfigOrigins.has('telemetry.enabled')) {
|
|
578
|
+
setAndTrack(this, 'telemetry.enabled', false)
|
|
579
|
+
}
|
|
1121
580
|
|
|
1122
581
|
// Experimental agentless APM span intake
|
|
1123
582
|
// When enabled, sends spans directly to Datadog intake without an agent
|
|
1124
|
-
|
|
583
|
+
// TODO: Replace this with a proper configuration
|
|
584
|
+
const agentlessEnabled = isTrue(getEnvironmentVariable('_DD_APM_TRACING_AGENTLESS_ENABLED'))
|
|
1125
585
|
if (agentlessEnabled) {
|
|
1126
|
-
|
|
1127
|
-
// Disable rate limiting - server-side sampling will be used
|
|
1128
|
-
calc['sampler.rateLimit'] = -1
|
|
586
|
+
setAndTrack(this, 'experimental.exporter', 'agentless')
|
|
1129
587
|
// Disable client-side stats computation
|
|
1130
|
-
|
|
588
|
+
setAndTrack(this, 'stats.enabled', false)
|
|
1131
589
|
// Enable hostname reporting
|
|
1132
|
-
|
|
590
|
+
setAndTrack(this, 'reportHostname', true)
|
|
591
|
+
// Disable rate limiting - server-side sampling will be used
|
|
592
|
+
setAndTrack(this, 'sampler.rateLimit', -1)
|
|
1133
593
|
// Clear sampling rules - server-side sampling handles this
|
|
1134
|
-
|
|
594
|
+
setAndTrack(this, 'sampler.rules', [])
|
|
1135
595
|
// 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)
|
|
596
|
+
if (!trackedConfigOrigins.has('traceId128BitGenerationEnabled')) {
|
|
597
|
+
setAndTrack(this, 'traceId128BitGenerationEnabled', false)
|
|
598
|
+
}
|
|
1162
599
|
}
|
|
1163
600
|
|
|
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)
|
|
601
|
+
// Apply all fallbacks to the calculated config.
|
|
602
|
+
for (const [configName, alias] of fallbackConfigurations) {
|
|
603
|
+
if (!trackedConfigOrigins.has(configName) && trackedConfigOrigins.has(alias)) {
|
|
604
|
+
setAndTrack(this, configName, this[alias])
|
|
1182
605
|
}
|
|
1183
606
|
}
|
|
1184
607
|
|
|
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
|
|
608
|
+
const DEFAULT_OTLP_PORT = '4318'
|
|
609
|
+
if (!this.otelLogsUrl) {
|
|
610
|
+
setAndTrack(this, 'otelLogsUrl', `http://${agentHostname}:${DEFAULT_OTLP_PORT}`)
|
|
1193
611
|
}
|
|
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
|
|
612
|
+
if (!this.otelMetricsUrl) {
|
|
613
|
+
setAndTrack(this, 'otelMetricsUrl', `http://${agentHostname}:${DEFAULT_OTLP_PORT}/v1/metrics`)
|
|
1220
614
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
if (!changeTracker[name]) {
|
|
1228
|
-
changeTracker[name] = {}
|
|
615
|
+
if (!trackedConfigOrigins.has('otelTracesUrl') && this.OTEL_EXPORTER_OTLP_ENDPOINT) {
|
|
616
|
+
// Generic OTLP endpoint: per spec, append /v1/traces signal-specific subpath
|
|
617
|
+
setAndTrack(this, 'otelTracesUrl', this.OTEL_EXPORTER_OTLP_ENDPOINT.replace(/\/$/, '') + '/v1/traces')
|
|
618
|
+
} else if (!this.otelTracesUrl) {
|
|
619
|
+
const tracesHostname = agentHostname === '127.0.0.1' ? 'localhost' : agentHostname
|
|
620
|
+
setAndTrack(this, 'otelTracesUrl', `http://${tracesHostname}:${DEFAULT_OTLP_PORT}/v1/traces`)
|
|
1229
621
|
}
|
|
1230
622
|
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
623
|
+
if (process.platform === 'win32') {
|
|
624
|
+
// OOM monitoring does not work properly on Windows, so it will be disabled.
|
|
625
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED')
|
|
626
|
+
// Profiler sampling contexts are not available on Windows, so features
|
|
627
|
+
// depending on those (code hotspots and endpoint collection) need to be disabled on Windows.
|
|
628
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_CODEHOTSPOTS_ENABLED')
|
|
629
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_ENDPOINT_COLLECTION_ENABLED')
|
|
630
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_CPU_ENABLED')
|
|
631
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_TIMELINE_ENABLED')
|
|
632
|
+
deactivateIfEnabledAndWarnOnWindows(this, 'DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED')
|
|
1241
633
|
}
|
|
1242
|
-
}
|
|
1243
634
|
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
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)
|
|
635
|
+
// Single tags update is tracked as a calculated value.
|
|
636
|
+
setAndTrack(this, 'tags', this.tags)
|
|
637
|
+
|
|
638
|
+
telemetry.updateConfig([...configWithOrigin.values()], this)
|
|
1271
639
|
}
|
|
1272
640
|
|
|
641
|
+
// TODO: Move outside of config. This is unrelated to the config system.
|
|
1273
642
|
#loadGitMetadata () {
|
|
1274
|
-
//
|
|
1275
|
-
this.repositoryUrl = removeUserSensitiveInfo(
|
|
1276
|
-
|
|
1277
|
-
)
|
|
1278
|
-
this.commitSHA = getEnv('DD_GIT_COMMIT_SHA') ?? this.tags[GIT_COMMIT_SHA]
|
|
643
|
+
// Try to read Git metadata from the environment variables
|
|
644
|
+
this.repositoryUrl = removeUserSensitiveInfo(this.DD_GIT_REPOSITORY_URL ?? this.tags[GIT_REPOSITORY_URL])
|
|
645
|
+
this.commitSHA = this.DD_GIT_COMMIT_SHA ?? this.tags[GIT_COMMIT_SHA]
|
|
1279
646
|
|
|
1280
|
-
//
|
|
647
|
+
// Otherwise, try to read Git metadata from the git.properties file
|
|
1281
648
|
if (!this.repositoryUrl || !this.commitSHA) {
|
|
1282
|
-
const DD_GIT_PROPERTIES_FILE =
|
|
649
|
+
const DD_GIT_PROPERTIES_FILE = this.DD_GIT_PROPERTIES_FILE
|
|
1283
650
|
const gitPropertiesFile = DD_GIT_PROPERTIES_FILE ?? `${process.cwd()}/git.properties`
|
|
1284
|
-
let gitPropertiesString
|
|
1285
651
|
try {
|
|
1286
|
-
gitPropertiesString = fs.readFileSync(gitPropertiesFile, 'utf8')
|
|
1287
|
-
|
|
652
|
+
const gitPropertiesString = fs.readFileSync(gitPropertiesFile, 'utf8')
|
|
653
|
+
const { commitSHA, repositoryUrl } = getGitMetadataFromGitProperties(gitPropertiesString)
|
|
654
|
+
this.commitSHA ??= commitSHA
|
|
655
|
+
this.repositoryUrl ??= repositoryUrl
|
|
656
|
+
} catch (error) {
|
|
1288
657
|
// Only log error if the user has set a git.properties path
|
|
1289
658
|
if (DD_GIT_PROPERTIES_FILE) {
|
|
1290
|
-
log.error('Error reading DD_GIT_PROPERTIES_FILE: %s', gitPropertiesFile,
|
|
659
|
+
log.error('Error reading DD_GIT_PROPERTIES_FILE: %s', gitPropertiesFile, error)
|
|
1291
660
|
}
|
|
1292
661
|
}
|
|
1293
|
-
if (gitPropertiesString) {
|
|
1294
|
-
const { commitSHA, repositoryUrl } = getGitMetadataFromGitProperties(gitPropertiesString)
|
|
1295
|
-
this.commitSHA = this.commitSHA || commitSHA
|
|
1296
|
-
this.repositoryUrl = this.repositoryUrl || repositoryUrl
|
|
1297
|
-
}
|
|
1298
662
|
}
|
|
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
|
-
}
|
|
663
|
+
|
|
664
|
+
// Otherwise, try to read Git metadata from the .git/ folder
|
|
665
|
+
const DD_GIT_FOLDER_PATH = this.DD_GIT_FOLDER_PATH
|
|
666
|
+
const gitFolderPath = DD_GIT_FOLDER_PATH ?? path.join(process.cwd(), '.git')
|
|
667
|
+
|
|
668
|
+
if (!this.repositoryUrl) {
|
|
669
|
+
// Try to read git config (repository URL)
|
|
670
|
+
const gitConfigPath = path.join(gitFolderPath, 'config')
|
|
671
|
+
try {
|
|
672
|
+
const gitConfigContent = fs.readFileSync(gitConfigPath, 'utf8')
|
|
673
|
+
if (gitConfigContent) {
|
|
674
|
+
this.repositoryUrl = getRemoteOriginURL(gitConfigContent)
|
|
1316
675
|
}
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
if (gitHeadSha) {
|
|
1322
|
-
this.commitSHA = gitHeadSha
|
|
676
|
+
} catch (error) {
|
|
677
|
+
// Only log error if the user has set a .git/ path
|
|
678
|
+
if (DD_GIT_FOLDER_PATH) {
|
|
679
|
+
log.error('Error reading git config: %s', gitConfigPath, error)
|
|
1323
680
|
}
|
|
1324
681
|
}
|
|
1325
682
|
}
|
|
683
|
+
// Try to read git HEAD (commit SHA)
|
|
684
|
+
this.commitSHA ??= resolveGitHeadSHA(gitFolderPath)
|
|
1326
685
|
}
|
|
1327
686
|
}
|
|
1328
687
|
|
|
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
688
|
/**
|
|
1363
|
-
*
|
|
1364
|
-
* @param {
|
|
1365
|
-
* @param {string} [value] - The value of the environment variable
|
|
1366
|
-
* @returns {boolean} - True if the value is valid, false otherwise
|
|
689
|
+
* @param {Config} config
|
|
690
|
+
* @param {ConfigKey} envVar
|
|
1367
691
|
*/
|
|
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()
|
|
1401
|
-
}
|
|
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()
|
|
692
|
+
function deactivateIfEnabledAndWarnOnWindows (config, envVar) {
|
|
693
|
+
if (config[envVar]) {
|
|
694
|
+
const source = trackedConfigOrigins.get(envVar)
|
|
695
|
+
setAndTrack(config, envVar, false)
|
|
696
|
+
// TODO: Should we log even for default values?
|
|
697
|
+
if (source) {
|
|
698
|
+
log.warn('%s is not supported on Windows. Deactivating. (source: %s)', envVar, source)
|
|
1406
699
|
}
|
|
1407
700
|
}
|
|
1408
701
|
}
|
|
1409
702
|
|
|
1410
|
-
function
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
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
|
-
}
|
|
1443
|
-
return versionString
|
|
1444
|
-
}
|
|
1445
|
-
|
|
1446
|
-
/**
|
|
1447
|
-
* Given a string of comma-separated paths, return the array of paths.
|
|
1448
|
-
* If a blank path is provided a null is returned to signal that the feature is disabled.
|
|
1449
|
-
* An empty array means the feature is enabled but that no rules need to be applied.
|
|
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
|
|
703
|
+
function increaseCounter (event, ddVar, otelVar) {
|
|
704
|
+
const tags = []
|
|
705
|
+
if (ddVar) {
|
|
706
|
+
tags.push(`config_datadog:${ddVar.toLowerCase()}`)
|
|
1466
707
|
}
|
|
1467
|
-
|
|
708
|
+
tags.push(`config_opentelemetry:${otelVar.toLowerCase()}`)
|
|
709
|
+
tracerMetrics.count(event, tags).inc()
|
|
1468
710
|
}
|
|
1469
711
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
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())
|
|
712
|
+
function getFromOtelSamplerMap (otelTracesSampler, otelTracesSamplerArg) {
|
|
713
|
+
const NON_PARENTBASED_TO_PARENTBASED = {
|
|
714
|
+
always_on: 'parentbased_always_on',
|
|
715
|
+
always_off: 'parentbased_always_off',
|
|
716
|
+
traceidratio: 'parentbased_traceidratio',
|
|
1482
717
|
}
|
|
1483
|
-
|
|
1484
|
-
|
|
718
|
+
const OTEL_TRACES_SAMPLER_MAPPING = {
|
|
719
|
+
parentbased_always_on: 1,
|
|
720
|
+
parentbased_always_off: 0,
|
|
1485
721
|
}
|
|
1486
|
-
}
|
|
1487
722
|
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
log.warn(
|
|
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'
|
|
723
|
+
const parentBasedEquivalent = NON_PARENTBASED_TO_PARENTBASED[otelTracesSampler]
|
|
724
|
+
if (parentBasedEquivalent) {
|
|
725
|
+
log.info(
|
|
726
|
+
'OTEL_TRACES_SAMPLER=%s does not respect upstream sampling decisions; using parent-based equivalent %s instead',
|
|
727
|
+
otelTracesSampler, parentBasedEquivalent
|
|
1496
728
|
)
|
|
729
|
+
otelTracesSampler = parentBasedEquivalent
|
|
1497
730
|
}
|
|
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
731
|
|
|
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')
|
|
732
|
+
const result = OTEL_TRACES_SAMPLER_MAPPING[otelTracesSampler] ?? otelTracesSamplerArg
|
|
733
|
+
if (result === undefined) {
|
|
734
|
+
increaseCounter('otel.env.invalid', 'DD_TRACE_SAMPLE_RATE', 'OTEL_TRACES_SAMPLER')
|
|
1517
735
|
}
|
|
1518
|
-
return
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
function isCiVisibilityItrEnabled () {
|
|
1522
|
-
return getEnv('DD_CIVISIBILITY_ITR_ENABLED') ?? true
|
|
736
|
+
return result
|
|
1523
737
|
}
|
|
1524
738
|
|
|
1525
|
-
function
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
739
|
+
function warnWrongOtelSettings () {
|
|
740
|
+
// This mostly works for non-aliased environment variables only.
|
|
741
|
+
// TODO: Adjust this to work across all sources.
|
|
742
|
+
for (const [otelEnvVar, ddEnvVar, key] of [
|
|
743
|
+
// eslint-disable-next-line eslint-rules/eslint-env-aliases
|
|
744
|
+
['OTEL_LOG_LEVEL', 'DD_TRACE_LOG_LEVEL', 'logLevel'],
|
|
745
|
+
// eslint-disable-next-line eslint-rules/eslint-env-aliases
|
|
746
|
+
['OTEL_PROPAGATORS', 'DD_TRACE_PROPAGATION_STYLE', 'DD_TRACE_PROPAGATION_STYLE'],
|
|
747
|
+
// eslint-disable-next-line eslint-rules/eslint-env-aliases
|
|
748
|
+
['OTEL_SERVICE_NAME', 'DD_SERVICE', 'service'],
|
|
749
|
+
['OTEL_TRACES_SAMPLER', 'DD_TRACE_SAMPLE_RATE'],
|
|
750
|
+
['OTEL_TRACES_SAMPLER_ARG', 'DD_TRACE_SAMPLE_RATE'],
|
|
751
|
+
['OTEL_TRACES_EXPORTER', 'DD_TRACE_ENABLED'],
|
|
752
|
+
['OTEL_METRICS_EXPORTER', 'DD_RUNTIME_METRICS_ENABLED'],
|
|
753
|
+
['OTEL_RESOURCE_ATTRIBUTES', 'DD_TAGS'],
|
|
754
|
+
['OTEL_SDK_DISABLED', 'DD_TRACE_OTEL_ENABLED'],
|
|
755
|
+
['OTEL_LOGS_EXPORTER'],
|
|
756
|
+
]) {
|
|
757
|
+
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
758
|
+
const envs = process.env
|
|
759
|
+
const otelSource = trackedConfigOrigins.get(/** @type {ConfigPath} */ (key ?? otelEnvVar))
|
|
760
|
+
const otelEnvValue = envs[otelEnvVar]
|
|
761
|
+
if (otelEnvValue) {
|
|
762
|
+
if (envs[ddEnvVar]) {
|
|
763
|
+
log.warn('Conflicting %s and %s environment variables are set for %s', ddEnvVar, otelEnvVar, otelSource)
|
|
764
|
+
increaseCounter('otel.env.hiding', ddEnvVar, otelEnvVar)
|
|
1531
765
|
}
|
|
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
766
|
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
const [key, val] = item.split(':').map(part => part.trim())
|
|
1572
|
-
return val === undefined ? key : `${key}:${val}`
|
|
1573
|
-
})
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
if (Array.isArray(value)) {
|
|
1577
|
-
obj[name] = value
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
function setIntegerRangeSet (obj, name, value) {
|
|
1582
|
-
if (value == null) {
|
|
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)
|
|
767
|
+
const invalidOtelValue = !otelSource
|
|
768
|
+
if (invalidOtelValue) {
|
|
769
|
+
increaseCounter('otel.env.invalid', ddEnvVar, otelEnvVar)
|
|
1594
770
|
}
|
|
1595
|
-
} else {
|
|
1596
|
-
result.push(Number(val))
|
|
1597
771
|
}
|
|
1598
772
|
}
|
|
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
773
|
}
|
|
1686
774
|
|
|
775
|
+
/**
|
|
776
|
+
* @param {TracerOptions} [options]
|
|
777
|
+
*/
|
|
1687
778
|
function getConfig (options) {
|
|
1688
779
|
if (!configInstance) {
|
|
1689
780
|
configInstance = new Config(options)
|