dd-trace 5.87.0 → 5.88.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.
Files changed (77) hide show
  1. package/LICENSE-3rdparty.csv +60 -32
  2. package/ext/exporters.d.ts +1 -0
  3. package/ext/exporters.js +1 -0
  4. package/index.d.ts +225 -4
  5. package/package.json +9 -6
  6. package/packages/datadog-instrumentations/src/ai.js +54 -90
  7. package/packages/datadog-instrumentations/src/helpers/hook.js +17 -11
  8. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +55 -14
  9. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +15 -13
  10. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +103 -0
  11. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/bullmq.js +108 -0
  12. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -1
  13. package/packages/datadog-instrumentations/src/helpers/rewriter/transformer.js +21 -0
  14. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +138 -12
  15. package/packages/datadog-instrumentations/src/jest.js +76 -12
  16. package/packages/datadog-instrumentations/src/kafkajs.js +20 -17
  17. package/packages/datadog-instrumentations/src/playwright.js +1 -1
  18. package/packages/datadog-plugin-amqplib/src/consumer.js +14 -10
  19. package/packages/datadog-plugin-amqplib/src/producer.js +23 -19
  20. package/packages/datadog-plugin-bullmq/src/consumer.js +33 -11
  21. package/packages/datadog-plugin-bullmq/src/producer.js +60 -31
  22. package/packages/datadog-plugin-cucumber/src/index.js +9 -6
  23. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +26 -0
  24. package/packages/datadog-plugin-cypress/src/support.js +48 -8
  25. package/packages/datadog-plugin-jest/src/index.js +12 -2
  26. package/packages/datadog-plugin-jest/src/util.js +2 -1
  27. package/packages/datadog-plugin-kafkajs/src/consumer.js +22 -12
  28. package/packages/datadog-plugin-kafkajs/src/producer.js +33 -22
  29. package/packages/datadog-plugin-mocha/src/index.js +9 -6
  30. package/packages/datadog-plugin-playwright/src/index.js +10 -6
  31. package/packages/datadog-plugin-vitest/src/index.js +13 -8
  32. package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +1 -1
  33. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +1 -1
  34. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +1 -1
  35. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +4 -5
  36. package/packages/dd-trace/src/appsec/iast/path-line.js +36 -25
  37. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +1 -1
  38. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -4
  39. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +3 -2
  40. package/packages/dd-trace/src/azure_metadata.js +0 -2
  41. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
  42. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -0
  43. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +1 -1
  44. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -1
  45. package/packages/dd-trace/src/ci-visibility/requests/request.js +236 -0
  46. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
  47. package/packages/dd-trace/src/config/defaults.js +148 -197
  48. package/packages/dd-trace/src/config/helper.js +43 -1
  49. package/packages/dd-trace/src/config/index.js +36 -14
  50. package/packages/dd-trace/src/config/supported-configurations.json +4115 -512
  51. package/packages/dd-trace/src/constants.js +0 -2
  52. package/packages/dd-trace/src/crashtracking/crashtracker.js +10 -3
  53. package/packages/dd-trace/src/datastreams/pathway.js +22 -3
  54. package/packages/dd-trace/src/datastreams/processor.js +14 -1
  55. package/packages/dd-trace/src/encode/agentless-json.js +141 -0
  56. package/packages/dd-trace/src/exporter.js +2 -0
  57. package/packages/dd-trace/src/exporters/agent/writer.js +22 -8
  58. package/packages/dd-trace/src/exporters/agentless/index.js +89 -0
  59. package/packages/dd-trace/src/exporters/agentless/writer.js +184 -0
  60. package/packages/dd-trace/src/exporters/common/request.js +4 -4
  61. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -3
  62. package/packages/dd-trace/src/opentelemetry/context_manager.js +19 -46
  63. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +3 -4
  64. package/packages/dd-trace/src/opentracing/propagation/text_map.js +3 -5
  65. package/packages/dd-trace/src/opentracing/span.js +6 -4
  66. package/packages/dd-trace/src/plugins/ci_plugin.js +57 -5
  67. package/packages/dd-trace/src/plugins/database.js +15 -2
  68. package/packages/dd-trace/src/plugins/util/test.js +48 -0
  69. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -0
  70. package/packages/dd-trace/src/propagation-hash/index.js +145 -0
  71. package/packages/dd-trace/src/proxy.js +4 -0
  72. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +1 -1
  73. package/packages/dd-trace/src/startup-log.js +1 -1
  74. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/bullmq.json +0 -106
  75. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +0 -741
  76. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +0 -11
  77. package/packages/dd-trace/src/scope/noop/scope.js +0 -21
@@ -1,15 +1,12 @@
1
1
  'use strict'
