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
|
@@ -201,6 +201,7 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
|
|
|
201
201
|
if (err) {
|
|
202
202
|
config.knownTests = []
|
|
203
203
|
config.isEarlyFlakeDetectionEnabled = false
|
|
204
|
+
config.isKnownTestsEnabled = false
|
|
204
205
|
} else {
|
|
205
206
|
config.knownTests = knownTests
|
|
206
207
|
}
|
|
@@ -222,12 +223,13 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
|
|
|
222
223
|
config.isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
223
224
|
config.earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
224
225
|
config.earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold
|
|
226
|
+
config.isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
|
|
225
227
|
// ITR and auto test retries are not supported in parallel mode yet
|
|
226
228
|
config.isSuitesSkippingEnabled = !isParallel && libraryConfig.isSuitesSkippingEnabled
|
|
227
229
|
config.isFlakyTestRetriesEnabled = !isParallel && libraryConfig.isFlakyTestRetriesEnabled
|
|
228
230
|
config.flakyTestRetriesCount = !isParallel && libraryConfig.flakyTestRetriesCount
|
|
229
231
|
|
|
230
|
-
if (config.
|
|
232
|
+
if (config.isKnownTestsEnabled) {
|
|
231
233
|
knownTestsCh.publish({
|
|
232
234
|
onDone: mochaRunAsyncResource.bind(onReceivedKnownTests)
|
|
233
235
|
})
|
|
@@ -273,7 +275,7 @@ addHook({
|
|
|
273
275
|
})
|
|
274
276
|
|
|
275
277
|
getExecutionConfiguration(runner, false, () => {
|
|
276
|
-
if (config.
|
|
278
|
+
if (config.isKnownTestsEnabled) {
|
|
277
279
|
const testSuites = this.files.map(file => getTestSuitePath(file, process.cwd()))
|
|
278
280
|
const isFaulty = getIsFaultyEarlyFlakeDetection(
|
|
279
281
|
testSuites,
|
|
@@ -283,6 +285,7 @@ addHook({
|
|
|
283
285
|
if (isFaulty) {
|
|
284
286
|
config.isEarlyFlakeDetectionEnabled = false
|
|
285
287
|
config.isEarlyFlakeDetectionFaulty = true
|
|
288
|
+
config.isKnownTestsEnabled = false
|
|
286
289
|
}
|
|
287
290
|
}
|
|
288
291
|
if (getCodeCoverageCh.hasSubscribers) {
|
|
@@ -537,7 +540,7 @@ addHook({
|
|
|
537
540
|
this.once('end', getOnEndHandler(true))
|
|
538
541
|
|
|
539
542
|
getExecutionConfiguration(this, true, () => {
|
|
540
|
-
if (config.
|
|
543
|
+
if (config.isKnownTestsEnabled) {
|
|
541
544
|
const testSuites = files.map(file => getTestSuitePath(file, process.cwd()))
|
|
542
545
|
const isFaulty = getIsFaultyEarlyFlakeDetection(
|
|
543
546
|
testSuites,
|
|
@@ -545,6 +548,7 @@ addHook({
|
|
|
545
548
|
config.earlyFlakeDetectionFaultyThreshold
|
|
546
549
|
)
|
|
547
550
|
if (isFaulty) {
|
|
551
|
+
config.isKnownTestsEnabled = false
|
|
548
552
|
config.isEarlyFlakeDetectionEnabled = false
|
|
549
553
|
config.isEarlyFlakeDetectionFaulty = true
|
|
550
554
|
}
|
|
@@ -569,7 +573,7 @@ addHook({
|
|
|
569
573
|
const { BufferedWorkerPool } = BufferedWorkerPoolPackage
|
|
570
574
|
|
|
571
575
|
shimmer.wrap(BufferedWorkerPool.prototype, 'run', run => async function (testSuiteAbsolutePath, workerArgs) {
|
|
572
|
-
if (!testStartCh.hasSubscribers || !config.
|
|
576
|
+
if (!testStartCh.hasSubscribers || !config.isKnownTestsEnabled) {
|
|
573
577
|
return run.apply(this, arguments)
|
|
574
578
|
}
|
|
575
579
|
|
|
@@ -584,6 +588,7 @@ addHook({
|
|
|
584
588
|
{
|
|
585
589
|
...workerArgs,
|
|
586
590
|
_ddEfdNumRetries: config.earlyFlakeDetectionNumRetries,
|
|
591
|
+
_ddIsEfdEnabled: config.isEarlyFlakeDetectionEnabled,
|
|
587
592
|
_ddKnownTests: {
|
|
588
593
|
mocha: {
|
|
589
594
|
[testPath]: testSuiteKnownTests
|
|
@@ -19,6 +19,7 @@ const skipCh = channel('ci:mocha:test:skip')
|
|
|
19
19
|
// suite channels
|
|
20
20
|
const testSuiteErrorCh = channel('ci:mocha:test-suite:error')
|
|
21
21
|
|
|
22
|
+
const BREAKPOINT_HIT_GRACE_PERIOD_MS = 200
|
|
22
23
|
const testToAr = new WeakMap()
|
|
23
24
|
const originalFns = new WeakMap()
|
|
24
25
|
const testToStartLine = new WeakMap()
|
|
@@ -73,7 +74,7 @@ function isMochaRetry (test) {
|
|
|
73
74
|
return test._currentRetry !== undefined && test._currentRetry !== 0
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
function
|
|
77
|
+
function getIsLastRetry (test) {
|
|
77
78
|
return test._currentRetry === test._retries
|
|
78
79
|
}
|
|
79
80
|
|
|
@@ -203,14 +204,28 @@ function getOnTestHandler (isMain) {
|
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
function getOnTestEndHandler () {
|
|
206
|
-
return function (test) {
|
|
207
|
+
return async function (test) {
|
|
207
208
|
const asyncResource = getTestAsyncResource(test)
|
|
208
209
|
const status = getTestStatus(test)
|
|
209
210
|
|
|
211
|
+
// After finishing it might take a bit for the snapshot to be handled.
|
|
212
|
+
// This means that tests retried with DI are BREAKPOINT_HIT_GRACE_PERIOD_MS slower at least.
|
|
213
|
+
if (test._ddShouldWaitForHitProbe || test._retriedTest?._ddShouldWaitForHitProbe) {
|
|
214
|
+
await new Promise((resolve) => {
|
|
215
|
+
setTimeout(() => {
|
|
216
|
+
resolve()
|
|
217
|
+
}, BREAKPOINT_HIT_GRACE_PERIOD_MS)
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
|
|
210
221
|
// if there are afterEach to be run, we don't finish the test yet
|
|
211
222
|
if (asyncResource && !test.parent._afterEach.length) {
|
|
212
223
|
asyncResource.runInAsyncScope(() => {
|
|
213
|
-
testFinishCh.publish({
|
|
224
|
+
testFinishCh.publish({
|
|
225
|
+
status,
|
|
226
|
+
hasBeenRetried: isMochaRetry(test),
|
|
227
|
+
isLastRetry: getIsLastRetry(test)
|
|
228
|
+
})
|
|
214
229
|
})
|
|
215
230
|
}
|
|
216
231
|
}
|
|
@@ -220,16 +235,17 @@ function getOnHookEndHandler () {
|
|
|
220
235
|
return function (hook) {
|
|
221
236
|
const test = hook.ctx.currentTest
|
|
222
237
|
if (test && hook.parent._afterEach.includes(hook)) { // only if it's an afterEach
|
|
223
|
-
const
|
|
224
|
-
if (test._retries > 0 && !isLastRetry
|
|
238
|
+
const isLastRetry = getIsLastRetry(test)
|
|
239
|
+
if (test._retries > 0 && !isLastRetry) {
|
|
225
240
|
return
|
|
226
241
|
}
|
|
242
|
+
const isLastAfterEach = hook.parent._afterEach.indexOf(hook) === hook.parent._afterEach.length - 1
|
|
227
243
|
if (isLastAfterEach) {
|
|
228
244
|
const status = getTestStatus(test)
|
|
229
245
|
const asyncResource = getTestAsyncResource(test)
|
|
230
246
|
if (asyncResource) {
|
|
231
247
|
asyncResource.runInAsyncScope(() => {
|
|
232
|
-
testFinishCh.publish({ status, hasBeenRetried: isMochaRetry(test) })
|
|
248
|
+
testFinishCh.publish({ status, hasBeenRetried: isMochaRetry(test), isLastRetry })
|
|
233
249
|
})
|
|
234
250
|
}
|
|
235
251
|
}
|
|
@@ -286,7 +302,7 @@ function getOnTestRetryHandler () {
|
|
|
286
302
|
const isFirstAttempt = test._currentRetry === 0
|
|
287
303
|
const willBeRetried = test._currentRetry < test._retries
|
|
288
304
|
asyncResource.runInAsyncScope(() => {
|
|
289
|
-
testRetryCh.publish({ isFirstAttempt, err, willBeRetried })
|
|
305
|
+
testRetryCh.publish({ isFirstAttempt, err, willBeRetried, test })
|
|
290
306
|
})
|
|
291
307
|
}
|
|
292
308
|
const key = getTestToArKey(test)
|
|
@@ -333,12 +349,14 @@ function getOnPendingHandler () {
|
|
|
333
349
|
// Hook to add retries to tests if EFD is enabled
|
|
334
350
|
function getRunTestsWrapper (runTests, config) {
|
|
335
351
|
return function (suite, fn) {
|
|
336
|
-
if (config.
|
|
352
|
+
if (config.isKnownTestsEnabled) {
|
|
337
353
|
// by the time we reach `this.on('test')`, it is too late. We need to add retries here
|
|
338
354
|
suite.tests.forEach(test => {
|
|
339
355
|
if (!test.isPending() && isNewTest(test, config.knownTests)) {
|
|
340
356
|
test._ddIsNew = true
|
|
341
|
-
|
|
357
|
+
if (config.isEarlyFlakeDetectionEnabled) {
|
|
358
|
+
retryTest(test, config.earlyFlakeDetectionNumRetries)
|
|
359
|
+
}
|
|
342
360
|
}
|
|
343
361
|
})
|
|
344
362
|
}
|
|
@@ -25,10 +25,12 @@ addHook({
|
|
|
25
25
|
}, (Mocha) => {
|
|
26
26
|
shimmer.wrap(Mocha.prototype, 'run', run => function () {
|
|
27
27
|
if (this.options._ddKnownTests) {
|
|
28
|
-
//
|
|
29
|
-
config.
|
|
28
|
+
// If there are known tests, it means isKnownTestsEnabled should be true
|
|
29
|
+
config.isKnownTestsEnabled = true
|
|
30
|
+
config.isEarlyFlakeDetectionEnabled = this.options._ddIsEfdEnabled
|
|
30
31
|
config.knownTests = this.options._ddKnownTests
|
|
31
32
|
config.earlyFlakeDetectionNumRetries = this.options._ddEfdNumRetries
|
|
33
|
+
delete this.options._ddIsEfdEnabled
|
|
32
34
|
delete this.options._ddKnownTests
|
|
33
35
|
delete this.options._ddEfdNumRetries
|
|
34
36
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
5
|
+
|
|
6
|
+
const nodeUnserializeCh = channel('datadog:node-serialize:unserialize:start')
|
|
7
|
+
|
|
8
|
+
function wrapUnserialize (serialize) {
|
|
9
|
+
return function wrappedUnserialize (obj) {
|
|
10
|
+
if (nodeUnserializeCh.hasSubscribers) {
|
|
11
|
+
nodeUnserializeCh.publish({ obj })
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return serialize.apply(this, arguments)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
addHook({ name: 'node-serialize', versions: ['0.0.4'] }, serialize => {
|
|
19
|
+
shimmer.wrap(serialize, 'unserialize', wrapUnserialize)
|
|
20
|
+
|
|
21
|
+
return serialize
|
|
22
|
+
})
|
|
@@ -35,6 +35,7 @@ const STATUS_TO_TEST_STATUS = {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
let remainingTestsByFile = {}
|
|
38
|
+
let isKnownTestsEnabled = false
|
|
38
39
|
let isEarlyFlakeDetectionEnabled = false
|
|
39
40
|
let earlyFlakeDetectionNumRetries = 0
|
|
40
41
|
let isFlakyTestRetriesEnabled = false
|
|
@@ -418,6 +419,7 @@ function runnerHook (runnerExport, playwrightVersion) {
|
|
|
418
419
|
try {
|
|
419
420
|
const { err, libraryConfig } = await getChannelPromise(libraryConfigurationCh)
|
|
420
421
|
if (!err) {
|
|
422
|
+
isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
|
|
421
423
|
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
422
424
|
earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
423
425
|
isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
|
|
@@ -425,19 +427,22 @@ function runnerHook (runnerExport, playwrightVersion) {
|
|
|
425
427
|
}
|
|
426
428
|
} catch (e) {
|
|
427
429
|
isEarlyFlakeDetectionEnabled = false
|
|
430
|
+
isKnownTestsEnabled = false
|
|
428
431
|
log.error('Playwright session start error', e)
|
|
429
432
|
}
|
|
430
433
|
|
|
431
|
-
if (
|
|
434
|
+
if (isKnownTestsEnabled && semver.gte(playwrightVersion, MINIMUM_SUPPORTED_VERSION_EFD)) {
|
|
432
435
|
try {
|
|
433
436
|
const { err, knownTests: receivedKnownTests } = await getChannelPromise(knownTestsCh)
|
|
434
437
|
if (!err) {
|
|
435
438
|
knownTests = receivedKnownTests
|
|
436
439
|
} else {
|
|
437
440
|
isEarlyFlakeDetectionEnabled = false
|
|
441
|
+
isKnownTestsEnabled = false
|
|
438
442
|
}
|
|
439
443
|
} catch (err) {
|
|
440
444
|
isEarlyFlakeDetectionEnabled = false
|
|
445
|
+
isKnownTestsEnabled = false
|
|
441
446
|
log.error('Playwright known tests error', err)
|
|
442
447
|
}
|
|
443
448
|
}
|
|
@@ -553,7 +558,7 @@ addHook({
|
|
|
553
558
|
|
|
554
559
|
async function newCreateRootSuite () {
|
|
555
560
|
const rootSuite = await oldCreateRootSuite.apply(this, arguments)
|
|
556
|
-
if (!
|
|
561
|
+
if (!isKnownTestsEnabled) {
|
|
557
562
|
return rootSuite
|
|
558
563
|
}
|
|
559
564
|
const newTests = rootSuite
|
|
@@ -562,7 +567,7 @@ addHook({
|
|
|
562
567
|
|
|
563
568
|
newTests.forEach(newTest => {
|
|
564
569
|
newTest._ddIsNew = true
|
|
565
|
-
if (newTest.expectedStatus !== 'skipped') {
|
|
570
|
+
if (isEarlyFlakeDetectionEnabled && newTest.expectedStatus !== 'skipped') {
|
|
566
571
|
const fileSuite = getSuiteType(newTest, 'file')
|
|
567
572
|
const projectSuite = getSuiteType(newTest, 'project')
|
|
568
573
|
for (let repeatEachIndex = 0; repeatEachIndex < earlyFlakeDetectionNumRetries; repeatEachIndex++) {
|
|
@@ -25,9 +25,49 @@ const isEarlyFlakeDetectionFaultyCh = channel('ci:vitest:is-early-flake-detectio
|
|
|
25
25
|
const taskToAsync = new WeakMap()
|
|
26
26
|
const taskToStatuses = new WeakMap()
|
|
27
27
|
const newTasks = new WeakSet()
|
|
28
|
+
let isRetryReasonEfd = false
|
|
28
29
|
const switchedStatuses = new WeakSet()
|
|
29
30
|
const sessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
30
31
|
|
|
32
|
+
const BREAKPOINT_HIT_GRACE_PERIOD_MS = 400
|
|
33
|
+
|
|
34
|
+
function waitForHitProbe () {
|
|
35
|
+
return new Promise(resolve => {
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
resolve()
|
|
38
|
+
}, BREAKPOINT_HIT_GRACE_PERIOD_MS)
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getProvidedContext () {
|
|
43
|
+
try {
|
|
44
|
+
const {
|
|
45
|
+
_ddIsEarlyFlakeDetectionEnabled,
|
|
46
|
+
_ddIsDiEnabled,
|
|
47
|
+
_ddKnownTests: knownTests,
|
|
48
|
+
_ddEarlyFlakeDetectionNumRetries: numRepeats,
|
|
49
|
+
_ddIsKnownTestsEnabled: isKnownTestsEnabled
|
|
50
|
+
} = globalThis.__vitest_worker__.providedContext
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
isDiEnabled: _ddIsDiEnabled,
|
|
54
|
+
isEarlyFlakeDetectionEnabled: _ddIsEarlyFlakeDetectionEnabled,
|
|
55
|
+
knownTests,
|
|
56
|
+
numRepeats,
|
|
57
|
+
isKnownTestsEnabled
|
|
58
|
+
}
|
|
59
|
+
} catch (e) {
|
|
60
|
+
log.error('Vitest workers could not parse provided context, so some features will not work.')
|
|
61
|
+
return {
|
|
62
|
+
isDiEnabled: false,
|
|
63
|
+
isEarlyFlakeDetectionEnabled: false,
|
|
64
|
+
knownTests: {},
|
|
65
|
+
numRepeats: 0,
|
|
66
|
+
isKnownTestsEnabled: false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
31
71
|
function isReporterPackage (vitestPackage) {
|
|
32
72
|
return vitestPackage.B?.name === 'BaseSequencer'
|
|
33
73
|
}
|
|
@@ -117,6 +157,7 @@ function getSortWrapper (sort) {
|
|
|
117
157
|
let isEarlyFlakeDetectionEnabled = false
|
|
118
158
|
let earlyFlakeDetectionNumRetries = 0
|
|
119
159
|
let isEarlyFlakeDetectionFaulty = false
|
|
160
|
+
let isKnownTestsEnabled = false
|
|
120
161
|
let isDiEnabled = false
|
|
121
162
|
let knownTests = {}
|
|
122
163
|
|
|
@@ -128,22 +169,26 @@ function getSortWrapper (sort) {
|
|
|
128
169
|
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
129
170
|
earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
130
171
|
isDiEnabled = libraryConfig.isDiEnabled
|
|
172
|
+
isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
|
|
131
173
|
}
|
|
132
174
|
} catch (e) {
|
|
133
175
|
isFlakyTestRetriesEnabled = false
|
|
134
176
|
isEarlyFlakeDetectionEnabled = false
|
|
135
177
|
isDiEnabled = false
|
|
178
|
+
isKnownTestsEnabled = false
|
|
136
179
|
}
|
|
137
180
|
|
|
138
181
|
if (isFlakyTestRetriesEnabled && !this.ctx.config.retry && flakyTestRetriesCount > 0) {
|
|
139
182
|
this.ctx.config.retry = flakyTestRetriesCount
|
|
140
183
|
}
|
|
141
184
|
|
|
142
|
-
if (
|
|
185
|
+
if (isKnownTestsEnabled) {
|
|
143
186
|
const knownTestsResponse = await getChannelPromise(knownTestsCh)
|
|
144
187
|
if (!knownTestsResponse.err) {
|
|
145
188
|
knownTests = knownTestsResponse.knownTests
|
|
146
|
-
const
|
|
189
|
+
const getFilePaths = this.ctx.getTestFilepaths || this.ctx._globTestFilepaths
|
|
190
|
+
|
|
191
|
+
const testFilepaths = await getFilePaths.call(this.ctx)
|
|
147
192
|
|
|
148
193
|
isEarlyFlakeDetectionFaultyCh.publish({
|
|
149
194
|
knownTests: knownTests.vitest || {},
|
|
@@ -154,13 +199,15 @@ function getSortWrapper (sort) {
|
|
|
154
199
|
})
|
|
155
200
|
if (isEarlyFlakeDetectionFaulty) {
|
|
156
201
|
isEarlyFlakeDetectionEnabled = false
|
|
157
|
-
|
|
202
|
+
isKnownTestsEnabled = false
|
|
203
|
+
log.warn('New test detection is disabled because the number of new tests is too high.')
|
|
158
204
|
} else {
|
|
159
205
|
// TODO: use this to pass session and module IDs to the worker, instead of polluting process.env
|
|
160
206
|
// Note: setting this.ctx.config.provide directly does not work because it's cached
|
|
161
207
|
try {
|
|
162
208
|
const workspaceProject = this.ctx.getCoreWorkspaceProject()
|
|
163
|
-
workspaceProject._provided.
|
|
209
|
+
workspaceProject._provided._ddIsKnownTestsEnabled = isKnownTestsEnabled
|
|
210
|
+
workspaceProject._provided._ddKnownTests = knownTests.vitest || {}
|
|
164
211
|
workspaceProject._provided._ddIsEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
165
212
|
workspaceProject._provided._ddEarlyFlakeDetectionNumRetries = earlyFlakeDetectionNumRetries
|
|
166
213
|
} catch (e) {
|
|
@@ -169,6 +216,7 @@ function getSortWrapper (sort) {
|
|
|
169
216
|
}
|
|
170
217
|
} else {
|
|
171
218
|
isEarlyFlakeDetectionEnabled = false
|
|
219
|
+
isKnownTestsEnabled = false
|
|
172
220
|
}
|
|
173
221
|
}
|
|
174
222
|
|
|
@@ -253,29 +301,30 @@ addHook({
|
|
|
253
301
|
// `onBeforeRunTask` is run before any repetition or attempt is run
|
|
254
302
|
shimmer.wrap(VitestTestRunner.prototype, 'onBeforeRunTask', onBeforeRunTask => async function (task) {
|
|
255
303
|
const testName = getTestName(task)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
304
|
+
|
|
305
|
+
const {
|
|
306
|
+
knownTests,
|
|
307
|
+
isEarlyFlakeDetectionEnabled,
|
|
308
|
+
isKnownTestsEnabled,
|
|
309
|
+
numRepeats
|
|
310
|
+
} = getProvidedContext()
|
|
311
|
+
|
|
312
|
+
if (isKnownTestsEnabled) {
|
|
313
|
+
isNewTestCh.publish({
|
|
314
|
+
knownTests,
|
|
315
|
+
testSuiteAbsolutePath: task.file.filepath,
|
|
316
|
+
testName,
|
|
317
|
+
onDone: (isNew) => {
|
|
318
|
+
if (isNew) {
|
|
319
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
320
|
+
isRetryReasonEfd = task.repeats !== numRepeats
|
|
270
321
|
task.repeats = numRepeats
|
|
271
|
-
newTasks.add(task)
|
|
272
|
-
taskToStatuses.set(task, [])
|
|
273
322
|
}
|
|
323
|
+
newTasks.add(task)
|
|
324
|
+
taskToStatuses.set(task, [])
|
|
274
325
|
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
} catch (e) {
|
|
278
|
-
log.error('Vitest workers could not parse known tests, so Early Flake Detection will not work.')
|
|
326
|
+
}
|
|
327
|
+
})
|
|
279
328
|
}
|
|
280
329
|
|
|
281
330
|
return onBeforeRunTask.apply(this, arguments)
|
|
@@ -283,9 +332,7 @@ addHook({
|
|
|
283
332
|
|
|
284
333
|
// `onAfterRunTask` is run after all repetitions or attempts are run
|
|
285
334
|
shimmer.wrap(VitestTestRunner.prototype, 'onAfterRunTask', onAfterRunTask => async function (task) {
|
|
286
|
-
const {
|
|
287
|
-
_ddIsEarlyFlakeDetectionEnabled: isEarlyFlakeDetectionEnabled
|
|
288
|
-
} = globalThis.__vitest_worker__.providedContext
|
|
335
|
+
const { isEarlyFlakeDetectionEnabled } = getProvidedContext()
|
|
289
336
|
|
|
290
337
|
if (isEarlyFlakeDetectionEnabled && taskToStatuses.has(task)) {
|
|
291
338
|
const statuses = taskToStatuses.get(task)
|
|
@@ -309,43 +356,41 @@ addHook({
|
|
|
309
356
|
}
|
|
310
357
|
const testName = getTestName(task)
|
|
311
358
|
let isNew = false
|
|
312
|
-
let isEarlyFlakeDetectionEnabled = false
|
|
313
|
-
let isDiEnabled = false
|
|
314
359
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
isEarlyFlakeDetectionEnabled = _ddIsEarlyFlakeDetectionEnabled
|
|
322
|
-
isDiEnabled = _ddIsDiEnabled
|
|
360
|
+
const {
|
|
361
|
+
isKnownTestsEnabled,
|
|
362
|
+
isEarlyFlakeDetectionEnabled,
|
|
363
|
+
isDiEnabled
|
|
364
|
+
} = getProvidedContext()
|
|
323
365
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
} catch (e) {
|
|
328
|
-
log.error('Vitest workers could not parse known tests, so Early Flake Detection will not work.')
|
|
366
|
+
if (isKnownTestsEnabled) {
|
|
367
|
+
isNew = newTasks.has(task)
|
|
329
368
|
}
|
|
369
|
+
|
|
330
370
|
const { retry: numAttempt, repeats: numRepetition } = retryInfo
|
|
331
371
|
|
|
332
372
|
// We finish the previous test here because we know it has failed already
|
|
333
373
|
if (numAttempt > 0) {
|
|
334
|
-
const
|
|
374
|
+
const shouldWaitForHitProbe = isDiEnabled && numAttempt > 1
|
|
375
|
+
if (shouldWaitForHitProbe) {
|
|
376
|
+
await waitForHitProbe()
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const promises = {}
|
|
380
|
+
const shouldSetProbe = isDiEnabled && numAttempt === 1
|
|
335
381
|
const asyncResource = taskToAsync.get(task)
|
|
336
382
|
const testError = task.result?.errors?.[0]
|
|
337
383
|
if (asyncResource) {
|
|
338
384
|
asyncResource.runInAsyncScope(() => {
|
|
339
385
|
testErrorCh.publish({
|
|
340
386
|
error: testError,
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
isDiEnabled
|
|
387
|
+
shouldSetProbe,
|
|
388
|
+
promises
|
|
344
389
|
})
|
|
345
390
|
})
|
|
346
391
|
// We wait for the probe to be set
|
|
347
|
-
if (
|
|
348
|
-
await
|
|
392
|
+
if (promises.setProbePromise) {
|
|
393
|
+
await promises.setProbePromise
|
|
349
394
|
}
|
|
350
395
|
}
|
|
351
396
|
}
|
|
@@ -401,7 +446,9 @@ addHook({
|
|
|
401
446
|
testName,
|
|
402
447
|
testSuiteAbsolutePath: task.file.filepath,
|
|
403
448
|
isRetry: numAttempt > 0 || numRepetition > 0,
|
|
404
|
-
|
|
449
|
+
isRetryReasonEfd,
|
|
450
|
+
isNew,
|
|
451
|
+
mightHitProbe: isDiEnabled && numAttempt > 0
|
|
405
452
|
})
|
|
406
453
|
})
|
|
407
454
|
return onBeforeTryTask.apply(this, arguments)
|
|
@@ -418,6 +465,12 @@ addHook({
|
|
|
418
465
|
const status = getVitestTestStatus(task, retryCount)
|
|
419
466
|
const asyncResource = taskToAsync.get(task)
|
|
420
467
|
|
|
468
|
+
const { isDiEnabled } = getProvidedContext()
|
|
469
|
+
|
|
470
|
+
if (isDiEnabled && retryCount > 1) {
|
|
471
|
+
await waitForHitProbe()
|
|
472
|
+
}
|
|
473
|
+
|
|
421
474
|
if (asyncResource) {
|
|
422
475
|
// We don't finish here because the test might fail in a later hook (afterEach)
|
|
423
476
|
asyncResource.runInAsyncScope(() => {
|
|
@@ -457,15 +510,6 @@ addHook({
|
|
|
457
510
|
return vitestPackage
|
|
458
511
|
})
|
|
459
512
|
|
|
460
|
-
addHook({
|
|
461
|
-
name: 'vitest',
|
|
462
|
-
versions: ['>=2.1.0'],
|
|
463
|
-
filePattern: 'dist/chunks/RandomSequencer.*'
|
|
464
|
-
}, (randomSequencerPackage) => {
|
|
465
|
-
shimmer.wrap(randomSequencerPackage.B.prototype, 'sort', getSortWrapper)
|
|
466
|
-
return randomSequencerPackage
|
|
467
|
-
})
|
|
468
|
-
|
|
469
513
|
addHook({
|
|
470
514
|
name: 'vitest',
|
|
471
515
|
versions: ['>=2.0.5 <2.1.0'],
|
|
@@ -478,6 +522,24 @@ addHook({
|
|
|
478
522
|
return vitestPackage
|
|
479
523
|
})
|
|
480
524
|
|
|
525
|
+
addHook({
|
|
526
|
+
name: 'vitest',
|
|
527
|
+
versions: ['>=2.1.0 <3.0.0'],
|
|
528
|
+
filePattern: 'dist/chunks/RandomSequencer.*'
|
|
529
|
+
}, (randomSequencerPackage) => {
|
|
530
|
+
shimmer.wrap(randomSequencerPackage.B.prototype, 'sort', getSortWrapper)
|
|
531
|
+
return randomSequencerPackage
|
|
532
|
+
})
|
|
533
|
+
|
|
534
|
+
addHook({
|
|
535
|
+
name: 'vitest',
|
|
536
|
+
versions: ['>=3.0.0'],
|
|
537
|
+
filePattern: 'dist/chunks/resolveConfig.*'
|
|
538
|
+
}, (randomSequencerPackage) => {
|
|
539
|
+
shimmer.wrap(randomSequencerPackage.B.prototype, 'sort', getSortWrapper)
|
|
540
|
+
return randomSequencerPackage
|
|
541
|
+
})
|
|
542
|
+
|
|
481
543
|
// Can't specify file because compiled vitest includes hashes in their files
|
|
482
544
|
addHook({
|
|
483
545
|
name: 'vitest',
|
|
@@ -498,15 +560,17 @@ addHook({
|
|
|
498
560
|
versions: ['>=1.6.0'],
|
|
499
561
|
file: 'dist/index.js'
|
|
500
562
|
}, (vitestPackage, frameworkVersion) => {
|
|
501
|
-
shimmer.wrap(vitestPackage, 'startTests', startTests => async function (
|
|
563
|
+
shimmer.wrap(vitestPackage, 'startTests', startTests => async function (testPaths) {
|
|
502
564
|
let testSuiteError = null
|
|
503
565
|
if (!testSuiteStartCh.hasSubscribers) {
|
|
504
566
|
return startTests.apply(this, arguments)
|
|
505
567
|
}
|
|
568
|
+
// From >=3.0.1, the first arguments changes from a string to an object containing the filepath
|
|
569
|
+
const testSuiteAbsolutePath = testPaths[0]?.filepath || testPaths[0]
|
|
506
570
|
|
|
507
571
|
const testSuiteAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
508
572
|
testSuiteAsyncResource.runInAsyncScope(() => {
|
|
509
|
-
testSuiteStartCh.publish({ testSuiteAbsolutePath
|
|
573
|
+
testSuiteStartCh.publish({ testSuiteAbsolutePath, frameworkVersion })
|
|
510
574
|
})
|
|
511
575
|
const startTestsResponse = await startTests.apply(this, arguments)
|
|
512
576
|
|
|
@@ -528,7 +592,11 @@ addHook({
|
|
|
528
592
|
if (result) {
|
|
529
593
|
const { state, duration, errors } = result
|
|
530
594
|
if (state === 'skip') { // programmatic skip
|
|
531
|
-
testSkipCh.publish({
|
|
595
|
+
testSkipCh.publish({
|
|
596
|
+
testName: getTestName(task),
|
|
597
|
+
testSuiteAbsolutePath: task.file.filepath,
|
|
598
|
+
isNew: newTasks.has(task)
|
|
599
|
+
})
|
|
532
600
|
} else if (state === 'pass' && !isSwitchedStatus) {
|
|
533
601
|
if (testAsyncResource) {
|
|
534
602
|
testAsyncResource.runInAsyncScope(() => {
|
|
@@ -554,7 +622,11 @@ addHook({
|
|
|
554
622
|
}
|
|
555
623
|
}
|
|
556
624
|
} else { // test.skip or test.todo
|
|
557
|
-
testSkipCh.publish({
|
|
625
|
+
testSkipCh.publish({
|
|
626
|
+
testName: getTestName(task),
|
|
627
|
+
testSuiteAbsolutePath: task.file.filepath,
|
|
628
|
+
isNew: newTasks.has(task)
|
|
629
|
+
})
|
|
558
630
|
}
|
|
559
631
|
})
|
|
560
632
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
4
|
+
const shimmer = require('../../datadog-shimmer')
|
|
5
|
+
const names = ['vm', 'node:vm']
|
|
6
|
+
|
|
7
|
+
const runScriptStartChannel = channel('datadog:vm:run-script:start')
|
|
8
|
+
const sourceTextModuleStartChannel = channel('datadog:vm:source-text-module:start')
|
|
9
|
+
|
|
10
|
+
addHook({ name: names }, function (vm) {
|
|
11
|
+
vm.Script = class extends vm.Script {
|
|
12
|
+
constructor (code) {
|
|
13
|
+
super(...arguments)
|
|
14
|
+
|
|
15
|
+
if (runScriptStartChannel.hasSubscribers && code) {
|
|
16
|
+
runScriptStartChannel.publish({ code })
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (vm.SourceTextModule && typeof vm.SourceTextModule === 'function') {
|
|
22
|
+
vm.SourceTextModule = class extends vm.SourceTextModule {
|
|
23
|
+
constructor (code) {
|
|
24
|
+
super(...arguments)
|
|
25
|
+
|
|
26
|
+
if (sourceTextModuleStartChannel.hasSubscribers && code) {
|
|
27
|
+
sourceTextModuleStartChannel.publish({ code })
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
shimmer.wrap(vm, 'runInContext', wrapVMMethod)
|
|
34
|
+
shimmer.wrap(vm, 'runInNewContext', wrapVMMethod)
|
|
35
|
+
shimmer.wrap(vm, 'runInThisContext', wrapVMMethod)
|
|
36
|
+
shimmer.wrap(vm, 'compileFunction', wrapVMMethod)
|
|
37
|
+
|
|
38
|
+
return vm
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
function wrapVMMethod (original) {
|
|
42
|
+
return function wrappedVMMethod (code) {
|
|
43
|
+
if (runScriptStartChannel.hasSubscribers && code) {
|
|
44
|
+
runScriptStartChannel.publish({ code })
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return original.apply(this, arguments)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const CompositePlugin = require('../../../../dd-trace/src/plugins/composite')
|
|
2
|
+
const BedrockRuntimeTracing = require('./tracing')
|
|
3
|
+
const BedrockRuntimeLLMObsPlugin = require('../../../../dd-trace/src/llmobs/plugins/bedrockruntime')
|
|
4
|
+
class BedrockRuntimePlugin extends CompositePlugin {
|
|
5
|
+
static get id () {
|
|
6
|
+
return 'bedrockruntime'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static get plugins () {
|
|
10
|
+
return {
|
|
11
|
+
llmobs: BedrockRuntimeLLMObsPlugin,
|
|
12
|
+
tracing: BedrockRuntimeTracing
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
module.exports = BedrockRuntimePlugin
|