dd-trace 5.96.0 → 5.97.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +34 -0
- package/package.json +9 -7
- package/packages/datadog-esbuild/index.js +20 -9
- package/packages/datadog-instrumentations/src/child_process.js +7 -17
- package/packages/datadog-instrumentations/src/crypto.js +1 -2
- package/packages/datadog-instrumentations/src/cucumber.js +4 -1
- package/packages/datadog-instrumentations/src/cypress-config.js +324 -0
- package/packages/datadog-instrumentations/src/cypress.js +86 -4
- package/packages/datadog-instrumentations/src/dns.js +1 -2
- package/packages/datadog-instrumentations/src/express.js +4 -4
- package/packages/datadog-instrumentations/src/fs.js +27 -29
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
- package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
- package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
- package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
- package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
- package/packages/datadog-instrumentations/src/http/client.js +2 -3
- package/packages/datadog-instrumentations/src/http/server.js +2 -5
- package/packages/datadog-instrumentations/src/http2/client.js +1 -3
- package/packages/datadog-instrumentations/src/http2/server.js +1 -3
- package/packages/datadog-instrumentations/src/jest.js +13 -4
- package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +4 -1
- package/packages/datadog-instrumentations/src/net.js +2 -8
- package/packages/datadog-instrumentations/src/pino.js +1 -1
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +1 -2
- package/packages/datadog-instrumentations/src/selenium.js +4 -1
- package/packages/datadog-instrumentations/src/sequelize.js +1 -1
- package/packages/datadog-instrumentations/src/url.js +1 -3
- package/packages/datadog-instrumentations/src/vitest.js +5 -1
- package/packages/datadog-instrumentations/src/vm.js +1 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +4 -3
- package/packages/datadog-plugin-cucumber/src/index.js +7 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +57 -5
- package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +4 -2
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
- package/packages/datadog-plugin-mocha/src/index.js +5 -2
- package/packages/datadog-plugin-next/src/index.js +2 -14
- package/packages/datadog-plugin-openai/src/services.js +1 -0
- package/packages/datadog-webpack/index.js +3 -3
- package/packages/dd-trace/index.js +12 -10
- package/packages/dd-trace/src/agent/url.js +2 -2
- package/packages/dd-trace/src/aiguard/sdk.js +4 -0
- package/packages/dd-trace/src/appsec/blocking.js +3 -0
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config.js +1 -0
- package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/config/defaults.js +316 -146
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
- package/packages/dd-trace/src/config/helper.js +59 -10
- package/packages/dd-trace/src/config/index.js +569 -1505
- package/packages/dd-trace/src/config/parsers.js +256 -0
- package/packages/dd-trace/src/config/remote_config.js +59 -2
- package/packages/dd-trace/src/config/supported-configurations.json +350 -433
- package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
- package/packages/dd-trace/src/crashtracking/index.js +1 -7
- package/packages/dd-trace/src/debugger/index.js +1 -1
- package/packages/dd-trace/src/dogstatsd.js +12 -9
- package/packages/dd-trace/src/encode/0.4.js +1 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
- package/packages/dd-trace/src/exporters/common/request.js +9 -0
- package/packages/dd-trace/src/exporters/common/writer.js +12 -2
- package/packages/dd-trace/src/heap_snapshots.js +3 -0
- package/packages/dd-trace/src/index.js +5 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
- package/packages/dd-trace/src/llmobs/index.js +4 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
- package/packages/dd-trace/src/llmobs/sdk.js +12 -8
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +9 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
- package/packages/dd-trace/src/log/index.js +26 -55
- package/packages/dd-trace/src/log/writer.js +7 -19
- package/packages/dd-trace/src/noop/proxy.js +8 -0
- package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
- package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
- package/packages/dd-trace/src/plugin_manager.js +8 -6
- package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
- package/packages/dd-trace/src/plugins/plugin.js +7 -4
- package/packages/dd-trace/src/process-tags/index.js +3 -0
- package/packages/dd-trace/src/profiler.js +27 -2
- package/packages/dd-trace/src/profiling/config.js +73 -241
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
- package/packages/dd-trace/src/profiling/profiler.js +56 -44
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
- package/packages/dd-trace/src/propagation-hash/index.js +2 -1
- package/packages/dd-trace/src/proxy.js +32 -3
- package/packages/dd-trace/src/remote_config/index.js +3 -0
- package/packages/dd-trace/src/require-package-json.js +8 -4
- package/packages/dd-trace/src/ritm.js +58 -26
- package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -0
- package/packages/dd-trace/src/sampler.js +1 -1
- package/packages/dd-trace/src/standalone/index.js +3 -0
- package/packages/dd-trace/src/telemetry/index.js +2 -3
- package/packages/dd-trace/src/telemetry/send-data.js +5 -19
- package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
- package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
- package/packages/dd-trace/src/util.js +0 -9
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
|
|
5
|
+
const tagger = require('../tagger')
|
|
6
|
+
|
|
7
|
+
let warnInvalidValue
|
|
8
|
+
function setWarnInvalidValue (fn) {
|
|
9
|
+
warnInvalidValue = fn
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const VALID_PROPAGATION_STYLES = new Set([
|
|
13
|
+
'datadog', 'tracecontext', 'b3', 'b3 single header', 'b3multi', 'baggage', 'none',
|
|
14
|
+
])
|
|
15
|
+
|
|
16
|
+
function toCase (value, methodName) {
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
return value.map(item => {
|
|
19
|
+
return transformers[methodName](item)
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
return value[methodName]()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const transformers = {
|
|
26
|
+
setGRPCRange (value) {
|
|
27
|
+
if (value == null) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
value = value.split(',')
|
|
31
|
+
const result = []
|
|
32
|
+
|
|
33
|
+
for (const val of value) {
|
|
34
|
+
const dashIndex = val.indexOf('-')
|
|
35
|
+
if (dashIndex === -1) {
|
|
36
|
+
result.push(Number(val))
|
|
37
|
+
} else {
|
|
38
|
+
const start = Number(val.slice(0, dashIndex))
|
|
39
|
+
const end = Number(val.slice(dashIndex + 1))
|
|
40
|
+
for (let i = start; i <= end; i++) {
|
|
41
|
+
result.push(i)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return result
|
|
46
|
+
},
|
|
47
|
+
toLowerCase (value) {
|
|
48
|
+
return toCase(value, 'toLowerCase')
|
|
49
|
+
},
|
|
50
|
+
toUpperCase (value) {
|
|
51
|
+
return toCase(value, 'toUpperCase')
|
|
52
|
+
},
|
|
53
|
+
toCamelCase (value) {
|
|
54
|
+
if (Array.isArray(value)) {
|
|
55
|
+
return value.map(item => {
|
|
56
|
+
return transformers.toCamelCase(item)
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
if (typeof value === 'object' && value !== null) {
|
|
60
|
+
const result = {}
|
|
61
|
+
for (const [key, innerValue] of Object.entries(value)) {
|
|
62
|
+
const camelCaseKey = key.replaceAll(/_(\w)/g, (_, letter) => letter.toUpperCase())
|
|
63
|
+
result[camelCaseKey] = transformers.toCamelCase(innerValue)
|
|
64
|
+
}
|
|
65
|
+
return result
|
|
66
|
+
}
|
|
67
|
+
return value
|
|
68
|
+
},
|
|
69
|
+
parseOtelTags (value, optionName) {
|
|
70
|
+
return parsers.MAP(value
|
|
71
|
+
?.replace(/(^|,)deployment\.environment=/, '$1env:')
|
|
72
|
+
.replace(/(^|,)service\.name=/, '$1service:')
|
|
73
|
+
.replace(/(^|,)service\.version=/, '$1version:')
|
|
74
|
+
.replaceAll('=', ':'), optionName)
|
|
75
|
+
},
|
|
76
|
+
normalizeProfilingEnabled (configValue) {
|
|
77
|
+
if (configValue == null) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
if (configValue === 'true' || configValue === '1') {
|
|
81
|
+
return 'true'
|
|
82
|
+
}
|
|
83
|
+
if (configValue === 'false' || configValue === '0') {
|
|
84
|
+
return 'false'
|
|
85
|
+
}
|
|
86
|
+
const lowercased = String(configValue).toLowerCase()
|
|
87
|
+
if (lowercased !== configValue) {
|
|
88
|
+
return transformers.normalizeProfilingEnabled(lowercased)
|
|
89
|
+
}
|
|
90
|
+
return configValue
|
|
91
|
+
},
|
|
92
|
+
sampleRate (value, optionName, source) {
|
|
93
|
+
const number = Number(value)
|
|
94
|
+
if (Number.isNaN(number) || value === null) {
|
|
95
|
+
warnInvalidValue(value, optionName, source, 'Sample rate invalid')
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
const clamped = Math.min(Math.max(number, 0), 1)
|
|
99
|
+
if (clamped !== number) {
|
|
100
|
+
warnInvalidValue(value, optionName, source, 'Sample rate out of range between 0 and 1')
|
|
101
|
+
return clamped
|
|
102
|
+
}
|
|
103
|
+
return number
|
|
104
|
+
},
|
|
105
|
+
readFilePath (raw, optionName, source) {
|
|
106
|
+
const { stackTraceLimit } = Error
|
|
107
|
+
Error.stackTraceLimit = 0
|
|
108
|
+
try {
|
|
109
|
+
return fs.readFileSync(raw, 'utf8')
|
|
110
|
+
} catch (error) {
|
|
111
|
+
warnInvalidValue(raw, optionName, source, 'Error reading path', error)
|
|
112
|
+
} finally {
|
|
113
|
+
Error.stackTraceLimit = stackTraceLimit
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
/**
|
|
117
|
+
* Given a string of comma-separated paths, return the array of paths.
|
|
118
|
+
* If a blank path is provided a null is returned to signal that the feature is disabled.
|
|
119
|
+
* An empty array means the feature is enabled but that no rules need to be applied.
|
|
120
|
+
*
|
|
121
|
+
* @param {string | string[]} input
|
|
122
|
+
*/
|
|
123
|
+
splitJSONPathRules (input) {
|
|
124
|
+
if (!input || input === '$') return
|
|
125
|
+
if (Array.isArray(input)) return input
|
|
126
|
+
if (input === 'all') return []
|
|
127
|
+
return input.split(',')
|
|
128
|
+
},
|
|
129
|
+
stripColonWhitespace (value) {
|
|
130
|
+
if (Array.isArray(value)) {
|
|
131
|
+
return value.map(item => {
|
|
132
|
+
return transformers.stripColonWhitespace(item)
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
return value.replaceAll(/\s*:\s*/g, ':')
|
|
136
|
+
},
|
|
137
|
+
validatePropagationStyles (value, optionName) {
|
|
138
|
+
value = transformers.toLowerCase(value)
|
|
139
|
+
for (const propagator of value) {
|
|
140
|
+
if (!VALID_PROPAGATION_STYLES.has(propagator)) {
|
|
141
|
+
warnInvalidValue(propagator, optionName, optionName, 'Invalid propagator')
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return value
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const telemetryTransformers = {
|
|
150
|
+
JSON (object) {
|
|
151
|
+
return (typeof object !== 'object' || object === null) ? object : JSON.stringify(object)
|
|
152
|
+
},
|
|
153
|
+
MAP (object) {
|
|
154
|
+
if (typeof object !== 'object' || object === null) {
|
|
155
|
+
return object
|
|
156
|
+
}
|
|
157
|
+
let result = ''
|
|
158
|
+
for (const [key, value] of Object.entries(object)) {
|
|
159
|
+
result += `${key}:${value},`
|
|
160
|
+
}
|
|
161
|
+
return result.slice(0, -1)
|
|
162
|
+
},
|
|
163
|
+
ARRAY (array) {
|
|
164
|
+
return Array.isArray(array) ? array.join(',') : array
|
|
165
|
+
},
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const parsers = {
|
|
169
|
+
BOOLEAN (raw) {
|
|
170
|
+
if (raw === 'true' || raw === '1') {
|
|
171
|
+
return true
|
|
172
|
+
}
|
|
173
|
+
if (raw === 'false' || raw === '0') {
|
|
174
|
+
return false
|
|
175
|
+
}
|
|
176
|
+
const lowercased = raw.toLowerCase()
|
|
177
|
+
if (lowercased !== raw) {
|
|
178
|
+
return parsers.BOOLEAN(lowercased)
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
INT (raw) {
|
|
182
|
+
const parsed = Math.trunc(raw)
|
|
183
|
+
if (Number.isNaN(parsed)) {
|
|
184
|
+
return
|
|
185
|
+
}
|
|
186
|
+
return parsed
|
|
187
|
+
},
|
|
188
|
+
DECIMAL (raw) {
|
|
189
|
+
const parsed = Number(raw)
|
|
190
|
+
if (Number.isNaN(parsed)) {
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
return parsed
|
|
194
|
+
},
|
|
195
|
+
ARRAY (raw) {
|
|
196
|
+
// TODO: Make the parsing a helper that is reused everywhere.
|
|
197
|
+
const result = []
|
|
198
|
+
if (!raw) {
|
|
199
|
+
return result
|
|
200
|
+
}
|
|
201
|
+
let valueStart = 0
|
|
202
|
+
for (let i = 0; i < raw.length; i++) {
|
|
203
|
+
const char = raw[i]
|
|
204
|
+
if (char === ',') {
|
|
205
|
+
const value = raw.slice(valueStart, i).trim()
|
|
206
|
+
// Auto filter empty entries.
|
|
207
|
+
if (value.length > 0) {
|
|
208
|
+
result.push(value)
|
|
209
|
+
}
|
|
210
|
+
valueStart = i + 1
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (valueStart < raw.length) {
|
|
214
|
+
const value = raw.slice(valueStart).trim()
|
|
215
|
+
// Auto filter empty entries.
|
|
216
|
+
if (value.length > 0) {
|
|
217
|
+
result.push(value)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return result
|
|
221
|
+
},
|
|
222
|
+
MAP (raw, optionName) {
|
|
223
|
+
/** @type {Record<string, string>} */
|
|
224
|
+
const entries = {}
|
|
225
|
+
if (!raw) {
|
|
226
|
+
return entries
|
|
227
|
+
}
|
|
228
|
+
// DD_TAGS is a special case. It may be a map of key-value pairs separated by spaces.
|
|
229
|
+
if (optionName === 'DD_TAGS' && !raw.includes(',')) {
|
|
230
|
+
raw = raw.replaceAll(/\s+/g, ',')
|
|
231
|
+
}
|
|
232
|
+
tagger.add(entries, raw)
|
|
233
|
+
return entries
|
|
234
|
+
},
|
|
235
|
+
JSON (raw) {
|
|
236
|
+
const { stackTraceLimit } = Error
|
|
237
|
+
Error.stackTraceLimit = 0
|
|
238
|
+
try {
|
|
239
|
+
return JSON.parse(raw)
|
|
240
|
+
} catch {
|
|
241
|
+
// ignore
|
|
242
|
+
} finally {
|
|
243
|
+
Error.stackTraceLimit = stackTraceLimit
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
STRING (raw) {
|
|
247
|
+
return raw
|
|
248
|
+
},
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
module.exports = {
|
|
252
|
+
parsers,
|
|
253
|
+
transformers,
|
|
254
|
+
telemetryTransformers,
|
|
255
|
+
setWarnInvalidValue,
|
|
256
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const RemoteConfigCapabilities = require('../remote_config/capabilities')
|
|
4
4
|
const log = require('../log')
|
|
5
|
+
const tagger = require('../tagger')
|
|
5
6
|
|
|
6
7
|
module.exports = {
|
|
7
8
|
enable,
|
|
@@ -194,10 +195,66 @@ function enable (rc, config, onConfigUpdated) {
|
|
|
194
195
|
transaction.ack(item.path)
|
|
195
196
|
}
|
|
196
197
|
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
/** @type {import('../config').TracerOptions|null|RemoteConfigOptions} */
|
|
199
|
+
let mergedLibConfig = rcClientLibConfigManager.getMergedLibConfig()
|
|
200
|
+
|
|
201
|
+
if (mergedLibConfig) {
|
|
202
|
+
mergedLibConfig = transformRemoteConfigToLocalOption(mergedLibConfig)
|
|
203
|
+
}
|
|
204
|
+
|
|
199
205
|
config.setRemoteConfig(mergedLibConfig)
|
|
200
206
|
|
|
201
207
|
onConfigUpdated()
|
|
202
208
|
})
|
|
203
209
|
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @param {RemoteConfigOptions} libConfig
|
|
213
|
+
* @returns {import('../config').TracerOptions}
|
|
214
|
+
*/
|
|
215
|
+
function transformRemoteConfigToLocalOption (libConfig) {
|
|
216
|
+
const normalizedConfig = {}
|
|
217
|
+
for (const [name, value] of Object.entries(libConfig)) {
|
|
218
|
+
if (value !== null) {
|
|
219
|
+
normalizedConfig[optionLookupTable[name] ?? name] = transformers[name]?.(value) ?? value
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return normalizedConfig
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// This is intermediate solution until remote config is reworked to handle all known entries with proper names
|
|
226
|
+
const optionLookupTable = {
|
|
227
|
+
dynamic_instrumentation_enabled: 'dynamicInstrumentation.enabled',
|
|
228
|
+
code_origin_enabled: 'codeOriginForSpans.enabled',
|
|
229
|
+
tracing_sampling_rate: 'sampleRate',
|
|
230
|
+
log_injection_enabled: 'logInjection',
|
|
231
|
+
tracing_enabled: 'tracing',
|
|
232
|
+
tracing_sampling_rules: 'samplingRules',
|
|
233
|
+
tracing_header_tags: 'headerTags',
|
|
234
|
+
tracing_tags: 'tags',
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const transformers = {
|
|
238
|
+
tracing_sampling_rules (samplingRules) {
|
|
239
|
+
for (const rule of (samplingRules || [])) {
|
|
240
|
+
if (rule.tags) {
|
|
241
|
+
const reformattedTags = {}
|
|
242
|
+
for (const tag of rule.tags) {
|
|
243
|
+
reformattedTags[tag.key] = tag.value_glob
|
|
244
|
+
}
|
|
245
|
+
rule.tags = reformattedTags
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return samplingRules
|
|
249
|
+
},
|
|
250
|
+
tracing_header_tags (headerTags) {
|
|
251
|
+
return headerTags?.map(tag => {
|
|
252
|
+
return tag.tag_name ? `${tag.header}:${tag.tag_name}` : tag.header
|
|
253
|
+
})
|
|
254
|
+
},
|
|
255
|
+
tracing_tags (tags) {
|
|
256
|
+
const normalizedTags = {}
|
|
257
|
+
tagger.add(normalizedTags, tags)
|
|
258
|
+
return normalizedTags
|
|
259
|
+
},
|
|
260
|
+
}
|