2
2
 
3
3
  const pkg = require('../pkg')
4
- const { GRPC_CLIENT_ERROR_STATUSES, GRPC_SERVER_ERROR_STATUSES } = require('../constants')
4
+ const { isFalse, isTrue } = require('../util')
5
5
  const { getEnvironmentVariable: getEnv } = require('./helper')
6
6
 
7
- // eslint-disable-next-line @stylistic/max-len
8
- const qsRegex = String.raw`(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\s|%20)*(?::|%3A)(?:\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\s|%20)+[a-z0-9\._\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\w=-]|%3D)+\.ey[I-L](?:[\w=-]|%3D)+(?:\.(?:[\w.+\/=-]|%3D|%2F|%2B)+)?|[\-]{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY[\-]{5}[^\-]+[\-]{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY|ssh-rsa(?:\s|%20)*(?:[a-z0-9\/\.+]|%2F|%5C|%2B){100,}`
9
- // eslint-disable-next-line @stylistic/max-len
10
- const defaultWafObfuscatorKeyRegex = String.raw`(?i)pass|pw(?:or)?d|secret|(?:api|private|public|access)[_-]?key|token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization|jsessionid|phpsessid|asp\.net[_-]sessionid|sid|jwt`
11
- // eslint-disable-next-line @stylistic/max-len
12
- const defaultWafObfuscatorValueRegex = String.raw`(?i)(?:p(?:ass)?w(?:or)?d|pass(?:[_-]?phrase)?|secret(?:[_-]?key)?|(?:(?:api|private|public|access)[_-]?)key(?:[_-]?id)?|(?:(?:auth|access|id|refresh)[_-]?)?token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|jsessionid|phpsessid|asp\.net(?:[_-]|-)sessionid|sid|jwt)(?:\s*=([^;&]+)|"\s*:\s*("[^"]+"|\d+))|bearer\s+([a-z0-9\._\-]+)|token\s*:\s*([a-z0-9]{13})|gh[opsu]_([0-9a-zA-Z]{36})|ey[I-L][\w=-]+\.(ey[I-L][\w=-]+(?:\.[\w.+\/=-]+)?)|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY[\-]{5}([^\-]+)[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*([a-z0-9\/\.+]{100,})`
7
+ const {
8
+ supportedConfigurations,
9
+ } = /** @type {import('./helper').SupportedConfigurationsJson} */ (require('./supported-configurations.json'))
13
10
 
14
11
  const service = getEnv('AWS_LAMBDA_FUNCTION_NAME') ||
15
12
  getEnv('FUNCTION_NAME') || // Google Cloud Function Name set by deprecated runtimes
@@ -18,206 +15,160 @@ const service = getEnv('AWS_LAMBDA_FUNCTION_NAME') ||
18
15
  pkg.name ||
19
16
  'node'
20
17
 
