dd-trace 5.31.0 → 5.33.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/LICENSE-3rdparty.csv +1 -0
- package/README.md +17 -14
- package/index.d.ts +11 -1
- package/package.json +6 -5
- package/packages/datadog-instrumentations/src/aws-sdk.js +4 -1
- package/packages/datadog-instrumentations/src/cucumber.js +31 -14
- package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
- package/packages/datadog-instrumentations/src/jest.js +105 -56
- package/packages/datadog-instrumentations/src/mocha/main.js +9 -4
- package/packages/datadog-instrumentations/src/mocha/utils.js +27 -9
- package/packages/datadog-instrumentations/src/mocha/worker.js +4 -2
- package/packages/datadog-instrumentations/src/node-serialize.js +22 -0
- package/packages/datadog-instrumentations/src/openai.js +2 -0
- package/packages/datadog-instrumentations/src/playwright.js +8 -3
- package/packages/datadog-instrumentations/src/vitest.js +134 -62
- package/packages/datadog-instrumentations/src/vm.js +49 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +16 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +63 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +287 -0
- package/packages/datadog-plugin-aws-sdk/src/services/index.js +1 -0
- package/packages/datadog-plugin-cucumber/src/index.js +31 -31
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +19 -8
- package/packages/datadog-plugin-cypress/src/support.js +6 -2
- package/packages/datadog-plugin-fetch/src/index.js +3 -3
- package/packages/datadog-plugin-http/src/client.js +5 -33
- package/packages/datadog-plugin-jest/src/index.js +37 -37
- package/packages/datadog-plugin-langchain/src/index.js +12 -80
- package/packages/datadog-plugin-langchain/src/tracing.js +89 -0
- package/packages/datadog-plugin-mocha/src/index.js +19 -35
- package/packages/datadog-plugin-playwright/src/index.js +3 -1
- package/packages/datadog-plugin-vitest/src/index.js +33 -35
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +2 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +3 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/untrusted-deserialization-analyzer.js +16 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +41 -24
- package/packages/dd-trace/src/appsec/iast/iast-context.js +12 -0
- package/packages/dd-trace/src/appsec/iast/path-line.js +19 -23
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +9 -8
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +75 -24
- package/packages/dd-trace/src/appsec/rasp/utils.js +10 -5
- package/packages/dd-trace/src/appsec/stack_trace.js +38 -28
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +37 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +65 -28
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +57 -17
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +5 -4
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +18 -3
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +5 -3
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +20 -3
- package/packages/dd-trace/src/config.js +43 -3
- package/packages/dd-trace/src/crashtracking/crashtracker.js +9 -0
- package/packages/dd-trace/src/crashtracking/noop.js +3 -0
- package/packages/dd-trace/src/datastreams/fnv.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/config.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/defaults.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +30 -13
- package/packages/dd-trace/src/debugger/devtools_client/send.js +4 -8
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +35 -1
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +112 -0
- package/packages/dd-trace/src/debugger/devtools_client/status.js +12 -10
- package/packages/dd-trace/src/debugger/index.js +2 -13
- package/packages/dd-trace/src/llmobs/plugins/base.js +40 -11
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +59 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +24 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +111 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +42 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +102 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/llm.js +32 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +131 -0
- package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +11 -3
- package/packages/dd-trace/src/llmobs/util.js +7 -1
- package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +3 -3
- package/packages/dd-trace/src/opentelemetry/context_manager.js +43 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +58 -27
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +0 -2
- package/packages/dd-trace/src/plugins/util/test.js +44 -12
- package/packages/dd-trace/src/priority_sampler.js +4 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +21 -0
- package/packages/dd-trace/src/profiling/profiler.js +11 -8
- package/packages/dd-trace/src/profiling/profilers/events.js +17 -1
- package/packages/dd-trace/src/proxy.js +6 -3
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { join } = require('path')
|
|
4
|
-
const { Worker } = require('worker_threads')
|
|
4
|
+
const { Worker, threadId: parentThreadId } = require('worker_threads')
|
|
5
5
|
const { randomUUID } = require('crypto')
|
|
6
6
|
const log = require('../../log')
|
|
7
7
|
|
|
8
8
|
const probeIdToResolveBreakpointSet = new Map()
|
|
9
|
-
const
|
|
9
|
+
const probeIdToResolveBreakpointRemove = new Map()
|
|
10
10
|
|
|
11
11
|
class TestVisDynamicInstrumentation {
|
|
12
12
|
constructor () {
|
|
@@ -16,28 +16,34 @@ class TestVisDynamicInstrumentation {
|
|
|
16
16
|
})
|
|
17
17
|
this.breakpointSetChannel = new MessageChannel()
|
|
18
18
|
this.breakpointHitChannel = new MessageChannel()
|
|
19
|
+
this.breakpointRemoveChannel = new MessageChannel()
|
|
20
|
+
this.onHitBreakpointByProbeId = new Map()
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
removeProbe (probeId) {
|
|
24
|
+
return new Promise(resolve => {
|
|
25
|
+
this.breakpointRemoveChannel.port2.postMessage(probeId)
|
|
26
|
+
|
|
27
|
+
probeIdToResolveBreakpointRemove.set(probeId, resolve)
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Return 2 elements:
|
|
32
|
+
// 1. Probe ID
|
|
23
33
|
// 2. Promise that's resolved when the breakpoint is set
|
|
24
|
-
|
|
25
|
-
addLineProbe ({ file, line }) {
|
|
26
|
-
const snapshotId = randomUUID()
|
|
34
|
+
addLineProbe ({ file, line }, onHitBreakpoint) {
|
|
27
35
|
const probeId = randomUUID()
|
|
28
36
|
|
|
29
|
-
this.breakpointSetChannel.port2.postMessage(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
this.breakpointSetChannel.port2.postMessage(
|
|
38
|
+
{ id: probeId, file, line }
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
this.onHitBreakpointByProbeId.set(probeId, onHitBreakpoint)
|
|
33
42
|
|
|
34
43
|
return [
|
|
35
|
-
|
|
44
|
+
probeId,
|
|
36
45
|
new Promise(resolve => {
|
|
37
46
|
probeIdToResolveBreakpointSet.set(probeId, resolve)
|
|
38
|
-
}),
|
|
39
|
-
new Promise(resolve => {
|
|
40
|
-
probeIdToResolveBreakpointHit.set(probeId, resolve)
|
|
41
47
|
})
|
|
42
48
|
]
|
|
43
49
|
}
|
|
@@ -46,23 +52,42 @@ class TestVisDynamicInstrumentation {
|
|
|
46
52
|
return this._readyPromise
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
start () {
|
|
55
|
+
start (config) {
|
|
50
56
|
if (this.worker) return
|
|
51
57
|
|
|
52
|
-
const { NODE_OPTIONS, ...envWithoutNodeOptions } = process.env
|
|
53
|
-
|
|
54
58
|
log.debug('Starting Test Visibility - Dynamic Instrumentation client...')
|
|
55
59
|
|
|
60
|
+
const rcChannel = new MessageChannel() // mock channel
|
|
61
|
+
const configChannel = new MessageChannel() // mock channel
|
|
62
|
+
|
|
56
63
|
this.worker = new Worker(
|
|
57
64
|
join(__dirname, 'worker', 'index.js'),
|
|
58
65
|
{
|
|
59
66
|
execArgv: [],
|
|
60
|
-
|
|
67
|
+
// Not passing `NODE_OPTIONS` results in issues with yarn, which relies on NODE_OPTIONS
|
|
68
|
+
// for PnP support, hence why we deviate from the DI pattern here.
|
|
69
|
+
// To avoid infinite initialization loops, we're disabling DI and tracing in the worker.
|
|
70
|
+
env: {
|
|
71
|
+
...process.env,
|
|
72
|
+
DD_TRACE_ENABLED: 0,
|
|
73
|
+
DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED: 0
|
|
74
|
+
},
|
|
61
75
|
workerData: {
|
|
76
|
+
config: config.serialize(),
|
|
77
|
+
parentThreadId,
|
|
78
|
+
rcPort: rcChannel.port1,
|
|
79
|
+
configPort: configChannel.port1,
|
|
62
80
|
breakpointSetChannel: this.breakpointSetChannel.port1,
|
|
63
|
-
breakpointHitChannel: this.breakpointHitChannel.port1
|
|
81
|
+
breakpointHitChannel: this.breakpointHitChannel.port1,
|
|
82
|
+
breakpointRemoveChannel: this.breakpointRemoveChannel.port1
|
|
64
83
|
},
|
|
65
|
-
transferList: [
|
|
84
|
+
transferList: [
|
|
85
|
+
rcChannel.port1,
|
|
86
|
+
configChannel.port1,
|
|
87
|
+
this.breakpointSetChannel.port1,
|
|
88
|
+
this.breakpointHitChannel.port1,
|
|
89
|
+
this.breakpointRemoveChannel.port1
|
|
90
|
+
]
|
|
66
91
|
}
|
|
67
92
|
)
|
|
68
93
|
this.worker.on('online', () => {
|
|
@@ -70,10 +95,18 @@ class TestVisDynamicInstrumentation {
|
|
|
70
95
|
this._onReady()
|
|
71
96
|
})
|
|
72
97
|
|
|
98
|
+
this.worker.on('error', (err) => {
|
|
99
|
+
log.error('Test Visibility - Dynamic Instrumentation worker error', err)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
this.worker.on('messageerror', (err) => {
|
|
103
|
+
log.error('Test Visibility - Dynamic Instrumentation worker messageerror', err)
|
|
104
|
+
})
|
|
105
|
+
|
|
73
106
|
// Allow the parent to exit even if the worker is still running
|
|
74
107
|
this.worker.unref()
|
|
75
108
|
|
|
76
|
-
this.breakpointSetChannel.port2.on('message', (
|
|
109
|
+
this.breakpointSetChannel.port2.on('message', (probeId) => {
|
|
77
110
|
const resolve = probeIdToResolveBreakpointSet.get(probeId)
|
|
78
111
|
if (resolve) {
|
|
79
112
|
resolve()
|
|
@@ -83,15 +116,19 @@ class TestVisDynamicInstrumentation {
|
|
|
83
116
|
|
|
84
117
|
this.breakpointHitChannel.port2.on('message', ({ snapshot }) => {
|
|
85
118
|
const { probe: { id: probeId } } = snapshot
|
|
86
|
-
const
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
probeIdToResolveBreakpointHit.delete(probeId)
|
|
119
|
+
const onHit = this.onHitBreakpointByProbeId.get(probeId)
|
|
120
|
+
if (onHit) {
|
|
121
|
+
onHit({ snapshot })
|
|
90
122
|
}
|
|
91
123
|
}).unref()
|
|
92
124
|
|
|
93
|
-
this.
|
|
94
|
-
|
|
125
|
+
this.breakpointRemoveChannel.port2.on('message', (probeId) => {
|
|
126
|
+
const resolve = probeIdToResolveBreakpointRemove.get(probeId)
|
|
127
|
+
if (resolve) {
|
|
128
|
+
resolve()
|
|
129
|
+
probeIdToResolveBreakpointRemove.delete(probeId)
|
|
130
|
+
}
|
|
131
|
+
}).unref()
|
|
95
132
|
}
|
|
96
133
|
}
|
|
97
134
|
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
const sourceMap = require('source-map')
|
|
3
2
|
const path = require('path')
|
|
4
|
-
const {
|
|
3
|
+
const {
|
|
4
|
+
workerData: {
|
|
5
|
+
breakpointSetChannel,
|
|
6
|
+
breakpointHitChannel,
|
|
7
|
+
breakpointRemoveChannel
|
|
8
|
+
}
|
|
9
|
+
} = require('worker_threads')
|
|
10
|
+
const { randomUUID } = require('crypto')
|
|
11
|
+
const sourceMap = require('source-map')
|
|
5
12
|
|
|
6
13
|
// TODO: move debugger/devtools_client/session to common place
|
|
7
14
|
const session = require('../../../debugger/devtools_client/session')
|
|
@@ -16,8 +23,8 @@ const log = require('../../../log')
|
|
|
16
23
|
|
|
17
24
|
let sessionStarted = false
|
|
18
25
|
|
|
19
|
-
const breakpointIdToSnapshotId = new Map()
|
|
20
26
|
const breakpointIdToProbe = new Map()
|
|
27
|
+
const probeIdToBreakpointId = new Map()
|
|
21
28
|
|
|
22
29
|
session.on('Debugger.paused', async ({ params: { hitBreakpoints: [hitBreakpoint], callFrames } }) => {
|
|
23
30
|
const probe = breakpointIdToProbe.get(hitBreakpoint)
|
|
@@ -32,13 +39,11 @@ session.on('Debugger.paused', async ({ params: { hitBreakpoints: [hitBreakpoint]
|
|
|
32
39
|
|
|
33
40
|
await session.post('Debugger.resume')
|
|
34
41
|
|
|
35
|
-
const snapshotId = breakpointIdToSnapshotId.get(hitBreakpoint)
|
|
36
|
-
|
|
37
42
|
const snapshot = {
|
|
38
|
-
id:
|
|
43
|
+
id: randomUUID(),
|
|
39
44
|
timestamp: Date.now(),
|
|
40
45
|
probe: {
|
|
41
|
-
id: probe.
|
|
46
|
+
id: probe.id,
|
|
42
47
|
version: '0',
|
|
43
48
|
location: probe.location
|
|
44
49
|
},
|
|
@@ -56,13 +61,32 @@ session.on('Debugger.paused', async ({ params: { hitBreakpoints: [hitBreakpoint]
|
|
|
56
61
|
breakpointHitChannel.postMessage({ snapshot })
|
|
57
62
|
})
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
breakpointRemoveChannel.on('message', async (probeId) => {
|
|
65
|
+
await removeBreakpoint(probeId)
|
|
66
|
+
breakpointRemoveChannel.postMessage(probeId)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
breakpointSetChannel.on('message', async (probe) => {
|
|
70
|
+
await addBreakpoint(probe)
|
|
71
|
+
breakpointSetChannel.postMessage(probe.id)
|
|
63
72
|
})
|
|
64
73
|
|
|
65
|
-
async function
|
|
74
|
+
async function removeBreakpoint (probeId) {
|
|
75
|
+
if (!sessionStarted) {
|
|
76
|
+
// We should not get in this state, but abort if we do, so the code doesn't fail unexpected
|
|
77
|
+
throw Error(`Cannot remove probe ${probeId}: Debugger not started`)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const breakpointId = probeIdToBreakpointId.get(probeId)
|
|
81
|
+
if (!breakpointId) {
|
|
82
|
+
throw Error(`Unknown probe id: ${probeId}`)
|
|
83
|
+
}
|
|
84
|
+
await session.post('Debugger.removeBreakpoint', { breakpointId })
|
|
85
|
+
probeIdToBreakpointId.delete(probeId)
|
|
86
|
+
breakpointIdToProbe.delete(breakpointId)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function addBreakpoint (probe) {
|
|
66
90
|
if (!sessionStarted) await start()
|
|
67
91
|
const { file, line } = probe
|
|
68
92
|
|
|
@@ -81,7 +105,7 @@ async function addBreakpoint (snapshotId, probe) {
|
|
|
81
105
|
try {
|
|
82
106
|
lineNumber = await processScriptWithInlineSourceMap({ file, line, sourceMapURL })
|
|
83
107
|
} catch (err) {
|
|
84
|
-
log.error(err)
|
|
108
|
+
log.error('Error processing script with inline source map', err)
|
|
85
109
|
}
|
|
86
110
|
}
|
|
87
111
|
|
|
@@ -93,7 +117,7 @@ async function addBreakpoint (snapshotId, probe) {
|
|
|
93
117
|
})
|
|
94
118
|
|
|
95
119
|
breakpointIdToProbe.set(breakpointId, probe)
|
|
96
|
-
|
|
120
|
+
probeIdToBreakpointId.set(probe.id, breakpointId)
|
|
97
121
|
}
|
|
98
122
|
|
|
99
123
|
function start () {
|
|
@@ -113,14 +137,30 @@ async function processScriptWithInlineSourceMap (params) {
|
|
|
113
137
|
// Parse the source map
|
|
114
138
|
const consumer = await new sourceMap.SourceMapConsumer(decodedSourceMap)
|
|
115
139
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
140
|
+
let generatedPosition
|
|
141
|
+
|
|
142
|
+
// Map to the generated position. We'll attempt with the full file path first, then with the basename.
|
|
143
|
+
// TODO: figure out why sometimes the full path doesn't work
|
|
144
|
+
generatedPosition = consumer.generatedPositionFor({
|
|
145
|
+
source: file,
|
|
119
146
|
line,
|
|
120
147
|
column: 0
|
|
121
148
|
})
|
|
149
|
+
if (generatedPosition.line === null) {
|
|
150
|
+
generatedPosition = consumer.generatedPositionFor({
|
|
151
|
+
source: path.basename(file),
|
|
152
|
+
line,
|
|
153
|
+
column: 0
|
|
154
|
+
})
|
|
155
|
+
}
|
|
122
156
|
|
|
123
157
|
consumer.destroy()
|
|
124
158
|
|
|
159
|
+
// If we can't find the line, just return the original line
|
|
160
|
+
if (generatedPosition.line === null) {
|
|
161
|
+
log.error(`Could not find generated position for ${file}:${line}`)
|
|
162
|
+
return line
|
|
163
|
+
}
|
|
164
|
+
|
|
125
165
|
return generatedPosition.line
|
|
126
166
|
}
|
|
@@ -87,9 +87,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
87
87
|
|
|
88
88
|
shouldRequestKnownTests () {
|
|
89
89
|
return !!(
|
|
90
|
-
this._config.isEarlyFlakeDetectionEnabled &&
|
|
91
90
|
this._canUseCiVisProtocol &&
|
|
92
|
-
this._libraryConfig?.
|
|
91
|
+
this._libraryConfig?.isKnownTestsEnabled
|
|
93
92
|
)
|
|
94
93
|
}
|
|
95
94
|
|
|
@@ -197,7 +196,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
197
196
|
earlyFlakeDetectionNumRetries,
|
|
198
197
|
earlyFlakeDetectionFaultyThreshold,
|
|
199
198
|
isFlakyTestRetriesEnabled,
|
|
200
|
-
isDiEnabled
|
|
199
|
+
isDiEnabled,
|
|
200
|
+
isKnownTestsEnabled
|
|
201
201
|
} = remoteConfiguration
|
|
202
202
|
return {
|
|
203
203
|
isCodeCoverageEnabled,
|
|
@@ -209,7 +209,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
209
209
|
earlyFlakeDetectionFaultyThreshold,
|
|
210
210
|
isFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled && this._config.isFlakyTestRetriesEnabled,
|
|
211
211
|
flakyTestRetriesCount: this._config.flakyTestRetriesCount,
|
|
212
|
-
isDiEnabled: isDiEnabled && this._config.isTestDynamicInstrumentationEnabled
|
|
212
|
+
isDiEnabled: isDiEnabled && this._config.isTestDynamicInstrumentationEnabled,
|
|
213
|
+
isKnownTestsEnabled
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
216
|
|
|
@@ -5,7 +5,8 @@ const {
|
|
|
5
5
|
JEST_WORKER_COVERAGE_PAYLOAD_CODE,
|
|
6
6
|
JEST_WORKER_TRACE_PAYLOAD_CODE,
|
|
7
7
|
CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
|
|
8
|
-
MOCHA_WORKER_TRACE_PAYLOAD_CODE
|
|
8
|
+
MOCHA_WORKER_TRACE_PAYLOAD_CODE,
|
|
9
|
+
JEST_WORKER_LOGS_PAYLOAD_CODE
|
|
9
10
|
} = require('../../../plugins/util/test')
|
|
10
11
|
|
|
11
12
|
function getInterprocessTraceCode () {
|
|
@@ -29,18 +30,27 @@ function getInterprocessCoverageCode () {
|
|
|
29
30
|
return null
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
function getInterprocessLogsCode () {
|
|
34
|
+
if (process.env.JEST_WORKER_ID) {
|
|
35
|
+
return JEST_WORKER_LOGS_PAYLOAD_CODE
|
|
36
|
+
}
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
|
|
32
40
|
/**
|
|
33
41
|
* Lightweight exporter whose writers only do simple JSON serialization
|
|
34
|
-
* of trace and
|
|
35
|
-
* Currently used by Jest and
|
|
42
|
+
* of trace, coverage and logs payloads, which they send to the test framework's main process.
|
|
43
|
+
* Currently used by Jest, Cucumber and Mocha workers.
|
|
36
44
|
*/
|
|
37
45
|
class TestWorkerCiVisibilityExporter {
|
|
38
46
|
constructor () {
|
|
39
47
|
const interprocessTraceCode = getInterprocessTraceCode()
|
|
40
48
|
const interprocessCoverageCode = getInterprocessCoverageCode()
|
|
49
|
+
const interprocessLogsCode = getInterprocessLogsCode()
|
|
41
50
|
|
|
42
51
|
this._writer = new Writer(interprocessTraceCode)
|
|
43
52
|
this._coverageWriter = new Writer(interprocessCoverageCode)
|
|
53
|
+
this._logsWriter = new Writer(interprocessLogsCode)
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
export (payload) {
|
|
@@ -51,9 +61,14 @@ class TestWorkerCiVisibilityExporter {
|
|
|
51
61
|
this._coverageWriter.append(formattedCoverage)
|
|
52
62
|
}
|
|
53
63
|
|
|
64
|
+
exportDiLogs (testConfiguration, logMessage) {
|
|
65
|
+
this._logsWriter.append({ testConfiguration, logMessage })
|
|
66
|
+
}
|
|
67
|
+
|
|
54
68
|
flush () {
|
|
55
69
|
this._writer.flush()
|
|
56
70
|
this._coverageWriter.flush()
|
|
71
|
+
this._logsWriter.flush()
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
|
|
@@ -93,7 +93,8 @@ function getLibraryConfiguration ({
|
|
|
93
93
|
require_git: requireGit,
|
|
94
94
|
early_flake_detection: earlyFlakeDetectionConfig,
|
|
95
95
|
flaky_test_retries_enabled: isFlakyTestRetriesEnabled,
|
|
96
|
-
di_enabled: isDiEnabled
|
|
96
|
+
di_enabled: isDiEnabled,
|
|
97
|
+
known_tests_enabled: isKnownTestsEnabled
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
} = JSON.parse(res)
|
|
@@ -103,13 +104,14 @@ function getLibraryConfiguration ({
|
|
|
103
104
|
isSuitesSkippingEnabled,
|
|
104
105
|
isItrEnabled,
|
|
105
106
|
requireGit,
|
|
106
|
-
isEarlyFlakeDetectionEnabled: earlyFlakeDetectionConfig?.enabled ?? false,
|
|
107
|
+
isEarlyFlakeDetectionEnabled: isKnownTestsEnabled && (earlyFlakeDetectionConfig?.enabled ?? false),
|
|
107
108
|
earlyFlakeDetectionNumRetries:
|
|
108
109
|
earlyFlakeDetectionConfig?.slow_test_retries?.['5s'] || DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES,
|
|
109
110
|
earlyFlakeDetectionFaultyThreshold:
|
|
110
111
|
earlyFlakeDetectionConfig?.faulty_session_threshold ?? DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD,
|
|
111
112
|
isFlakyTestRetriesEnabled,
|
|
112
|
-
isDiEnabled: isDiEnabled && isFlakyTestRetriesEnabled
|
|
113
|
+
isDiEnabled: isDiEnabled && isFlakyTestRetriesEnabled,
|
|
114
|
+
isKnownTestsEnabled
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
log.debug(() => `Remote settings: ${JSON.stringify(settings)}`)
|
|
@@ -13,15 +13,16 @@ class TestApiManualPlugin extends CiPlugin {
|
|
|
13
13
|
|
|
14
14
|
constructor (...args) {
|
|
15
15
|
super(...args)
|
|
16
|
+
this._isEnvDataCalcualted = false
|
|
16
17
|
this.sourceRoot = process.cwd()
|
|
17
18
|
|
|
18
|
-
this.
|
|
19
|
+
this.unconfiguredAddSub('dd-trace:ci:manual:test:start', ({ testName, testSuite }) => {
|
|
19
20
|
const store = storage.getStore()
|
|
20
21
|
const testSuiteRelative = getTestSuitePath(testSuite, this.sourceRoot)
|
|
21
22
|
const testSpan = this.startTestSpan(testName, testSuiteRelative)
|
|
22
23
|
this.enter(testSpan, store)
|
|
23
24
|
})
|
|
24
|
-
this.
|
|
25
|
+
this.unconfiguredAddSub('dd-trace:ci:manual:test:finish', ({ status, error }) => {
|
|
25
26
|
const store = storage.getStore()
|
|
26
27
|
const testSpan = store && store.span
|
|
27
28
|
if (testSpan) {
|
|
@@ -33,7 +34,7 @@ class TestApiManualPlugin extends CiPlugin {
|
|
|
33
34
|
finishAllTraceSpans(testSpan)
|
|
34
35
|
}
|
|
35
36
|
})
|
|
36
|
-
this.
|
|
37
|
+
this.unconfiguredAddSub('dd-trace:ci:manual:test:addTags', (tags) => {
|
|
37
38
|
const store = storage.getStore()
|
|
38
39
|
const testSpan = store && store.span
|
|
39
40
|
if (testSpan) {
|
|
@@ -41,6 +42,22 @@ class TestApiManualPlugin extends CiPlugin {
|
|
|
41
42
|
}
|
|
42
43
|
})
|
|
43
44
|
}
|
|
45
|
+
|
|
46
|
+
// To lazily calculate env data.
|
|
47
|
+
unconfiguredAddSub (channelName, handler) {
|
|
48
|
+
this.addSub(channelName, (...args) => {
|
|
49
|
+
if (!this._isEnvDataCalcualted) {
|
|
50
|
+
this._isEnvDataCalcualted = true
|
|
51
|
+
this.configure(this._config, true)
|
|
52
|
+
}
|
|
53
|
+
return handler(...args)
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
configure (config, shouldGetEnvironmentData) {
|
|
58
|
+
this._config = config
|
|
59
|
+
super.configure(config, shouldGetEnvironmentData)
|
|
60
|
+
}
|
|
44
61
|
}
|
|
45
62
|
|
|
46
63
|
module.exports = TestApiManualPlugin
|
|
@@ -472,7 +472,9 @@ class Config {
|
|
|
472
472
|
this._setValue(defaults, 'dogstatsd.hostname', '127.0.0.1')
|
|
473
473
|
this._setValue(defaults, 'dogstatsd.port', '8125')
|
|
474
474
|
this._setValue(defaults, 'dsmEnabled', false)
|
|
475
|
-
this._setValue(defaults, '
|
|
475
|
+
this._setValue(defaults, 'dynamicInstrumentation.enabled', false)
|
|
476
|
+
this._setValue(defaults, 'dynamicInstrumentation.redactedIdentifiers', [])
|
|
477
|
+
this._setValue(defaults, 'dynamicInstrumentation.redactionExcludedIdentifiers', [])
|
|
476
478
|
this._setValue(defaults, 'env', undefined)
|
|
477
479
|
this._setValue(defaults, 'experimental.enableGetRumData', false)
|
|
478
480
|
this._setValue(defaults, 'experimental.exporter', undefined)
|
|
@@ -495,6 +497,7 @@ class Config {
|
|
|
495
497
|
this._setValue(defaults, 'iast.redactionValuePattern', null)
|
|
496
498
|
this._setValue(defaults, 'iast.requestSampling', 30)
|
|
497
499
|
this._setValue(defaults, 'iast.telemetryVerbosity', 'INFORMATION')
|
|
500
|
+
this._setValue(defaults, 'iast.stackTrace.enabled', true)
|
|
498
501
|
this._setValue(defaults, 'injectionEnabled', [])
|
|
499
502
|
this._setValue(defaults, 'isAzureFunction', false)
|
|
500
503
|
this._setValue(defaults, 'isCiVisibility', false)
|
|
@@ -600,6 +603,8 @@ class Config {
|
|
|
600
603
|
DD_DOGSTATSD_HOST,
|
|
601
604
|
DD_DOGSTATSD_PORT,
|
|
602
605
|
DD_DYNAMIC_INSTRUMENTATION_ENABLED,
|
|
606
|
+
DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS,
|
|
607
|
+
DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS,
|
|
603
608
|
DD_ENV,
|
|
604
609
|
DD_EXPERIMENTAL_API_SECURITY_ENABLED,
|
|
605
610
|
DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED,
|
|
@@ -618,6 +623,7 @@ class Config {
|
|
|
618
623
|
DD_IAST_REDACTION_VALUE_PATTERN,
|
|
619
624
|
DD_IAST_REQUEST_SAMPLING,
|
|
620
625
|
DD_IAST_TELEMETRY_VERBOSITY,
|
|
626
|
+
DD_IAST_STACK_TRACE_ENABLED,
|
|
621
627
|
DD_INJECTION_ENABLED,
|
|
622
628
|
DD_INSTRUMENTATION_TELEMETRY_ENABLED,
|
|
623
629
|
DD_INSTRUMENTATION_CONFIG_ID,
|
|
@@ -746,7 +752,13 @@ class Config {
|
|
|
746
752
|
this._setString(env, 'dogstatsd.hostname', DD_DOGSTATSD_HOST || DD_DOGSTATSD_HOSTNAME)
|
|
747
753
|
this._setString(env, 'dogstatsd.port', DD_DOGSTATSD_PORT)
|
|
748
754
|
this._setBoolean(env, 'dsmEnabled', DD_DATA_STREAMS_ENABLED)
|
|
749
|
-
this._setBoolean(env, '
|
|
755
|
+
this._setBoolean(env, 'dynamicInstrumentation.enabled', DD_DYNAMIC_INSTRUMENTATION_ENABLED)
|
|
756
|
+
this._setArray(env, 'dynamicInstrumentation.redactedIdentifiers', DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS)
|
|
757
|
+
this._setArray(
|
|
758
|
+
env,
|
|
759
|
+
'dynamicInstrumentation.redactionExcludedIdentifiers',
|
|
760
|
+
DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS
|
|
761
|
+
)
|
|
750
762
|
this._setString(env, 'env', DD_ENV || tags.env)
|
|
751
763
|
this._setBoolean(env, 'traceEnabled', DD_TRACE_ENABLED)
|
|
752
764
|
this._setBoolean(env, 'experimental.enableGetRumData', DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED)
|
|
@@ -777,6 +789,7 @@ class Config {
|
|
|
777
789
|
}
|
|
778
790
|
this._envUnprocessed['iast.requestSampling'] = DD_IAST_REQUEST_SAMPLING
|
|
779
791
|
this._setString(env, 'iast.telemetryVerbosity', DD_IAST_TELEMETRY_VERBOSITY)
|
|
792
|
+
this._setBoolean(env, 'iast.stackTrace.enabled', DD_IAST_STACK_TRACE_ENABLED)
|
|
780
793
|
this._setArray(env, 'injectionEnabled', DD_INJECTION_ENABLED)
|
|
781
794
|
this._setBoolean(env, 'isAzureFunction', getIsAzureFunction())
|
|
782
795
|
this._setBoolean(env, 'isGCPFunction', getIsGCPFunction())
|
|
@@ -926,7 +939,17 @@ class Config {
|
|
|
926
939
|
this._setString(opts, 'dogstatsd.port', options.dogstatsd.port)
|
|
927
940
|
}
|
|
928
941
|
this._setBoolean(opts, 'dsmEnabled', options.dsmEnabled)
|
|
929
|
-
this._setBoolean(opts, '
|
|
942
|
+
this._setBoolean(opts, 'dynamicInstrumentation.enabled', options.dynamicInstrumentation?.enabled)
|
|
943
|
+
this._setArray(
|
|
944
|
+
opts,
|
|
945
|
+
'dynamicInstrumentation.redactedIdentifiers',
|
|
946
|
+
options.dynamicInstrumentation?.redactedIdentifiers
|
|
947
|
+
)
|
|
948
|
+
this._setArray(
|
|
949
|
+
opts,
|
|
950
|
+
'dynamicInstrumentation.redactionExcludedIdentifiers',
|
|
951
|
+
options.dynamicInstrumentation?.redactionExcludedIdentifiers
|
|
952
|
+
)
|
|
930
953
|
this._setString(opts, 'env', options.env || tags.env)
|
|
931
954
|
this._setBoolean(opts, 'experimental.enableGetRumData', options.experimental?.enableGetRumData)
|
|
932
955
|
this._setString(opts, 'experimental.exporter', options.experimental?.exporter)
|
|
@@ -956,6 +979,7 @@ class Config {
|
|
|
956
979
|
this._optsUnprocessed['iast.requestSampling'] = options.iast?.requestSampling
|
|
957
980
|
}
|
|
958
981
|
this._setString(opts, 'iast.telemetryVerbosity', options.iast && options.iast.telemetryVerbosity)
|
|
982
|
+
this._setBoolean(opts, 'iast.stackTrace.enabled', options.iast?.stackTrace?.enabled)
|
|
959
983
|
this._setBoolean(opts, 'isCiVisibility', options.isCiVisibility)
|
|
960
984
|
this._setBoolean(opts, 'legacyBaggageEnabled', options.legacyBaggageEnabled)
|
|
961
985
|
this._setBoolean(opts, 'llmobs.agentlessEnabled', options.llmobs?.agentlessEnabled)
|
|
@@ -1312,6 +1336,22 @@ class Config {
|
|
|
1312
1336
|
this.sampler.sampleRate = this.sampleRate
|
|
1313
1337
|
updateConfig(changes, this)
|
|
1314
1338
|
}
|
|
1339
|
+
|
|
1340
|
+
// TODO: Refactor the Config class so it never produces any config objects that are incompatible with MessageChannel
|
|
1341
|
+
/**
|
|
1342
|
+
* Serializes the config object so it can be passed over a Worker Thread MessageChannel.
|
|
1343
|
+
* @returns {Object} The serialized config object.
|
|
1344
|
+
*/
|
|
1345
|
+
serialize () {
|
|
1346
|
+
// URL objects cannot be serialized over the MessageChannel, so we need to convert them to strings first
|
|
1347
|
+
if (this.url instanceof URL) {
|
|
1348
|
+
const config = { ...this }
|
|
1349
|
+
config.url = this.url.toString()
|
|
1350
|
+
return config
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
return this
|
|
1354
|
+
}
|
|
1315
1355
|
}
|
|
1316
1356
|
|
|
1317
1357
|
function maybeInt (number) {
|
|
@@ -40,6 +40,15 @@ class Crashtracker {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
withProfilerSerializing (f) {
|
|
44
|
+
binding.beginProfilerSerializing()
|
|
45
|
+
try {
|
|
46
|
+
return f()
|
|
47
|
+
} finally {
|
|
48
|
+
binding.endProfilerSerializing()
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
// TODO: Send only configured values when defaults are fixed.
|
|
44
53
|
_getConfig (config) {
|
|
45
54
|
const { hostname = '127.0.0.1', port = 8126 } = config
|
|
@@ -15,7 +15,7 @@ function fnv64 (data) {
|
|
|
15
15
|
data = Buffer.from(data, 'utf-8')
|
|
16
16
|
}
|
|
17
17
|
const byteArray = new Uint8Array(data)
|
|
18
|
-
return fnv(byteArray, FNV1_64_INIT, FNV_64_PRIME,
|
|
18
|
+
return fnv(byteArray, FNV1_64_INIT, FNV_64_PRIME, 2n ** 64n)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
module.exports = {
|
|
@@ -23,10 +23,10 @@ async function addBreakpoint (probe) {
|
|
|
23
23
|
delete probe.where
|
|
24
24
|
|
|
25
25
|
// Optimize for fast calculations when probe is hit
|
|
26
|
-
const snapshotsPerSecond = probe.sampling
|
|
26
|
+
const snapshotsPerSecond = probe.sampling?.snapshotsPerSecond ?? (probe.captureSnapshot
|
|
27
27
|
? MAX_SNAPSHOTS_PER_SECOND_PER_PROBE
|
|
28
28
|
: MAX_NON_SNAPSHOTS_PER_SECOND_PER_PROBE)
|
|
29
|
-
probe.
|
|
29
|
+
probe.nsBetweenSampling = BigInt(1 / snapshotsPerSecond * 1e9)
|
|
30
30
|
probe.lastCaptureNs = 0n
|
|
31
31
|
|
|
32
32
|
// TODO: Inbetween `await session.post('Debugger.enable')` and here, the scripts are parsed and cached.
|
|
@@ -5,6 +5,7 @@ const { format } = require('node:url')
|
|
|
5
5
|
const log = require('../../log')
|
|
6
6
|
|
|
7
7
|
const config = module.exports = {
|
|
8
|
+
dynamicInstrumentation: parentConfig.dynamicInstrumentation,
|
|
8
9
|
runtimeId: parentConfig.tags['runtime-id'],
|
|
9
10
|
service: parentConfig.service,
|
|
10
11
|
commitSHA: parentConfig.commitSHA,
|