dd-trace 5.51.0 → 5.53.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 +0 -6
- package/README.md +5 -0
- package/index.d.ts +88 -6
- package/package.json +3 -9
- package/packages/datadog-instrumentations/src/amqplib.js +8 -5
- package/packages/datadog-instrumentations/src/child_process.js +2 -1
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +406 -0
- package/packages/datadog-instrumentations/src/couchbase.js +2 -1
- package/packages/datadog-instrumentations/src/cucumber.js +43 -45
- package/packages/datadog-instrumentations/src/dns.js +16 -14
- package/packages/datadog-instrumentations/src/express.js +2 -6
- package/packages/datadog-instrumentations/src/fs.js +43 -51
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +17 -12
- package/packages/datadog-instrumentations/src/http/client.js +2 -1
- package/packages/datadog-instrumentations/src/iovalkey.js +51 -0
- package/packages/datadog-instrumentations/src/jest.js +53 -40
- package/packages/datadog-instrumentations/src/kafkajs.js +21 -8
- package/packages/datadog-instrumentations/src/mocha/main.js +33 -46
- package/packages/datadog-instrumentations/src/mocha/utils.js +76 -74
- package/packages/datadog-instrumentations/src/mysql2.js +3 -1
- package/packages/datadog-instrumentations/src/net.js +27 -29
- package/packages/datadog-instrumentations/src/next.js +6 -14
- package/packages/datadog-instrumentations/src/pg.js +15 -7
- package/packages/datadog-instrumentations/src/playwright.js +64 -67
- package/packages/datadog-instrumentations/src/url.js +9 -17
- package/packages/datadog-instrumentations/src/vitest.js +66 -72
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +11 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +11 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +19 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +11 -0
- package/packages/datadog-plugin-cucumber/src/index.js +32 -18
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +3 -0
- package/packages/datadog-plugin-dns/src/lookup.js +10 -5
- package/packages/datadog-plugin-dns/src/lookup_service.js +6 -2
- package/packages/datadog-plugin-dns/src/resolve.js +5 -2
- package/packages/datadog-plugin-dns/src/reverse.js +6 -2
- package/packages/datadog-plugin-fs/src/index.js +9 -2
- package/packages/datadog-plugin-iovalkey/src/index.js +18 -0
- package/packages/datadog-plugin-jest/src/index.js +17 -8
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -1
- package/packages/datadog-plugin-kafkajs/src/consumer.js +12 -21
- package/packages/datadog-plugin-kafkajs/src/producer.js +12 -5
- package/packages/datadog-plugin-kafkajs/src/utils.js +27 -0
- package/packages/datadog-plugin-langchain/src/index.js +0 -1
- package/packages/datadog-plugin-mocha/src/index.js +58 -35
- package/packages/datadog-plugin-net/src/ipc.js +6 -4
- package/packages/datadog-plugin-net/src/tcp.js +15 -9
- package/packages/datadog-plugin-pg/src/index.js +5 -1
- package/packages/datadog-plugin-playwright/src/index.js +29 -20
- package/packages/datadog-plugin-redis/src/index.js +8 -3
- package/packages/datadog-plugin-vitest/src/index.js +67 -44
- package/packages/datadog-shimmer/src/shimmer.js +164 -33
- package/packages/dd-trace/src/appsec/api_security_sampler.js +20 -12
- package/packages/dd-trace/src/appsec/graphql.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +14 -9
- package/packages/dd-trace/src/appsec/index.js +15 -12
- package/packages/dd-trace/src/appsec/rasp/index.js +4 -2
- package/packages/dd-trace/src/appsec/rasp/utils.js +11 -6
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
- package/packages/dd-trace/src/appsec/telemetry/index.js +1 -2
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +0 -9
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -6
- package/packages/dd-trace/src/baggage.js +36 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
- package/packages/dd-trace/src/config.js +14 -2
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +61 -7
- package/packages/dd-trace/src/debugger/devtools_client/index.js +10 -26
- package/packages/dd-trace/src/debugger/devtools_client/send.js +8 -7
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +15 -7
- package/packages/dd-trace/src/debugger/devtools_client/state.js +22 -2
- package/packages/dd-trace/src/dogstatsd.js +2 -0
- package/packages/dd-trace/src/exporters/common/docker.js +13 -31
- package/packages/dd-trace/src/guardrails/telemetry.js +2 -5
- package/packages/dd-trace/src/llmobs/tagger.js +3 -3
- package/packages/dd-trace/src/llmobs/writers/base.js +33 -12
- package/packages/dd-trace/src/noop/proxy.js +5 -0
- package/packages/dd-trace/src/opentelemetry/context_manager.js +2 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -9
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/index.js +4 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +9 -20
- package/packages/dd-trace/src/plugins/outbound.js +11 -3
- package/packages/dd-trace/src/plugins/tracing.js +8 -4
- package/packages/dd-trace/src/plugins/util/test.js +1 -1
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +15 -14
- package/packages/dd-trace/src/proxy.js +12 -4
- package/packages/dd-trace/src/serverless.js +0 -48
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/standalone/product.js +3 -5
|
@@ -26,7 +26,7 @@ const {
|
|
|
26
26
|
getOnHookEndHandler,
|
|
27
27
|
getOnFailHandler,
|
|
28
28
|
getOnPendingHandler,
|
|
29
|
-
|
|
29
|
+
testFileToSuiteCtx,
|
|
30
30
|
newTests,
|
|
31
31
|
testsQuarantined,
|
|
32
32
|
getTestFullName,
|
|
@@ -53,7 +53,7 @@ const originalCoverageMap = createCoverageMap()
|
|
|
53
53
|
let untestedCoverage
|
|
54
54
|
|
|
55
55
|
// test channels
|
|
56
|
-
const
|
|
56
|
+
const testFinishCh = channel('ci:mocha:test:finish')
|
|
57
57
|
|
|
58
58
|
// test suite channels
|
|
59
59
|
const testSuiteStartCh = channel('ci:mocha:test-suite:start')
|
|
@@ -166,7 +166,7 @@ function getOnEndHandler (isParallel) {
|
|
|
166
166
|
error = new Error(`Failed tests: ${this.failures}.`)
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
testFileToSuiteCtx.clear()
|
|
170
170
|
|
|
171
171
|
let testCodeCoverageLinesTotal
|
|
172
172
|
if (global.__coverage__) {
|
|
@@ -312,7 +312,7 @@ addHook({
|
|
|
312
312
|
}, (Mocha) => {
|
|
313
313
|
shimmer.wrap(Mocha.prototype, 'run', run => function () {
|
|
314
314
|
// Workers do not need to request any data, just run the tests
|
|
315
|
-
if (!
|
|
315
|
+
if (!testFinishCh.hasSubscribers || process.env.MOCHA_WORKER_ID || this.options.parallel) {
|
|
316
316
|
return run.apply(this, arguments)
|
|
317
317
|
}
|
|
318
318
|
|
|
@@ -367,7 +367,7 @@ addHook({
|
|
|
367
367
|
}, (run) => {
|
|
368
368
|
// `runMocha` is an async function
|
|
369
369
|
shimmer.wrap(run, 'runMocha', runMocha => function () {
|
|
370
|
-
if (!
|
|
370
|
+
if (!testFinishCh.hasSubscribers) {
|
|
371
371
|
return runMocha.apply(this, arguments)
|
|
372
372
|
}
|
|
373
373
|
const mocha = arguments[0]
|
|
@@ -403,7 +403,7 @@ addHook({
|
|
|
403
403
|
shimmer.wrap(Runner.prototype, 'runTests', runTests => getRunTestsWrapper(runTests, config))
|
|
404
404
|
|
|
405
405
|
shimmer.wrap(Runner.prototype, 'run', run => function () {
|
|
406
|
-
if (!
|
|
406
|
+
if (!testFinishCh.hasSubscribers) {
|
|
407
407
|
return run.apply(this, arguments)
|
|
408
408
|
}
|
|
409
409
|
|
|
@@ -430,20 +430,18 @@ addHook({
|
|
|
430
430
|
if (suite.root || !suite.tests.length) {
|
|
431
431
|
return
|
|
432
432
|
}
|
|
433
|
-
let
|
|
434
|
-
if (!
|
|
435
|
-
asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
436
|
-
testFileToSuiteAr.set(suite.file, asyncResource)
|
|
433
|
+
let ctx = testFileToSuiteCtx.get(suite.file)
|
|
434
|
+
if (!ctx) {
|
|
437
435
|
const isUnskippable = unskippableSuites.includes(suite.file)
|
|
438
436
|
isForcedToRun = isUnskippable && suitesToSkip.includes(getTestSuitePath(suite.file, process.cwd()))
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
})
|
|
437
|
+
ctx = {
|
|
438
|
+
testSuiteAbsolutePath: suite.file,
|
|
439
|
+
isUnskippable,
|
|
440
|
+
isForcedToRun,
|
|
441
|
+
itrCorrelationId
|
|
442
|
+
}
|
|
443
|
+
testFileToSuiteCtx.set(suite.file, ctx)
|
|
444
|
+
testSuiteStartCh.runStores(ctx, () => { })
|
|
447
445
|
}
|
|
448
446
|
})
|
|
449
447
|
|
|
@@ -485,11 +483,9 @@ addHook({
|
|
|
485
483
|
resetCoverage(global.__coverage__)
|
|
486
484
|
}
|
|
487
485
|
|
|
488
|
-
const
|
|
489
|
-
if (
|
|
490
|
-
|
|
491
|
-
testSuiteFinishCh.publish(status)
|
|
492
|
-
})
|
|
486
|
+
const ctx = testFileToSuiteCtx.get(suite.file)
|
|
487
|
+
if (ctx) {
|
|
488
|
+
testSuiteFinishCh.publish({ status, ...ctx.currentStore }, () => { })
|
|
493
489
|
} else {
|
|
494
490
|
log.warn(() => `No AsyncResource found for suite ${suite.file}`)
|
|
495
491
|
}
|
|
@@ -520,58 +516,49 @@ addHook({
|
|
|
520
516
|
file: 'src/WorkerHandler.js'
|
|
521
517
|
}, (workerHandlerPackage) => {
|
|
522
518
|
shimmer.wrap(workerHandlerPackage.prototype, 'exec', exec => function (_, path) {
|
|
523
|
-
if (!
|
|
519
|
+
if (!testFinishCh.hasSubscribers) {
|
|
524
520
|
return exec.apply(this, arguments)
|
|
525
521
|
}
|
|
526
522
|
if (!path?.length) {
|
|
527
523
|
return exec.apply(this, arguments)
|
|
528
524
|
}
|
|
529
525
|
const [testSuiteAbsolutePath] = path
|
|
530
|
-
const
|
|
526
|
+
const testSuiteContext = { }
|
|
531
527
|
|
|
532
528
|
function onMessage (message) {
|
|
533
529
|
if (Array.isArray(message)) {
|
|
534
530
|
const [messageCode, payload] = message
|
|
535
531
|
if (messageCode === MOCHA_WORKER_TRACE_PAYLOAD_CODE) {
|
|
536
|
-
|
|
537
|
-
workerReportTraceCh.publish(payload)
|
|
538
|
-
})
|
|
532
|
+
workerReportTraceCh.publish(payload)
|
|
539
533
|
}
|
|
540
534
|
}
|
|
541
535
|
}
|
|
542
536
|
|
|
543
537
|
this.worker.on('message', onMessage)
|
|
544
538
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
testSuiteAbsolutePath
|
|
548
|
-
})
|
|
549
|
-
})
|
|
539
|
+
testSuiteContext.testSuiteAbsolutePath = testSuiteAbsolutePath
|
|
540
|
+
testSuiteStartCh.runStores(testSuiteContext, () => { })
|
|
550
541
|
|
|
551
542
|
try {
|
|
552
543
|
const promise = exec.apply(this, arguments)
|
|
553
544
|
promise.then(
|
|
554
545
|
(result) => {
|
|
555
546
|
const status = result.failureCount === 0 ? 'pass' : 'fail'
|
|
556
|
-
|
|
557
|
-
testSuiteFinishCh.publish(status)
|
|
558
|
-
})
|
|
547
|
+
testSuiteFinishCh.publish({ status, ...testSuiteContext.currentStore }, () => { })
|
|
559
548
|
this.worker.off('message', onMessage)
|
|
560
549
|
},
|
|
561
550
|
(err) => {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
})
|
|
551
|
+
testSuiteContext.error = err
|
|
552
|
+
testSuiteErrorCh.runStores(testSuiteContext, () => { })
|
|
553
|
+
testSuiteFinishCh.publish({ status: 'fail', ...testSuiteContext.currentStore }, () => { })
|
|
566
554
|
this.worker.off('message', onMessage)
|
|
567
555
|
}
|
|
568
556
|
)
|
|
569
557
|
return promise
|
|
570
558
|
} catch (err) {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
})
|
|
559
|
+
testSuiteContext.error = err
|
|
560
|
+
testSuiteErrorCh.runStores(testSuiteContext, () => { })
|
|
561
|
+
testSuiteFinishCh.publish({ status: 'fail', ...testSuiteContext.currentStore }, () => { })
|
|
575
562
|
this.worker.off('message', onMessage)
|
|
576
563
|
throw err
|
|
577
564
|
}
|
|
@@ -588,7 +575,7 @@ addHook({
|
|
|
588
575
|
file: 'lib/nodejs/parallel-buffered-runner.js'
|
|
589
576
|
}, (ParallelBufferedRunner, frameworkVersion) => {
|
|
590
577
|
shimmer.wrap(ParallelBufferedRunner.prototype, 'run', run => function (cb, { files }) {
|
|
591
|
-
if (!
|
|
578
|
+
if (!testFinishCh.hasSubscribers) {
|
|
592
579
|
return run.apply(this, arguments)
|
|
593
580
|
}
|
|
594
581
|
|
|
@@ -629,7 +616,7 @@ addHook({
|
|
|
629
616
|
const { BufferedWorkerPool } = BufferedWorkerPoolPackage
|
|
630
617
|
|
|
631
618
|
shimmer.wrap(BufferedWorkerPool.prototype, 'run', run => async function (testSuiteAbsolutePath, workerArgs) {
|
|
632
|
-
if (!
|
|
619
|
+
if (!testFinishCh.hasSubscribers || (!config.isKnownTestsEnabled && !config.isTestManagementTestsEnabled)) {
|
|
633
620
|
return run.apply(this, arguments)
|
|
634
621
|
}
|
|
635
622
|
|
|
@@ -7,7 +7,7 @@ const {
|
|
|
7
7
|
addAttemptToFixStringToTestName,
|
|
8
8
|
removeAttemptToFixStringFromTestName
|
|
9
9
|
} = require('../../../dd-trace/src/plugins/util/test')
|
|
10
|
-
const { channel
|
|
10
|
+
const { channel } = require('../helpers/instrument')
|
|
11
11
|
const shimmer = require('../../../datadog-shimmer')
|
|
12
12
|
|
|
13
13
|
// test channels
|
|
@@ -17,15 +17,16 @@ const testFinishCh = channel('ci:mocha:test:finish')
|
|
|
17
17
|
const testRetryCh = channel('ci:mocha:test:retry')
|
|
18
18
|
const errorCh = channel('ci:mocha:test:error')
|
|
19
19
|
const skipCh = channel('ci:mocha:test:skip')
|
|
20
|
+
const testFnCh = channel('ci:mocha:test:fn')
|
|
20
21
|
|
|
21
22
|
// suite channels
|
|
22
23
|
const testSuiteErrorCh = channel('ci:mocha:test-suite:error')
|
|
23
24
|
|
|
24
25
|
const BREAKPOINT_HIT_GRACE_PERIOD_MS = 200
|
|
25
|
-
const
|
|
26
|
+
const testToContext = new WeakMap()
|
|
26
27
|
const originalFns = new WeakMap()
|
|
27
28
|
const testToStartLine = new WeakMap()
|
|
28
|
-
const
|
|
29
|
+
const testFileToSuiteCtx = new Map()
|
|
29
30
|
const wrappedFunctions = new WeakSet()
|
|
30
31
|
const newTests = {}
|
|
31
32
|
const testsAttemptToFix = new Set()
|
|
@@ -125,7 +126,7 @@ function getTestStatus (test) {
|
|
|
125
126
|
return 'pass'
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
function
|
|
129
|
+
function getTestToContextKey (test) {
|
|
129
130
|
if (!test.fn) {
|
|
130
131
|
return test
|
|
131
132
|
}
|
|
@@ -136,14 +137,14 @@ function getTestToArKey (test) {
|
|
|
136
137
|
return originalFn
|
|
137
138
|
}
|
|
138
139
|
|
|
139
|
-
function
|
|
140
|
-
const key =
|
|
141
|
-
return
|
|
140
|
+
function getTestContext (test) {
|
|
141
|
+
const key = getTestToContextKey(test)
|
|
142
|
+
return testToContext.get(key)
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
function runnableWrapper (RunnablePackage, libraryConfig) {
|
|
145
146
|
shimmer.wrap(RunnablePackage.prototype, 'run', run => function () {
|
|
146
|
-
if (!
|
|
147
|
+
if (!testFinishCh.hasSubscribers) {
|
|
147
148
|
return run.apply(this, arguments)
|
|
148
149
|
}
|
|
149
150
|
// Flaky test retries does not work in parallel mode
|
|
@@ -167,14 +168,17 @@ function runnableWrapper (RunnablePackage, libraryConfig) {
|
|
|
167
168
|
|
|
168
169
|
if (isTestHook || this.type === 'test') {
|
|
169
170
|
const test = isTestHook ? this.ctx.currentTest : this
|
|
170
|
-
const
|
|
171
|
+
const ctx = getTestContext(test)
|
|
171
172
|
|
|
172
|
-
if (
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
if (ctx) {
|
|
174
|
+
const originalFn = this.fn
|
|
175
|
+
// we bind the test fn to the correct context
|
|
176
|
+
const newFn = function () {
|
|
177
|
+
return testFnCh.runStores(ctx, () => originalFn.apply(this, arguments))
|
|
178
|
+
}
|
|
175
179
|
|
|
176
180
|
// we store the original function, not to lose it
|
|
177
|
-
originalFns.set(newFn,
|
|
181
|
+
originalFns.set(newFn, originalFn)
|
|
178
182
|
this.fn = newFn
|
|
179
183
|
|
|
180
184
|
wrappedFunctions.add(this.fn)
|
|
@@ -189,7 +193,6 @@ function runnableWrapper (RunnablePackage, libraryConfig) {
|
|
|
189
193
|
function getOnTestHandler (isMain) {
|
|
190
194
|
return function (test) {
|
|
191
195
|
const testStartLine = testToStartLine.get(test)
|
|
192
|
-
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
193
196
|
|
|
194
197
|
// This may be a retry. If this is the case, `test.fn` is already wrapped,
|
|
195
198
|
// so we need to restore it.
|
|
@@ -198,7 +201,6 @@ function getOnTestHandler (isMain) {
|
|
|
198
201
|
test.fn = originalFn
|
|
199
202
|
wrappedFunctions.delete(test.fn)
|
|
200
203
|
}
|
|
201
|
-
testToAr.set(test.fn, asyncResource)
|
|
202
204
|
|
|
203
205
|
const {
|
|
204
206
|
file: testSuiteAbsolutePath,
|
|
@@ -242,15 +244,15 @@ function getOnTestHandler (isMain) {
|
|
|
242
244
|
test.pending = true
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
})
|
|
247
|
+
const ctx = testInfo
|
|
248
|
+
testToContext.set(test.fn, ctx)
|
|
249
|
+
testStartCh.runStores(ctx, () => { })
|
|
248
250
|
}
|
|
249
251
|
}
|
|
250
252
|
|
|
251
253
|
function getOnTestEndHandler (config) {
|
|
252
254
|
return async function (test) {
|
|
253
|
-
const
|
|
255
|
+
const ctx = getTestContext(test)
|
|
254
256
|
const status = getTestStatus(test)
|
|
255
257
|
|
|
256
258
|
// After finishing it might take a bit for the snapshot to be handled.
|
|
@@ -265,6 +267,7 @@ function getOnTestEndHandler (config) {
|
|
|
265
267
|
|
|
266
268
|
let hasFailedAllRetries = false
|
|
267
269
|
let attemptToFixPassed = false
|
|
270
|
+
let attemptToFixFailed = false
|
|
268
271
|
|
|
269
272
|
const testName = getTestFullName(test)
|
|
270
273
|
|
|
@@ -278,6 +281,9 @@ function getOnTestEndHandler (config) {
|
|
|
278
281
|
const isLastAttempt = testStatuses.length === config.testManagementAttemptToFixRetries + 1
|
|
279
282
|
|
|
280
283
|
if (test._ddIsAttemptToFix && isLastAttempt) {
|
|
284
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
285
|
+
attemptToFixFailed = true
|
|
286
|
+
}
|
|
281
287
|
if (testStatuses.every(status => status === 'fail')) {
|
|
282
288
|
hasFailedAllRetries = true
|
|
283
289
|
} else if (testStatuses.every(status => status === 'pass')) {
|
|
@@ -291,17 +297,17 @@ function getOnTestEndHandler (config) {
|
|
|
291
297
|
!test._ddIsEfdRetry
|
|
292
298
|
|
|
293
299
|
// if there are afterEach to be run, we don't finish the test yet
|
|
294
|
-
if (
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
300
|
+
if (ctx && !getAfterEachHooks(test).length) {
|
|
301
|
+
testFinishCh.publish({
|
|
302
|
+
status,
|
|
303
|
+
hasBeenRetried: isMochaRetry(test),
|
|
304
|
+
isLastRetry: getIsLastRetry(test),
|
|
305
|
+
hasFailedAllRetries,
|
|
306
|
+
attemptToFixPassed,
|
|
307
|
+
attemptToFixFailed,
|
|
308
|
+
isAttemptToFixRetry,
|
|
309
|
+
isAtrRetry,
|
|
310
|
+
...ctx.currentStore
|
|
305
311
|
})
|
|
306
312
|
}
|
|
307
313
|
}
|
|
@@ -315,10 +321,13 @@ function getOnHookEndHandler () {
|
|
|
315
321
|
const isLastAfterEach = afterEachHooks.indexOf(hook) === afterEachHooks.length - 1
|
|
316
322
|
if (isLastAfterEach) {
|
|
317
323
|
const status = getTestStatus(test)
|
|
318
|
-
const
|
|
319
|
-
if (
|
|
320
|
-
|
|
321
|
-
|
|
324
|
+
const ctx = getTestContext(test)
|
|
325
|
+
if (ctx) {
|
|
326
|
+
testFinishCh.publish({
|
|
327
|
+
status,
|
|
328
|
+
hasBeenRetried: isMochaRetry(test),
|
|
329
|
+
isLastRetry: getIsLastRetry(test),
|
|
330
|
+
...ctx.currentStore
|
|
322
331
|
})
|
|
323
332
|
}
|
|
324
333
|
}
|
|
@@ -334,35 +343,34 @@ function getOnFailHandler (isMain) {
|
|
|
334
343
|
if (isHook && testOrHook.ctx) {
|
|
335
344
|
test = testOrHook.ctx.currentTest
|
|
336
345
|
}
|
|
337
|
-
let
|
|
346
|
+
let testContext
|
|
338
347
|
if (test) {
|
|
339
|
-
|
|
348
|
+
testContext = getTestContext(test)
|
|
340
349
|
}
|
|
341
|
-
if (
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
}
|
|
350
|
+
if (testContext) {
|
|
351
|
+
if (isHook) {
|
|
352
|
+
err.message = `${testOrHook.fullTitle()}: ${err.message}`
|
|
353
|
+
testContext.err = err
|
|
354
|
+
errorCh.runStores(testContext, () => { })
|
|
355
|
+
// if it's a hook and it has failed, 'test end' will not be called
|
|
356
|
+
testFinishCh.publish({ status: 'fail', hasBeenRetried: isMochaRetry(test), ...testContext.currentStore })
|
|
357
|
+
} else {
|
|
358
|
+
testContext.err = err
|
|
359
|
+
errorCh.runStores(testContext, () => { })
|
|
360
|
+
}
|
|
352
361
|
}
|
|
353
362
|
|
|
354
363
|
if (isMain) {
|
|
355
|
-
const
|
|
364
|
+
const testSuiteContext = testFileToSuiteCtx.get(testFile)
|
|
356
365
|
|
|
357
|
-
if (
|
|
366
|
+
if (testSuiteContext) {
|
|
358
367
|
// we propagate the error to the suite
|
|
359
368
|
const testSuiteError = new Error(
|
|
360
369
|
`"${testOrHook.parent.fullTitle()}" failed with message "${err.message}"`
|
|
361
370
|
)
|
|
362
371
|
testSuiteError.stack = err.stack
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
})
|
|
372
|
+
testSuiteContext.error = testSuiteError
|
|
373
|
+
testSuiteErrorCh.runStores(testSuiteContext, () => { })
|
|
366
374
|
}
|
|
367
375
|
}
|
|
368
376
|
}
|
|
@@ -370,20 +378,18 @@ function getOnFailHandler (isMain) {
|
|
|
370
378
|
|
|
371
379
|
function getOnTestRetryHandler (config) {
|
|
372
380
|
return function (test, err) {
|
|
373
|
-
const
|
|
374
|
-
if (
|
|
381
|
+
const ctx = getTestContext(test)
|
|
382
|
+
if (ctx) {
|
|
375
383
|
const isFirstAttempt = test._currentRetry === 0
|
|
376
384
|
const willBeRetried = test._currentRetry < test._retries
|
|
377
385
|
const isAtrRetry = !isFirstAttempt &&
|
|
378
386
|
config.isFlakyTestRetriesEnabled &&
|
|
379
387
|
!test._ddIsAttemptToFix &&
|
|
380
388
|
!test._ddIsEfdRetry
|
|
381
|
-
|
|
382
|
-
testRetryCh.publish({ isFirstAttempt, err, willBeRetried, test, isAtrRetry })
|
|
383
|
-
})
|
|
389
|
+
testRetryCh.publish({ isFirstAttempt, err, willBeRetried, test, isAtrRetry, ...ctx.currentStore })
|
|
384
390
|
}
|
|
385
|
-
const key =
|
|
386
|
-
|
|
391
|
+
const key = getTestToContextKey(test)
|
|
392
|
+
testToContext.delete(key)
|
|
387
393
|
}
|
|
388
394
|
}
|
|
389
395
|
|
|
@@ -402,23 +408,19 @@ function getOnPendingHandler () {
|
|
|
402
408
|
testStartLine
|
|
403
409
|
}
|
|
404
410
|
|
|
405
|
-
const
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
skipCh.publish(testInfo)
|
|
409
|
-
})
|
|
411
|
+
const ctx = getTestContext(test)
|
|
412
|
+
if (ctx) {
|
|
413
|
+
skipCh.publish(testInfo)
|
|
410
414
|
} else {
|
|
411
|
-
// if there is no
|
|
415
|
+
// if there is no context, the test has been skipped through `test.skip`
|
|
412
416
|
// or the parent suite is skipped
|
|
413
|
-
const
|
|
417
|
+
const testCtx = testInfo
|
|
414
418
|
if (test.fn) {
|
|
415
|
-
|
|
419
|
+
testToContext.set(test.fn, testCtx)
|
|
416
420
|
} else {
|
|
417
|
-
|
|
421
|
+
testToContext.set(test, testCtx)
|
|
418
422
|
}
|
|
419
|
-
|
|
420
|
-
skipCh.publish(testInfo)
|
|
421
|
-
})
|
|
423
|
+
skipCh.runStores(testCtx, () => { })
|
|
422
424
|
}
|
|
423
425
|
}
|
|
424
426
|
}
|
|
@@ -479,9 +481,9 @@ module.exports = {
|
|
|
479
481
|
getTestFullName,
|
|
480
482
|
getTestStatus,
|
|
481
483
|
runnableWrapper,
|
|
482
|
-
|
|
484
|
+
testToContext,
|
|
483
485
|
originalFns,
|
|
484
|
-
|
|
486
|
+
getTestContext,
|
|
485
487
|
testToStartLine,
|
|
486
488
|
getOnTestHandler,
|
|
487
489
|
getOnTestEndHandler,
|
|
@@ -489,7 +491,7 @@ module.exports = {
|
|
|
489
491
|
getOnHookEndHandler,
|
|
490
492
|
getOnFailHandler,
|
|
491
493
|
getOnPendingHandler,
|
|
492
|
-
|
|
494
|
+
testFileToSuiteCtx,
|
|
493
495
|
getRunTestsWrapper,
|
|
494
496
|
newTests,
|
|
495
497
|
testsQuarantined,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { errorMonitor } = require('node:events')
|
|
4
|
+
|
|
3
5
|
const {
|
|
4
6
|
channel,
|
|
5
7
|
addHook,
|
|
@@ -138,7 +140,7 @@ function wrapConnection (Connection, version) {
|
|
|
138
140
|
onResult.apply(this, arguments)
|
|
139
141
|
}, 'bound-anonymous-fn', this))
|
|
140
142
|
} else {
|
|
141
|
-
this.on(
|
|
143
|
+
this.on(errorMonitor, asyncResource.bind(error => errorCh.publish(error)))
|
|
142
144
|
this.on('end', asyncResource.bind(() => finishCh.publish(undefined)))
|
|
143
145
|
}
|
|
144
146
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
AsyncResource
|
|
7
|
-
} = require('./helpers/instrument')
|
|
3
|
+
const { errorMonitor } = require('events')
|
|
4
|
+
|
|
5
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
8
6
|
const shimmer = require('../../datadog-shimmer')
|
|
9
7
|
|
|
10
8
|
const startICPCh = channel('apm:net:ipc:start')
|
|
@@ -15,6 +13,7 @@ const startTCPCh = channel('apm:net:tcp:start')
|
|
|
15
13
|
const finishTCPCh = channel('apm:net:tcp:finish')
|
|
16
14
|
const errorTCPCh = channel('apm:net:tcp:error')
|
|
17
15
|
|
|
16
|
+
const readyCh = channel('apm:net:tcp:ready')
|
|
18
17
|
const connectionCh = channel('apm:net:tcp:connection')
|
|
19
18
|
|
|
20
19
|
const names = ['net', 'node:net']
|
|
@@ -39,30 +38,27 @@ addHook({ name: names }, (net, version, name) => {
|
|
|
39
38
|
|
|
40
39
|
if (!options) return connect.apply(this, arguments)
|
|
41
40
|
|
|
42
|
-
const
|
|
43
|
-
const
|
|
41
|
+
const protocol = options.path ? 'ipc' : 'tcp'
|
|
42
|
+
const startCh = protocol === 'ipc' ? startICPCh : startTCPCh
|
|
43
|
+
const finishCh = protocol === 'ipc' ? finishICPCh : finishTCPCh
|
|
44
|
+
const errorCh = protocol === 'ipc' ? errorICPCh : errorTCPCh
|
|
45
|
+
const ctx = { options }
|
|
44
46
|
|
|
45
47
|
if (typeof callback === 'function') {
|
|
46
|
-
arguments[lastIndex] =
|
|
48
|
+
arguments[lastIndex] = function (...args) {
|
|
49
|
+
return finishCh.runStores(ctx, callback, this, ...args)
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return asyncResource.runInAsyncScope(() => {
|
|
52
|
-
if (protocol === 'ipc') {
|
|
53
|
-
startICPCh.publish({ options })
|
|
54
|
-
setupListeners(this, 'ipc', asyncResource)
|
|
55
|
-
} else {
|
|
56
|
-
startTCPCh.publish({ options })
|
|
57
|
-
setupListeners(this, 'tcp', asyncResource)
|
|
58
|
-
}
|
|
53
|
+
return startCh.runStores(ctx, () => {
|
|
54
|
+
setupListeners(this, protocol, ctx, finishCh, errorCh)
|
|
59
55
|
|
|
60
56
|
const emit = this.emit
|
|
61
57
|
this.emit = shimmer.wrapFunction(emit, emit => function (eventName) {
|
|
62
58
|
switch (eventName) {
|
|
63
59
|
case 'ready':
|
|
64
60
|
case 'connect':
|
|
65
|
-
return
|
|
61
|
+
return readyCh.runStores(ctx, () => {
|
|
66
62
|
return emit.apply(this, arguments)
|
|
67
63
|
})
|
|
68
64
|
default:
|
|
@@ -73,7 +69,7 @@ addHook({ name: names }, (net, version, name) => {
|
|
|
73
69
|
try {
|
|
74
70
|
return connect.apply(this, arguments)
|
|
75
71
|
} catch (err) {
|
|
76
|
-
|
|
72
|
+
errorCh.publish(err)
|
|
77
73
|
|
|
78
74
|
throw err
|
|
79
75
|
}
|
|
@@ -104,19 +100,21 @@ function getOptions (args) {
|
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
102
|
|
|
107
|
-
function setupListeners (socket, protocol,
|
|
108
|
-
const events = ['connect',
|
|
103
|
+
function setupListeners (socket, protocol, ctx, finishCh, errorCh) {
|
|
104
|
+
const events = ['connect', errorMonitor, 'close', 'timeout']
|
|
109
105
|
|
|
110
|
-
const wrapListener =
|
|
106
|
+
const wrapListener = function (error) {
|
|
111
107
|
if (error) {
|
|
112
|
-
|
|
108
|
+
ctx.error = error
|
|
109
|
+
errorCh.publish(ctx)
|
|
113
110
|
}
|
|
114
|
-
|
|
115
|
-
}
|
|
111
|
+
finishCh.runStores(ctx, () => {})
|
|
112
|
+
}
|
|
116
113
|
|
|
117
|
-
const localListener =
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
const localListener = function () {
|
|
115
|
+
ctx.socket = socket
|
|
116
|
+
connectionCh.publish(ctx)
|
|
117
|
+
}
|
|
120
118
|
|
|
121
119
|
const cleanupListener = function () {
|
|
122
120
|
socket.removeListener('connect', localListener)
|