21
- module.exports = {
22
- apiKey: undefined,
23
- appKey: undefined,
24
- apmTracingEnabled: true,
25
- 'appsec.apiSecurity.enabled': true,
26
- 'appsec.apiSecurity.sampleDelay': 30,
27
- 'appsec.apiSecurity.endpointCollectionEnabled': true,
28
- 'appsec.apiSecurity.endpointCollectionMessageLimit': 300,
29
- 'appsec.apiSecurity.downstreamBodyAnalysisSampleRate': 0.5,
30
- 'appsec.apiSecurity.maxDownstreamRequestBodyAnalysis': 1,
31
- 'appsec.blockedTemplateGraphql': undefined,
32
- 'appsec.blockedTemplateHtml': undefined,
33
- 'appsec.blockedTemplateJson': undefined,
34
- 'appsec.enabled': undefined,
35
- 'appsec.eventTracking.mode': 'identification',
36
- // TODO appsec.extendedHeadersCollection is deprecated, to delete in a major
37
- 'appsec.extendedHeadersCollection.enabled': false,
38
- 'appsec.extendedHeadersCollection.redaction': true,
39
- 'appsec.extendedHeadersCollection.maxHeaders': 50,
40
- 'appsec.obfuscatorKeyRegex': defaultWafObfuscatorKeyRegex,
41
- 'appsec.obfuscatorValueRegex': defaultWafObfuscatorValueRegex,
42
- 'appsec.rasp.enabled': true,
43
- // TODO Deprecated, to delete in a major
44
- 'appsec.rasp.bodyCollection': false,
45
- 'appsec.rateLimit': 100,
46
- 'appsec.rules': undefined,
47
- 'appsec.sca.enabled': null,
48
- 'appsec.stackTrace.enabled': true,
49
- 'appsec.stackTrace.maxDepth': 32,
50
- 'appsec.stackTrace.maxStackTraces': 2,
51
- 'appsec.wafTimeout': 5e3, // µs
52
- baggageMaxBytes: 8192,
53
- baggageMaxItems: 64,
54
- baggageTagKeys: 'user.id,session.id,account.id',
55
- clientIpEnabled: false,
56
- clientIpHeader: null,
18
+ /**
19
+ * @param {string|null} raw
20
+ * @param {string} type
21
+ * @returns {string|number|boolean|Record<string, string>|unknown[]|undefined}
22
+ */
23
+ function parseDefaultByType (raw, type) {
24
+ if (raw === null) {
25
+ return
26
+ }
27
+
28
+ switch (type) {
29
+ case 'boolean':
30
+ if (isTrue(raw)) return true
31
+ if (isFalse(raw)) return false
32
+ // TODO: What should we do with these?
33
+ return
34
+ case 'int':
35
+ case 'decimal': {
36
+ return Number(raw)
37
+ }
38
+ case 'array': {
39
+ if (!raw || raw.length === 0) return []
40
+ // TODO: Make the parsing a helper that is reused.
41
+ return raw.split(',').map(item => {
42
+ const colonIndex = item.indexOf(':')
43
+ if (colonIndex === -1) {
44
+ return item.trim()
45
+ }
46
+ const key = item.slice(0, colonIndex).trim()
47
+ const value = item.slice(colonIndex + 1).trim()
48
+ return `${key}:${value}`
49
+ })
50
+ }
51
+ case 'map': {
52
+ if (!raw || raw.length === 0) return {}
53
+ // TODO: Make the parsing a helper that is reused.
54
+ /** @type {Record<string, string>} */
55
+ const entries = {}
56
+ for (const item of raw.split(',')) {
57
+ const colonIndex = item.indexOf(':')
58
+ if (colonIndex === -1) {
59
+ const key = item.trim()
60
+ if (key.length > 0) {
61
+ entries[key] = ''
62
+ }
63
+ continue
64
+ }
65
+ const key = item.slice(0, colonIndex).trim()
66
+ const value = item.slice(colonIndex + 1).trim()
67
+ if (key.length > 0) {
68
+ entries[key] = value
69
+ }
70
+ }
71
+ return entries
72
+ }
73
+ default:
74
+ return raw
75
+ }
76
+ }
77
+
78
+ /** @type {Record<string, unknown>} */
79
+ const metadataDefaults = {}
80
+ for (const entries of Object.values(supportedConfigurations)) {
81
+ for (const entry of entries) {
82
+ // TODO: Replace $dynamic with method names that would be called and that
83
+ // are also called when the user passes through the value. That way the
84
+ // handling is unified and methods can be declared as default.
85
+ // The name of that method should be expressive for users.
86
+ // TODO: Add handling for all environment variable names. They should not
87
+ // need a configuration name for being listed with their default.
88
+ if (!Array.isArray(entry.configurationNames)) {
89
+ continue
90
+ }
91
+
92
+ const parsedValue = parseDefaultByType(entry.default, entry.type)
93
+ for (const configurationName of entry.configurationNames) {
94
+ metadataDefaults[configurationName] = entry.default === null ? undefined : parsedValue
95
+ }
96
+ }
97
+ }
98
+
99
+ // Defaults required by JS config merge/applyCalculated that are not represented in supported-configurations.
100
+ const defaultsWithoutSupportedConfigurationEntry = {
101
+ 'cloudPayloadTagging.rules': [],
57
102
  'cloudPayloadTagging.requestsEnabled': false,
58
103
  'cloudPayloadTagging.responsesEnabled': false,
59
- 'cloudPayloadTagging.maxDepth': 10,
60
- 'cloudPayloadTagging.rules': [],
61
- 'crashtracking.enabled': true,
62
- 'codeOriginForSpans.enabled': true,
63
- 'codeOriginForSpans.experimental.exit_spans.enabled': false,
64
- dbmPropagationMode: 'disabled',
65
- 'dogstatsd.hostname': '127.0.0.1',
66
- 'dogstatsd.port': '8125',
67
- dsmEnabled: false,
68
- 'dynamicInstrumentation.captureTimeoutMs': 15,
69
- 'dynamicInstrumentation.enabled': false,
70
- 'dynamicInstrumentation.probeFile': undefined,
71
- 'dynamicInstrumentation.redactedIdentifiers': [],
72
- 'dynamicInstrumentation.redactionExcludedIdentifiers': [],
73
- 'dynamicInstrumentation.uploadIntervalSeconds': 1,
74
- env: undefined,
75
- 'experimental.aiguard.enabled': false,
76
- 'experimental.aiguard.endpoint': undefined,
77
- 'experimental.aiguard.maxMessagesLength': 16,
78
- 'experimental.aiguard.maxContentSize': 512 * 1024,
79
- 'experimental.aiguard.timeout': 10_000, // ms
80
- 'experimental.enableGetRumData': false,
81
- 'experimental.exporter': undefined,
82
- 'experimental.flaggingProvider.enabled': false,
83
- 'experimental.flaggingProvider.initializationTimeoutMs': 30_000,
84
- flushInterval: 2000,
85
- flushMinSpans: 1000,
86
- gitMetadataEnabled: true,
87
- graphqlErrorExtensions: [],
88
- 'grpc.client.error.statuses': GRPC_CLIENT_ERROR_STATUSES,
89
- 'grpc.server.error.statuses': GRPC_SERVER_ERROR_STATUSES,
90
- headerTags: [],
91
- 'heapSnapshot.count': 0,
92
- 'heapSnapshot.destination': '',
93
- 'heapSnapshot.interval': 3600,
94
- hostname: '127.0.0.1',
95
- 'iast.dbRowsToTaint': 1,
96
- 'iast.deduplicationEnabled': true,
97
- 'iast.enabled': false,
98
- 'iast.maxConcurrentRequests': 2,
99
- 'iast.maxContextOperations': 2,
100
- 'iast.redactionEnabled': true,
101
- 'iast.redactionNamePattern': null,
102
- 'iast.redactionValuePattern': null,
103
- 'iast.requestSampling': 30,
104
- 'iast.securityControlsConfiguration': null,
105
- 'iast.telemetryVerbosity': 'INFORMATION',
106
- 'iast.stackTrace.enabled': true,
107
- injectionEnabled: [],
108
- 'installSignature.id': null,
109
- 'installSignature.time': null,
110
- 'installSignature.type': null,
111
- instrumentationSource: 'manual',
112
- injectForce: null,
113
104
  isAzureFunction: false,
114
105
  isCiVisibility: false,
115
- isEarlyFlakeDetectionEnabled: false,
116
- isFlakyTestRetriesEnabled: false,
117
- flakyTestRetriesCount: 5,
118
106
  isGCPFunction: false,
119
- isGCPPubSubPushSubscriptionEnabled: true,
107
+ instrumentationSource: 'manual',
108
+ isServiceUserProvided: false,
109
+ lookup: undefined,
110
+ plugins: true,
111
+ }
112
+
113
+ // These values are documented in supported-configurations as CI Visibility
114
+ // defaults. Keep startup baseline false and let #applyCalculated() switch them
115
+ // when CI Visibility is active.
116
+ // TODO: These entries should be removed. They are off by default
117
+ // because they rely on other configs.
118
+ const defaultsWithConditionalRuntimeBehavior = {
120
119
  isGitUploadEnabled: false,
120
+ isImpactedTestsEnabled: false,
121
121
  isIntelligentTestRunnerEnabled: false,
122
122
  isManualApiEnabled: false,
123
- 'langchain.spanCharLimit': 128,
124
- 'langchain.spanPromptCompletionSampleRate': 1,
125
- 'llmobs.agentlessEnabled': undefined,
126
- 'llmobs.enabled': false,
127
- 'llmobs.mlApp': undefined,
128
- ciVisibilityTestSessionName: '',
129
- ciVisAgentlessLogSubmissionEnabled: false,
130
- legacyBaggageEnabled: true,
131
- isTestDynamicInstrumentationEnabled: false,
132
- isServiceUserProvided: false,
133
- testManagementAttemptToFixRetries: 20,
134
123
  isTestManagementEnabled: false,
135
- isImpactedTestsEnabled: false,
136
- logInjection: true,
137
- otelLogsEnabled: false,
138
- otelUrl: undefined,
139
- otelLogsUrl: undefined, // Will be computed using agent host
140
- otelHeaders: undefined,
141
- otelLogsHeaders: '',
142
- otelProtocol: 'http/protobuf',
143
- otelLogsProtocol: 'http/protobuf',
144
- otelLogsTimeout: 10_000,
145
- otelTimeout: 10_000,
146
- otelBatchTimeout: 5000,
147
- otelMaxExportBatchSize: 512,
148
- otelMaxQueueSize: 2048,
149
- otelMetricsEnabled: false,
150
- otelMetricsUrl: undefined, // Will be computed using agent host
151
- otelMetricsHeaders: '',
152
- otelMetricsProtocol: 'http/protobuf',
153
- otelMetricsTimeout: 10_000,
154
- otelMetricsExportTimeout: 7500,
155
- otelMetricsExportInterval: 10_000,
156
- otelMetricsTemporalityPreference: 'DELTA', // DELTA, CUMULATIVE, or LOWMEMORY
157
- lookup: undefined,
158
- inferredProxyServicesEnabled: false,
159
- memcachedCommandEnabled: false,
160
- middlewareTracingEnabled: true,
161
- openAiLogsEnabled: false,
162
- 'openai.spanCharLimit': 128,
163
- peerServiceMapping: {},
164
- plugins: true,
124
+ // TODO: These are not conditional, they would just be of type number.
125
+ 'dogstatsd.port': '8125',
165
126
  port: '8126',
166
- 'profiling.enabled': undefined,
167
- 'propagateProcessTags.enabled': undefined,
168
- 'profiling.exporters': 'agent',
169
- 'profiling.sourceMap': true,
170
- 'profiling.longLivedThreshold': undefined,
171
- protocolVersion: '0.4',
172
- queryStringObfuscation: qsRegex,
173
- 'remoteConfig.enabled': true,
174
- 'remoteConfig.pollInterval': 5, // seconds
175
- reportHostname: false,
176
- resourceRenamingEnabled: false,
177
- 'runtimeMetrics.enabled': false,
178
- 'runtimeMetrics.eventLoop': true,
179
- 'runtimeMetrics.gc': true,
180
- runtimeMetricsRuntimeId: false,
181
- sampleRate: undefined,
182
- 'sampler.rateLimit': 100,
183
- 'sampler.rules': [],
184
- 'sampler.spanSamplingRules': [],
185
- scope: undefined,
127
+ // Override due to expecting numbers, not strings. TODO: Replace later.
128
+ 'grpc.client.error.statuses': [
129
+ 1,
130
+ 2,
131
+ 3,
132
+ 4,
133
+ 5,
134
+ 6,
135
+ 7,
136
+ 8,
137
+ 9,
138
+ 10,
139
+ 11,
140
+ 12,
141
+ 13,
142
+ 14,
143
+ 15,
144
+ 16,
145
+ ],
146
+ 'grpc.server.error.statuses': [
147
+ 2,
148
+ 3,
149
+ 4,
150
+ 5,
151
+ 6,
152
+ 7,
153
+ 8,
154
+ 9,
155
+ 10,
156
+ 11,
157
+ 12,
158
+ 13,
159
+ 14,
160
+ 15,
161
+ 16,
162
+ ],
163
+ }
164
+
165
+ /** @type {Record<string, unknown>} */
166
+ const defaults = {
167
+ ...defaultsWithoutSupportedConfigurationEntry,
168
+ ...metadataDefaults,
169
+ ...defaultsWithConditionalRuntimeBehavior,
186
170
  service,
187
- serviceMapping: {},
188
- site: 'datadoghq.com',
189
- spanAttributeSchema: 'v0',
190
- spanComputePeerService: false,
191
- spanLeakDebug: 0,
192
- spanRemoveIntegrationFromService: false,
193
- startupLogs: false,
194
- 'stats.enabled': false,
195
- tags: {},
196
- tagsHeaderMaxLength: 512,
197
- 'telemetry.debug': false,
198
- 'telemetry.dependencyCollection': true,
199
- 'telemetry.enabled': true,
200
- 'telemetry.heartbeatInterval': 60_000,
201
- 'telemetry.logCollection': true,
202
- 'telemetry.metrics': true,
203
- traceEnabled: true,
204
- traceId128BitGenerationEnabled: true,
205
- traceId128BitLoggingEnabled: true,
206
- tracePropagationExtractFirst: false,
207
- tracePropagationBehaviorExtract: 'continue',
208
- 'tracePropagationStyle.inject': ['datadog', 'tracecontext', 'baggage'],
209
- 'tracePropagationStyle.extract': ['datadog', 'tracecontext', 'baggage'],
210
- 'tracePropagationStyle.otelPropagators': false,
211
- traceWebsocketMessagesEnabled: true,
212
- traceWebsocketMessagesInheritSampling: true,
213
- traceWebsocketMessagesSeparateTraces: true,
214
- tracing: true,
215
- url: undefined,
216
171
  version: pkg.version,
217
- instrumentation_config_id: undefined,
218
- 'vertexai.spanCharLimit': 128,
219
- 'vertexai.spanPromptCompletionSampleRate': 1,
220
- 'trace.aws.addSpanPointers': true,
221
- 'trace.dynamoDb.tablePrimaryKeys': undefined,
222
- 'trace.nativeSpanEvents': false,
223
172
  }
173
+
174
+ module.exports = defaults
@@ -2,8 +2,25 @@
2
2
 
3
3
  /* eslint-disable eslint-rules/eslint-process-env */
4
4
 
5
+ /**
6
+ * @typedef {object} SupportedConfigurationEntry
7
+ * @property {string} implementation
8
+ * @property {string} type
9
+ * @property {string|number|boolean|null|object|unknown[]} default
10
+ * @property {string[]} [aliases]
11
+ * @property {string[]} [configurationNames]
12
+ * @property {string|boolean} [deprecated]
13
+ */
14
+
15
+ /**
16
+ * @typedef {object} SupportedConfigurationsJson
17
+ * @property {Record<`DD_${string}` | `OTEL_${string}`, SupportedConfigurationEntry[]>} supportedConfigurations
18
+ */
19
+
5
20
  const { deprecate } = require('util')
6
- const { supportedConfigurations, aliases, deprecations } = require('./supported-configurations.json')
21
+ const {
22
+ supportedConfigurations,
23
+ } = /** @type {SupportedConfigurationsJson} */ (require('./supported-configurations.json'))
7
24
 
8
25
  /**
9
26
  * Types for environment variable handling.
@@ -12,6 +29,31 @@ const { supportedConfigurations, aliases, deprecations } = require('./supported-
12
29
  * @typedef {Partial<typeof process.env> & Partial<Record<SupportedEnvKey, string|undefined>>} TracerEnv
13
30
  */
14
31
 
32
+ // Backwards-compatible views for old helper logic:
33
+ // - `aliases`: Record<canonicalEnvVar, string[]>
34
+ // - `deprecations`: Record<deprecatedEnvVar, string> (message suffix)
35
+ const aliases = {}
36
+ const deprecations = {}
37
+
38
+ for (const [canonical, configuration] of Object.entries(supportedConfigurations)) {
39
+ for (const implementation of configuration) {
40
+ if (implementation.deprecated) {
41
+ deprecations[canonical] = implementation.deprecated
42
+ // Deprecated entries with an alias may not be listed in the supported configurations map
43
+ if (implementation.aliases) {
44
+ delete supportedConfigurations[canonical]
45
+ continue
46
+ }
47
+ }
48
+ if (Array.isArray(implementation.aliases)) {
49
+ for (const alias of implementation.aliases) {
50
+ aliases[canonical] ??= new Set()
51
+ aliases[canonical].add(alias)
52
+ }
53
+ }
54
+ }
55
+ }
56
+
15
57
  const aliasToCanonical = {}
16
58
  for (const canonical of Object.keys(aliases)) {
17
59
  for (const alias of aliases[canonical]) {
@@ -62,7 +62,7 @@ module.exports = getConfig
62
62
  class Config {
63
63
  /**
64
64
  * parsed DD_TAGS, usable as a standalone tag set across products
65
- * @type {Record<string, string> | undefined}
65
+ * @type {Record<string, string>}
66
66
  */
67
67
  #parsedDdTags = {}
68
68
  #envUnprocessed = {}
@@ -89,6 +89,8 @@ class Config {
89
89
 
90
90
  options = {
91
91
  ...options,
92
+ // TODO(BridgeAR): Remove the experimental prefix once we have a major version.
93
+ // That also applies to index.d.ts
92
94
  appsec: options.appsec == null ? options.experimental?.appsec : options.appsec,
93
95
  iast: options.iast == null ? options.experimental?.iast : options.iast,
94
96
  }
@@ -162,7 +164,7 @@ class Config {
162
164
  * Set the configuration with remote config settings.
163
165
  * Applies remote configuration, recalculates derived values, and merges all configuration sources.
164
166
  *
165
- * @param {import('./config/remote_config').RemoteConfigOptions|null} options - Configurations received via Remote
167
+ * @param {import('./remote_config').RemoteConfigOptions|null} options - Configurations received via Remote
166
168
  * Config or null to reset all remote configuration
167
169
  */
168
170
  setRemoteConfig (options) {
@@ -283,6 +285,7 @@ class Config {
283
285
  DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED,
284
286
  DD_DATA_STREAMS_ENABLED,
285
287
  DD_DBM_PROPAGATION_MODE,
288
+ DD_DBM_INJECT_SQL_BASEHASH,
286
289
  DD_DOGSTATSD_HOST,
287
290
  DD_DOGSTATSD_PORT,
288
291
  DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS,
@@ -368,7 +371,6 @@ class Config {
368
371
  DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
369
372
  DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED,
370
373
  DD_TRACE_GIT_METADATA_ENABLED,
371
- DD_TRACE_GLOBAL_TAGS,
372
374
  DD_TRACE_GRAPHQL_ERROR_EXTENSIONS,
373
375
  DD_TRACE_HEADER_TAGS,
374
376
  DD_TRACE_LEGACY_BAGGAGE_ENABLED,
@@ -435,13 +437,11 @@ class Config {
435
437
 
436
438
  const tags = {}
437
439
 
438
- const parsedDdTags = parseSpaceSeparatedTags(DD_TAGS)
439
- tagger.add(this.#parsedDdTags, parsedDdTags)
440
-
441
440
  tagger.add(tags, parseSpaceSeparatedTags(handleOtel(OTEL_RESOURCE_ATTRIBUTES)))
442
- tagger.add(tags, parsedDdTags)
441
+ tagger.add(tags, parseSpaceSeparatedTags(DD_TAGS))
443
442
  tagger.add(tags, DD_TRACE_TAGS)
444
- tagger.add(tags, DD_TRACE_GLOBAL_TAGS)
443
+
444
+ Object.assign(this.#parsedDdTags, tags)
445
445
 
446
446
  setString(target, 'apiKey', DD_API_KEY)
447
447
  setBoolean(target, 'otelLogsEnabled', DD_LOGS_OTEL_ENABLED)
@@ -548,7 +548,7 @@ class Config {
548
548
  maybeInt(DD_API_SECURITY_MAX_DOWNSTREAM_REQUEST_BODY_ANALYSIS)
549
549
  target.baggageMaxBytes = DD_TRACE_BAGGAGE_MAX_BYTES
550
550
  target.baggageMaxItems = DD_TRACE_BAGGAGE_MAX_ITEMS
551
- target.baggageTagKeys = DD_TRACE_BAGGAGE_TAG_KEYS
551
+ setArray(target, 'baggageTagKeys', DD_TRACE_BAGGAGE_TAG_KEYS)
552
552
  setBoolean(target, 'clientIpEnabled', DD_TRACE_CLIENT_IP_ENABLED)
553
553
  setString(target, 'clientIpHeader', DD_TRACE_CLIENT_IP_HEADER?.toLowerCase())
554
554
  if (DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING || DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING) {
@@ -574,6 +574,7 @@ class Config {
574
574
  DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED
575
575
  )
576
576
  setString(target, 'dbmPropagationMode', DD_DBM_PROPAGATION_MODE)
577
+ setBoolean(target, 'dbm.injectSqlBaseHash', DD_DBM_INJECT_SQL_BASEHASH)
577
578
  setString(target, 'dogstatsd.hostname', DD_DOGSTATSD_HOST)
578
579
  setString(target, 'dogstatsd.port', DD_DOGSTATSD_PORT)
579
580
  setBoolean(target, 'dsmEnabled', DD_DATA_STREAMS_ENABLED)
@@ -648,6 +649,7 @@ class Config {
648
649
  setString(target, 'installSignature.id', DD_INSTRUMENTATION_INSTALL_ID)
649
650
  setString(target, 'installSignature.time', DD_INSTRUMENTATION_INSTALL_TIME)
650
651
  setString(target, 'installSignature.type', DD_INSTRUMENTATION_INSTALL_TYPE)
652
+ // TODO: Why is DD_INJECTION_ENABLED a comma separated list?
651
653
  setArray(target, 'injectionEnabled', DD_INJECTION_ENABLED)
652
654
  if (DD_INJECTION_ENABLED !== undefined) {
653
655
  setString(target, 'instrumentationSource', DD_INJECTION_ENABLED ? 'ssi' : 'manual')
@@ -707,8 +709,11 @@ class Config {
707
709
  maybeJsonFile(DD_SPAN_SAMPLING_RULES_FILE) ??
708
710
  safeJsonParse(DD_SPAN_SAMPLING_RULES)
709
711
  ))
710
- setUnit(target, 'sampleRate', DD_TRACE_SAMPLE_RATE ||
711
- getFromOtelSamplerMap(OTEL_TRACES_SAMPLER, OTEL_TRACES_SAMPLER_ARG))
712
+ setUnit(
713
+ target,
714
+ 'sampleRate',
715
+ DD_TRACE_SAMPLE_RATE || getFromOtelSamplerMap(OTEL_TRACES_SAMPLER, OTEL_TRACES_SAMPLER_ARG)
716
+ )
712
717
  target['sampler.rateLimit'] = DD_TRACE_RATE_LIMIT
713
718
  setSamplingRule(target, 'sampler.rules', safeJsonParse(DD_TRACE_SAMPLING_RULES))
714
719
  unprocessedTarget['sampler.rules'] = DD_TRACE_SAMPLING_RULES
@@ -749,7 +754,7 @@ class Config {
749
754
  setBoolean(target, 'telemetry.debug', DD_TELEMETRY_DEBUG)
750
755
  setBoolean(target, 'telemetry.dependencyCollection', DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED)
751
756
  target['telemetry.heartbeatInterval'] = maybeInt(Math.floor(DD_TELEMETRY_HEARTBEAT_INTERVAL * 1000))
752
- unprocessedTarget['telemetry.heartbeatInterval'] = DD_TELEMETRY_HEARTBEAT_INTERVAL * 1000
757
+ unprocessedTarget['telemetry.heartbeatInterval'] = DD_TELEMETRY_HEARTBEAT_INTERVAL
753
758
  setBoolean(target, 'telemetry.logCollection', DD_TELEMETRY_LOG_COLLECTION_ENABLED)
754
759
  setBoolean(target, 'telemetry.metrics', DD_TELEMETRY_METRICS_ENABLED)
755
760
  setBoolean(target, 'traceId128BitGenerationEnabled', DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
@@ -892,7 +897,7 @@ class Config {
892
897
  opts['cloudPayloadTagging.maxDepth'] = maybeInt(options.cloudPayloadTagging?.maxDepth)
893
898
  opts.baggageMaxBytes = options.baggageMaxBytes
894
899
  opts.baggageMaxItems = options.baggageMaxItems
895
- opts.baggageTagKeys = options.baggageTagKeys
900
+ setArray(opts, 'baggageTagKeys', options.baggageTagKeys)
896
901
  setBoolean(opts, 'codeOriginForSpans.enabled', options.codeOriginForSpans?.enabled)
897
902
  setBoolean(
898
903
  opts,
@@ -900,6 +905,7 @@ class Config {
900
905
  options.codeOriginForSpans?.experimental?.exit_spans?.enabled
901
906
  )
902
907
  setString(opts, 'dbmPropagationMode', options.dbmPropagationMode)
908
+ setBoolean(opts, 'dbm.injectSqlBaseHash', options.dbm?.injectSqlBaseHash)
903
909
  if (options.dogstatsd) {
904
910
  setString(opts, 'dogstatsd.hostname', options.dogstatsd.hostname)
905
911
  setString(opts, 'dogstatsd.port', options.dogstatsd.port)
@@ -1097,6 +1103,21 @@ class Config {
1097
1103
  ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
1098
1104
  : getAgentUrl(this.#getTraceAgentUrl(), this.#optionsArg)
1099
1105
 
1106
+ // Experimental agentless APM span intake
1107
+ // When enabled, sends spans directly to Datadog intake without an agent
1108
+ const agentlessEnabled = isTrue(getEnv('_DD_APM_TRACING_AGENTLESS_ENABLED'))
1109
+ if (agentlessEnabled) {
1110
+ setString(calc, 'experimental.exporter', 'agentless')
1111
+ // Disable rate limiting - server-side sampling will be used
1112
+ calc['sampler.rateLimit'] = -1
1113
+ // Disable client-side stats computation
1114
+ setBoolean(calc, 'stats.enabled', false)
1115
+ // Enable hostname reporting
1116
+ setBoolean(calc, 'reportHostname', true)
1117
+ // Clear sampling rules - server-side sampling handles this
1118
+ calc['sampler.rules'] = []
1119
+ }
1120
+
1100
1121
  if (this.#isCiVisibility()) {
1101
1122
  setBoolean(calc, 'isEarlyFlakeDetectionEnabled',
1102
1123
  getEnv('DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED') ?? true)
@@ -1129,6 +1150,7 @@ class Config {
1129
1150
  calc.otelLogsUrl = `http://${agentHostname}:${DEFAULT_OTLP_PORT}`
1130
1151
  calc.otelMetricsUrl = `http://${agentHostname}:${DEFAULT_OTLP_PORT}/v1/metrics`
1131
1152
  calc.otelUrl = `http://${agentHostname}:${DEFAULT_OTLP_PORT}`
1153
+ calc['telemetry.heartbeatInterval'] = maybeInt(Math.floor(this.#defaults['telemetry.heartbeatInterval'] * 1000))
1132
1154
 
1133
1155
  setBoolean(calc, 'isGitUploadEnabled',
1134
1156
  calc.isIntelligentTestRunnerEnabled && !isFalse(getEnv('DD_CIVISIBILITY_GIT_UPLOAD_ENABLED')))
@@ -1156,7 +1178,7 @@ class Config {
1156
1178
  /**
1157
1179
  * Applies remote configuration options from APM_TRACING configs.
1158
1180
  *
1159
- * @param {import('./config/remote_config').RemoteConfigOptions} options - Configurations received via Remote Config
1181
+ * @param {import('./remote_config').RemoteConfigOptions} options - Configurations received via Remote Config
1160
1182
  */
1161
1183
  #applyRemoteConfig (options) {
1162
1184
  const opts = this.#remote