dd-trace 5.107.0 → 5.108.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/package.json +5 -5
- package/packages/dd-trace/src/appsec/downstream_requests.js +3 -2
- package/packages/dd-trace/src/appsec/iast/index.js +3 -2
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +2 -1
- package/packages/dd-trace/src/appsec/reporter.js +1 -1
- package/packages/dd-trace/src/config/generated-config-types.d.ts +1 -0
- package/packages/dd-trace/src/config/supported-configurations.json +7 -0
- package/packages/dd-trace/src/profiling/config.js +2 -0
- package/packages/dd-trace/src/profiling/profilers/events.js +26 -4
- package/packages/dd-trace/src/profiling/profilers/space.js +3 -1
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.108.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
"@datadog/native-iast-taint-tracking": "4.2.0",
|
|
170
170
|
"@datadog/native-metrics": "3.1.2",
|
|
171
171
|
"@datadog/openfeature-node-server": "2.0.0",
|
|
172
|
-
"@datadog/pprof": "5.
|
|
172
|
+
"@datadog/pprof": "5.15.0",
|
|
173
173
|
"@datadog/wasm-js-rewriter": "5.0.1",
|
|
174
174
|
"@opentelemetry/api": ">=1.0.0 <1.10.0",
|
|
175
175
|
"@opentelemetry/api-logs": "<1.0.0",
|
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
"@types/mocha": "^10.0.10",
|
|
189
189
|
"@types/node": "^18.19.106",
|
|
190
190
|
"@types/sinon": "^21.0.1",
|
|
191
|
-
"axios": "^1.
|
|
191
|
+
"axios": "^1.17.0",
|
|
192
192
|
"benchmark": "^2.1.4",
|
|
193
193
|
"body-parser": "^2.2.2",
|
|
194
194
|
"bun": "1.3.14",
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
"eslint": "^9.39.2",
|
|
197
197
|
"eslint-plugin-cypress": "^6.4.1",
|
|
198
198
|
"eslint-plugin-import": "^2.32.0",
|
|
199
|
-
"eslint-plugin-jsdoc": "^63.0.
|
|
199
|
+
"eslint-plugin-jsdoc": "^63.0.1",
|
|
200
200
|
"eslint-plugin-mocha": "^11.3.0",
|
|
201
201
|
"eslint-plugin-n": "^18.0.1",
|
|
202
202
|
"eslint-plugin-promise": "^7.3.0",
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
"proxyquire": "^2.1.3",
|
|
223
223
|
"retry": "^0.13.1",
|
|
224
224
|
"semifies": "^1.0.0",
|
|
225
|
-
"semver": "^7.8.
|
|
225
|
+
"semver": "^7.8.2",
|
|
226
226
|
"sinon": "^22.0.0",
|
|
227
227
|
"tiktoken": "^1.0.21",
|
|
228
228
|
"typescript": "^6.0.3",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const web = require('../plugins/util/web')
|
|
4
4
|
const log = require('../log')
|
|
5
|
+
const { isEmpty } = require('../util')
|
|
5
6
|
const {
|
|
6
7
|
HTTP_OUTGOING_METHOD,
|
|
7
8
|
HTTP_OUTGOING_HEADERS,
|
|
@@ -137,7 +138,7 @@ function extractRequestData (ctx) {
|
|
|
137
138
|
addresses[HTTP_OUTGOING_METHOD] = getMethod(options.method)
|
|
138
139
|
|
|
139
140
|
const headers = options?.headers
|
|
140
|
-
if (headers &&
|
|
141
|
+
if (headers && !isEmpty(headers)) {
|
|
141
142
|
addresses[HTTP_OUTGOING_HEADERS] = lowercaseHeaderKeys(headers)
|
|
142
143
|
}
|
|
143
144
|
|
|
@@ -177,7 +178,7 @@ function extractResponseData (res, responseBody) {
|
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
const headers = res.headers
|
|
180
|
-
if (headers &&
|
|
181
|
+
if (headers && !isEmpty(headers)) {
|
|
181
182
|
addresses[HTTP_OUTGOING_RESPONSE_HEADERS] = headers
|
|
182
183
|
}
|
|
183
184
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const dc = require('dc-polyfill')
|
|
4
4
|
const web = require('../../plugins/util/web')
|
|
5
5
|
const { storage } = require('../../../../datadog-core')
|
|
6
|
+
const { isEmpty } = require('../../util')
|
|
6
7
|
const { enable: enableFsPlugin, disable: disableFsPlugin, IAST_MODULE } = require('../rasp/fs-plugin')
|
|
7
8
|
const { incomingHttpRequestStart, incomingHttpRequestEnd, responseWriteHead } = require('../channels')
|
|
8
9
|
const vulnerabilityReporter = require('./vulnerability-reporter')
|
|
@@ -96,7 +97,7 @@ function onIncomingHttpRequestEnd (data) {
|
|
|
96
97
|
|
|
97
98
|
iastResponseEnd.publish({ ...data, storedHeaders })
|
|
98
99
|
|
|
99
|
-
if (
|
|
100
|
+
if (!isEmpty(storedHeaders)) {
|
|
100
101
|
collectedResponseHeaders.delete(data.res)
|
|
101
102
|
}
|
|
102
103
|
|
|
@@ -118,7 +119,7 @@ function onIncomingHttpRequestEnd (data) {
|
|
|
118
119
|
function onResponseWriteHeadCollect ({ res, responseHeaders = {} }) {
|
|
119
120
|
if (!res) return
|
|
120
121
|
|
|
121
|
-
if (
|
|
122
|
+
if (!isEmpty(responseHeaders)) {
|
|
122
123
|
collectedResponseHeaders.set(res, responseHeaders)
|
|
123
124
|
}
|
|
124
125
|
}
|
|
@@ -9,6 +9,7 @@ const addresses = require('../addresses')
|
|
|
9
9
|
const web = require('../../plugins/util/web')
|
|
10
10
|
const { getActiveRequest } = require('../store')
|
|
11
11
|
const waf = require('../waf')
|
|
12
|
+
const { isEmpty } = require('../../util')
|
|
12
13
|
const downstream = require('../downstream_requests')
|
|
13
14
|
const { updateRaspRuleMatchMetricTags } = require('../telemetry')
|
|
14
15
|
const { RULE_TYPES, handleResult } = require('./utils')
|
|
@@ -85,7 +86,7 @@ function handleResponseFinish ({ ctx, res, body }) {
|
|
|
85
86
|
function runResponseEvaluation (res, req, responseBody) {
|
|
86
87
|
const responseAddresses = downstream.extractResponseData(res, responseBody)
|
|
87
88
|
|
|
88
|
-
if (
|
|
89
|
+
if (isEmpty(responseAddresses)) return
|
|
89
90
|
|
|
90
91
|
const raspRule = { type: RULE_TYPES.SSRF, variant: 'response' }
|
|
91
92
|
const result = waf.run({ ephemeral: responseAddresses }, req, raspRule)
|
|
@@ -461,7 +461,7 @@ function truncateRequestBody (target, depth = 0) {
|
|
|
461
461
|
}
|
|
462
462
|
|
|
463
463
|
function reportRequestBody (rootSpan, requestBody, comesFromRaspAction = false) {
|
|
464
|
-
if (!requestBody ||
|
|
464
|
+
if (!requestBody || isEmpty(requestBody)) return
|
|
465
465
|
|
|
466
466
|
if (!rootSpan.meta_struct) {
|
|
467
467
|
rootSpan.meta_struct = {}
|
|
@@ -130,6 +130,7 @@ export interface GeneratedConfig {
|
|
|
130
130
|
DD_MINI_AGENT_PATH: string | undefined;
|
|
131
131
|
DD_PIPELINE_EXECUTION_ID: string | undefined;
|
|
132
132
|
DD_PLAYWRIGHT_WORKER: string | undefined;
|
|
133
|
+
DD_PROFILING_ALLOCATION_ENABLED: boolean;
|
|
133
134
|
DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED: boolean;
|
|
134
135
|
DD_PROFILING_CODEHOTSPOTS_ENABLED: boolean;
|
|
135
136
|
DD_PROFILING_CPU_ENABLED: boolean;
|
|
@@ -1308,6 +1308,13 @@
|
|
|
1308
1308
|
"default": null
|
|
1309
1309
|
}
|
|
1310
1310
|
],
|
|
1311
|
+
"DD_PROFILING_ALLOCATION_ENABLED": [
|
|
1312
|
+
{
|
|
1313
|
+
"implementation": "A",
|
|
1314
|
+
"type": "boolean",
|
|
1315
|
+
"default": "false"
|
|
1316
|
+
}
|
|
1317
|
+
],
|
|
1311
1318
|
"DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED": [
|
|
1312
1319
|
{
|
|
1313
1320
|
"implementation": "A",
|
|
@@ -86,6 +86,7 @@ class Config {
|
|
|
86
86
|
|
|
87
87
|
this.timelineEnabled = options.DD_PROFILING_TIMELINE_ENABLED
|
|
88
88
|
this.timelineSamplingEnabled = options.DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED
|
|
89
|
+
this.allocationProfilingEnabled = options.DD_PROFILING_ALLOCATION_ENABLED
|
|
89
90
|
this.codeHotspotsEnabled = options.DD_PROFILING_CODEHOTSPOTS_ENABLED
|
|
90
91
|
this.cpuProfilingEnabled = options.DD_PROFILING_CPU_ENABLED
|
|
91
92
|
this.heapSamplingInterval = options.DD_PROFILING_HEAP_SAMPLING_INTERVAL
|
|
@@ -139,6 +140,7 @@ class Config {
|
|
|
139
140
|
|
|
140
141
|
get systemInfoReport () {
|
|
141
142
|
const report = {
|
|
143
|
+
allocationProfilingEnabled: this.allocationProfilingEnabled,
|
|
142
144
|
asyncContextFrameEnabled: this.asyncContextFrameEnabled,
|
|
143
145
|
codeHotspotsEnabled: this.codeHotspotsEnabled,
|
|
144
146
|
cpuProfilingEnabled: this.cpuProfilingEnabled,
|
|
@@ -66,12 +66,11 @@ class GCDecorator {
|
|
|
66
66
|
constructor (stringTable) {
|
|
67
67
|
this.stringTable = stringTable
|
|
68
68
|
this.reasonLabelKey = stringTable.dedup('gc reason')
|
|
69
|
+
this.kindLabelKey = stringTable.dedup('gc type')
|
|
69
70
|
this.kindLabels = []
|
|
70
71
|
this.reasonLabels = []
|
|
71
72
|
this.flagObj = {}
|
|
72
73
|
|
|
73
|
-
const kindLabelKey = stringTable.dedup('gc type')
|
|
74
|
-
|
|
75
74
|
// Create labels for all GC performance flags and kinds of GC
|
|
76
75
|
for (const [key, value] of Object.entries(constants)) {
|
|
77
76
|
if (key.startsWith('NODE_PERFORMANCE_GC_FLAGS_')) {
|
|
@@ -79,20 +78,43 @@ class GCDecorator {
|
|
|
79
78
|
} else if (key.startsWith('NODE_PERFORMANCE_GC_')) {
|
|
80
79
|
// It's a constant for a kind of GC
|
|
81
80
|
const kind = key.slice(20).toLowerCase()
|
|
82
|
-
this.kindLabels[value] = labelFromStr(stringTable, kindLabelKey, kind)
|
|
81
|
+
this.kindLabels[value] = labelFromStr(stringTable, this.kindLabelKey, kind)
|
|
83
82
|
}
|
|
84
83
|
}
|
|
84
|
+
|
|
85
|
+
// V8's young-generation collector emits GC events with kind 2, but Node.js
|
|
86
|
+
// doesn't expose a matching NODE_PERFORMANCE_GC_* constant for it, so we map it
|
|
87
|
+
// explicitly. The collector was renamed from Minor Mark-Compact to Minor
|
|
88
|
+
// Mark-Sweep in the V8 version that shipped with Node 22. See equivalent
|
|
89
|
+
// mapping in runtime_metrics.js.
|
|
90
|
+
const minorMarkGCKind = 2
|
|
91
|
+
if (this.kindLabels[minorMarkGCKind] === undefined) {
|
|
92
|
+
const { NODE_MAJOR } = require('../../../../../version')
|
|
93
|
+
const minorGCLabel = NODE_MAJOR >= 22 ? 'minor_mark_sweep' : 'minor_mark_compact'
|
|
94
|
+
this.kindLabels[minorMarkGCKind] = labelFromStr(stringTable, this.kindLabelKey, minorGCLabel)
|
|
95
|
+
}
|
|
85
96
|
}
|
|
86
97
|
|
|
87
98
|
decorateSample (sampleInput, item) {
|
|
88
99
|
const { kind, flags } = item.detail
|
|
89
|
-
sampleInput.label.push(this.
|
|
100
|
+
sampleInput.label.push(this.getKindLabel(kind))
|
|
90
101
|
const reasonLabel = this.getReasonLabel(flags)
|
|
91
102
|
if (reasonLabel) {
|
|
92
103
|
sampleInput.label.push(reasonLabel)
|
|
93
104
|
}
|
|
94
105
|
}
|
|
95
106
|
|
|
107
|
+
getKindLabel (kind) {
|
|
108
|
+
let kindLabel = this.kindLabels[kind]
|
|
109
|
+
if (kindLabel === undefined) {
|
|
110
|
+
// Gracefully handle GC kinds we don't have a label for (e.g. a value
|
|
111
|
+
// introduced by a future Node.js/V8 version).
|
|
112
|
+
kindLabel = labelFromStr(this.stringTable, this.kindLabelKey, `unknown_${kind}`)
|
|
113
|
+
this.kindLabels[kind] = kindLabel
|
|
114
|
+
}
|
|
115
|
+
return kindLabel
|
|
116
|
+
}
|
|
117
|
+
|
|
96
118
|
getReasonLabel (flags) {
|
|
97
119
|
if (flags === 0) {
|
|
98
120
|
return null
|
|
@@ -13,12 +13,14 @@ class NativeSpaceProfiler {
|
|
|
13
13
|
#mapper
|
|
14
14
|
#oomMonitoring
|
|
15
15
|
#pprof
|
|
16
|
+
#allocationProfilingEnabled = false
|
|
16
17
|
#samplingInterval = 512 * 1024
|
|
17
18
|
#started = false
|
|
18
19
|
|
|
19
20
|
constructor (options = {}) {
|
|
20
21
|
// TODO: Remove default value. It is only used in testing.
|
|
21
22
|
this.#samplingInterval = options.heapSamplingInterval || 512 * 1024
|
|
23
|
+
this.#allocationProfilingEnabled = options.allocationProfilingEnabled
|
|
22
24
|
this.#oomMonitoring = options.oomMonitoring || {}
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -31,7 +33,7 @@ class NativeSpaceProfiler {
|
|
|
31
33
|
|
|
32
34
|
this.#mapper = mapper
|
|
33
35
|
this.#pprof = require('@datadog/pprof')
|
|
34
|
-
this.#pprof.heap.start(this.#samplingInterval, STACK_DEPTH)
|
|
36
|
+
this.#pprof.heap.start(this.#samplingInterval, STACK_DEPTH, this.#allocationProfilingEnabled)
|
|
35
37
|
if (this.#oomMonitoring.enabled) {
|
|
36
38
|
const strategies = this.#oomMonitoring.exportStrategies
|
|
37
39
|
this.#pprof.heap.monitorOutOfMemory(
|