dd-trace 5.87.0 → 5.89.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 +60 -32
- package/ext/exporters.d.ts +1 -0
- package/ext/exporters.js +1 -0
- package/ext/tags.js +2 -0
- package/index.d.ts +234 -4
- package/package.json +18 -11
- package/packages/datadog-instrumentations/src/ai.js +54 -90
- package/packages/datadog-instrumentations/src/helpers/hook.js +17 -11
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +27 -110
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +103 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/bullmq.js +108 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/orchestrion/compiler.js +74 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/orchestrion/index.js +43 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/orchestrion/matcher.js +49 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/orchestrion/transformer.js +121 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/{transforms.js → orchestrion/transforms.js} +143 -17
- package/packages/datadog-instrumentations/src/jest.js +176 -54
- package/packages/datadog-instrumentations/src/kafkajs.js +20 -17
- package/packages/datadog-instrumentations/src/playwright.js +1 -1
- package/packages/datadog-plugin-amqplib/src/consumer.js +14 -10
- package/packages/datadog-plugin-amqplib/src/producer.js +23 -19
- package/packages/datadog-plugin-bullmq/src/consumer.js +33 -11
- package/packages/datadog-plugin-bullmq/src/producer.js +60 -31
- package/packages/datadog-plugin-cucumber/src/index.js +9 -6
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +62 -5
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +297 -0
- package/packages/datadog-plugin-cypress/src/support.js +52 -9
- package/packages/datadog-plugin-jest/src/index.js +12 -2
- package/packages/datadog-plugin-jest/src/util.js +2 -1
- package/packages/datadog-plugin-kafkajs/src/consumer.js +22 -12
- package/packages/datadog-plugin-kafkajs/src/producer.js +33 -22
- package/packages/datadog-plugin-mocha/src/index.js +9 -6
- package/packages/datadog-plugin-playwright/src/index.js +10 -6
- package/packages/datadog-plugin-vitest/src/index.js +13 -8
- package/packages/dd-trace/src/aiguard/sdk.js +5 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +4 -5
- package/packages/dd-trace/src/appsec/iast/path-line.js +36 -25
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -4
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +3 -2
- package/packages/dd-trace/src/azure_metadata.js +0 -2
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +3 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +1 -1
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -1
- package/packages/dd-trace/src/ci-visibility/requests/request.js +236 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
- package/packages/dd-trace/src/config/defaults.js +148 -197
- package/packages/dd-trace/src/config/helper.js +43 -1
- package/packages/dd-trace/src/config/index.js +38 -14
- package/packages/dd-trace/src/config/supported-configurations.json +4125 -512
- package/packages/dd-trace/src/constants.js +0 -2
- package/packages/dd-trace/src/crashtracking/crashtracker.js +10 -3
- package/packages/dd-trace/src/datastreams/checkpointer.js +13 -0
- package/packages/dd-trace/src/datastreams/index.js +3 -0
- package/packages/dd-trace/src/datastreams/manager.js +9 -0
- package/packages/dd-trace/src/datastreams/pathway.js +22 -3
- package/packages/dd-trace/src/datastreams/processor.js +140 -4
- package/packages/dd-trace/src/encode/agentless-json.js +155 -0
- package/packages/dd-trace/src/exporter.js +2 -0
- package/packages/dd-trace/src/exporters/agent/writer.js +21 -8
- package/packages/dd-trace/src/exporters/agentless/index.js +89 -0
- package/packages/dd-trace/src/exporters/agentless/writer.js +184 -0
- package/packages/dd-trace/src/exporters/common/request.js +4 -4
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -3
- package/packages/dd-trace/src/opentelemetry/context_manager.js +19 -46
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +3 -4
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +3 -5
- package/packages/dd-trace/src/opentracing/span.js +6 -4
- package/packages/dd-trace/src/pkg.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +57 -5
- package/packages/dd-trace/src/plugins/database.js +15 -2
- package/packages/dd-trace/src/plugins/util/test.js +48 -0
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -0
- package/packages/dd-trace/src/propagation-hash/index.js +145 -0
- package/packages/dd-trace/src/proxy.js +6 -1
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +1 -1
- package/packages/dd-trace/src/startup-log.js +53 -19
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/@datadog/source-map/index.js +1 -1
- package/vendor/dist/@isaacs/ttlcache/index.js +1 -1
- package/vendor/dist/@opentelemetry/core/index.js +1 -1
- package/vendor/dist/@opentelemetry/resources/index.js +1 -1
- package/vendor/dist/astring/index.js +1 -1
- package/vendor/dist/crypto-randomuuid/index.js +1 -1
- package/vendor/dist/escape-string-regexp/index.js +1 -1
- package/vendor/dist/esquery/index.js +1 -1
- package/vendor/dist/ignore/index.js +1 -1
- package/vendor/dist/istanbul-lib-coverage/index.js +1 -1
- package/vendor/dist/jest-docblock/index.js +1 -1
- package/vendor/dist/jsonpath-plus/index.js +1 -1
- package/vendor/dist/limiter/index.js +1 -1
- package/vendor/dist/lodash.sortby/index.js +1 -1
- package/vendor/dist/lru-cache/index.js +1 -1
- package/vendor/dist/meriyah/index.js +1 -1
- package/vendor/dist/module-details-from-path/index.js +1 -1
- package/vendor/dist/mutexify/promise/index.js +1 -1
- package/vendor/dist/opentracing/index.js +1 -1
- package/vendor/dist/path-to-regexp/index.js +1 -1
- package/vendor/dist/pprof-format/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/retry/index.js +1 -1
- package/vendor/dist/rfdc/index.js +1 -1
- package/vendor/dist/semifies/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
- package/vendor/dist/source-map/index.js +1 -1
- package/vendor/dist/source-map/lib/util/index.js +1 -1
- package/vendor/dist/tlhunter-sorted-set/index.js +1 -1
- package/vendor/dist/ttl-set/index.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +0 -33
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/bullmq.json +0 -106
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +0 -741
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +0 -11
- package/packages/dd-trace/src/scope/noop/scope.js +0 -21
|
@@ -21,6 +21,7 @@ const {
|
|
|
21
21
|
getFormattedJestTestParameters,
|
|
22
22
|
getJestTestName,
|
|
23
23
|
getJestSuitesToRun,
|
|
24
|
+
getEfdRetryCount,
|
|
24
25
|
} = require('../../datadog-plugin-jest/src/util')
|
|
25
26
|
const { addHook, channel } = require('./helpers/instrument')
|
|
26
27
|
|
|
@@ -68,7 +69,9 @@ const RETRY_TIMES = Symbol.for('RETRY_TIMES')
|
|
|
68
69
|
let skippableSuites = []
|
|
69
70
|
let knownTests = {}
|
|
70
71
|
let isCodeCoverageEnabled = false
|
|
72
|
+
let isCodeCoverageEnabledBecauseOfUs = false
|
|
71
73
|
let isSuitesSkippingEnabled = false
|
|
74
|
+
let isKeepingCoverageConfiguration = false
|
|
72
75
|
let isUserCodeCoverageEnabled = false
|
|
73
76
|
let isSuitesSkipped = false
|
|
74
77
|
let numSkippedSuites = 0
|
|
@@ -76,6 +79,7 @@ let hasUnskippableSuites = false
|
|
|
76
79
|
let hasForcedToRunSuites = false
|
|
77
80
|
let isEarlyFlakeDetectionEnabled = false
|
|
78
81
|
let earlyFlakeDetectionNumRetries = 0
|
|
82
|
+
let earlyFlakeDetectionSlowTestRetries = {}
|
|
79
83
|
let earlyFlakeDetectionFaultyThreshold = 30
|
|
80
84
|
let isEarlyFlakeDetectionFaulty = false
|
|
81
85
|
let hasFilteredSkippableSuites = false
|
|
@@ -95,6 +99,12 @@ const attemptToFixRetriedTestsStatuses = new Map()
|
|
|
95
99
|
const wrappedWorkers = new WeakSet()
|
|
96
100
|
const testSuiteMockedFiles = new Map()
|
|
97
101
|
const testsToBeRetried = new Set()
|
|
102
|
+
// Per-test: how many EFD retries were determined after the first execution.
|
|
103
|
+
const efdDeterminedRetries = new Map()
|
|
104
|
+
// Tests whose first run exceeded the 5-min threshold — tagged "slow".
|
|
105
|
+
const efdSlowAbortedTests = new Set()
|
|
106
|
+
// Tests added as EFD new-test candidates (not ATF, not impacted).
|
|
107
|
+
const efdNewTestCandidates = new Set()
|
|
98
108
|
const testSuiteAbsolutePathsWithFastCheck = new Set()
|
|
99
109
|
const testSuiteJestObjects = new Map()
|
|
100
110
|
|
|
@@ -197,7 +207,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
197
207
|
this.isImpactedTestsEnabled = this.testEnvironmentOptions._ddIsImpactedTestsEnabled
|
|
198
208
|
|
|
199
209
|
if (this.isKnownTestsEnabled) {
|
|
200
|
-
|
|
210
|
+
earlyFlakeDetectionSlowTestRetries = this.testEnvironmentOptions._ddEarlyFlakeDetectionSlowTestRetries ?? {}
|
|
201
211
|
try {
|
|
202
212
|
this.knownTestsForThisSuite = this.getKnownTestsForSuite(this.testEnvironmentOptions._ddKnownTests)
|
|
203
213
|
|
|
@@ -466,7 +476,13 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
466
476
|
testContexts.set(event.test, ctx)
|
|
467
477
|
|
|
468
478
|
testStartCh.runStores(ctx, () => {
|
|
469
|
-
|
|
479
|
+
let p = event.test.parent
|
|
480
|
+
const hooks = []
|
|
481
|
+
while (p != null) {
|
|
482
|
+
hooks.push(...p.hooks)
|
|
483
|
+
p = p.parent
|
|
484
|
+
}
|
|
485
|
+
for (const hook of hooks) {
|
|
470
486
|
let hookFn = hook.fn
|
|
471
487
|
if (originalHookFns.has(hook)) {
|
|
472
488
|
hookFn = originalHookFns.get(hook)
|
|
@@ -537,11 +553,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
537
553
|
retriedTestsToNumAttempts.set(testFullName, 0)
|
|
538
554
|
if (this.isEarlyFlakeDetectionEnabled) {
|
|
539
555
|
testsToBeRetried.add(testFullName)
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
retryType: 'Early flake detection',
|
|
544
|
-
})
|
|
556
|
+
efdNewTestCandidates.add(testFullName)
|
|
557
|
+
// Cloning is deferred to test_done after the first execution,
|
|
558
|
+
// when we know the duration and can choose the right retry count.
|
|
545
559
|
}
|
|
546
560
|
}
|
|
547
561
|
}
|
|
@@ -566,8 +580,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
566
580
|
let attemptToFixFailed = false
|
|
567
581
|
let failedAllTests = false
|
|
568
582
|
let isAttemptToFix = false
|
|
583
|
+
const testName = getJestTestName(event.test, this.getShouldStripSeedFromTestName())
|
|
569
584
|
if (this.isTestManagementTestsEnabled) {
|
|
570
|
-
const testName = getJestTestName(event.test, this.getShouldStripSeedFromTestName())
|
|
571
585
|
isAttemptToFix = this.testManagementTestsForThisSuite?.attemptToFix?.includes(testName)
|
|
572
586
|
if (isAttemptToFix) {
|
|
573
587
|
if (attemptToFixRetriedTestsStatuses.has(testName)) {
|
|
@@ -592,9 +606,53 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
592
606
|
}
|
|
593
607
|
}
|
|
594
608
|
|
|
609
|
+
// EFD dynamic cloning: on first execution of a new EFD candidate,
|
|
610
|
+
// determine the retry count from the test's duration.
|
|
611
|
+
if (
|
|
612
|
+
this.isEarlyFlakeDetectionEnabled &&
|
|
613
|
+
this.isKnownTestsEnabled &&
|
|
614
|
+
efdNewTestCandidates.has(testName) &&
|
|
615
|
+
event.test.invocations === 1 &&
|
|
616
|
+
!efdDeterminedRetries.has(testName)
|
|
617
|
+
) {
|
|
618
|
+
const durationMs = event.test.duration ?? 0
|
|
619
|
+
const retryCount = getEfdRetryCount(durationMs, earlyFlakeDetectionSlowTestRetries)
|
|
620
|
+
efdDeterminedRetries.set(testName, retryCount)
|
|
621
|
+
if (retryCount > 0) {
|
|
622
|
+
// Temporarily adjust jest-circus state so that retry tests are registered
|
|
623
|
+
// into the correct describe block and bypass the "tests have started" guard.
|
|
624
|
+
//
|
|
625
|
+
// Problem 1 (jest-circus ≤24): currentDescribeBlock points to ROOT during
|
|
626
|
+
// execution, and ROOT's tests loop already finished before children ran.
|
|
627
|
+
//
|
|
628
|
+
// Problem 2 (jest-circus ≥27): `hasStarted = true` causes `test()` to throw
|
|
629
|
+
// "Cannot add a test after tests have started running".
|
|
630
|
+
//
|
|
631
|
+
// Fix: temporarily point currentDescribeBlock to the test's parent (so retries
|
|
632
|
+
// land in the still-iterating children array) and set hasStarted = false (so the
|
|
633
|
+
// guard is bypassed). Both are restored immediately after scheduling the retries.
|
|
634
|
+
const originalDescribeBlock = state.currentDescribeBlock
|
|
635
|
+
const originalHasStarted = state.hasStarted
|
|
636
|
+
state.currentDescribeBlock = event.test.parent ?? originalDescribeBlock
|
|
637
|
+
state.hasStarted = false
|
|
638
|
+
this.retryTest({
|
|
639
|
+
jestEvent: {
|
|
640
|
+
testName: event.test.name,
|
|
641
|
+
fn: event.test.fn,
|
|
642
|
+
timeout: event.test.timeout,
|
|
643
|
+
},
|
|
644
|
+
retryCount,
|
|
645
|
+
retryType: 'Early flake detection',
|
|
646
|
+
})
|
|
647
|
+
state.currentDescribeBlock = originalDescribeBlock
|
|
648
|
+
state.hasStarted = originalHasStarted
|
|
649
|
+
} else {
|
|
650
|
+
efdSlowAbortedTests.add(testName)
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
595
654
|
let isEfdRetry = false
|
|
596
655
|
// We'll store the test statuses of the retries
|
|
597
|
-
const testName = getJestTestName(event.test, this.getShouldStripSeedFromTestName())
|
|
598
656
|
if (this.isKnownTestsEnabled) {
|
|
599
657
|
const isNewTest = retriedTestsToNumAttempts.has(testName)
|
|
600
658
|
if (isNewTest) {
|
|
@@ -607,7 +665,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
607
665
|
const testStatuses = newTestsTestStatuses.get(testName)
|
|
608
666
|
// Check if this is the last EFD retry.
|
|
609
667
|
// If it is, we'll set the failedAllTests flag to true if all the tests failed
|
|
610
|
-
|
|
668
|
+
const efdRetryCount = efdDeterminedRetries.get(testName) ?? 0
|
|
669
|
+
if (efdRetryCount > 0 && testStatuses.length === efdRetryCount + 1 &&
|
|
611
670
|
testStatuses.every(status => status === 'fail')) {
|
|
612
671
|
failedAllTests = true
|
|
613
672
|
}
|
|
@@ -665,6 +724,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
665
724
|
attemptToFixFailed,
|
|
666
725
|
isAtrRetry,
|
|
667
726
|
finalStatus,
|
|
727
|
+
earlyFlakeAbortReason: efdSlowAbortedTests.has(testName) ? 'slow' : undefined,
|
|
668
728
|
})
|
|
669
729
|
|
|
670
730
|
if (promises.isProbeReady) {
|
|
@@ -676,6 +736,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
676
736
|
test.errors = errors
|
|
677
737
|
}
|
|
678
738
|
atrSuppressedErrors.clear()
|
|
739
|
+
efdDeterminedRetries.clear()
|
|
740
|
+
efdSlowAbortedTests.clear()
|
|
741
|
+
efdNewTestCandidates.clear()
|
|
679
742
|
}
|
|
680
743
|
if (event.name === 'test_skip' || event.name === 'test_todo') {
|
|
681
744
|
const testName = getJestTestName(event.test, this.getShouldStripSeedFromTestName())
|
|
@@ -696,7 +759,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
696
759
|
getEfdResult ({ testName, isNewTest, isModifiedTest, isEfdRetry, numberOfExecutedRetries }) {
|
|
697
760
|
const isEfdEnabled = this.isEarlyFlakeDetectionEnabled
|
|
698
761
|
const isEfdActive = isEfdEnabled && (isNewTest || isModifiedTest)
|
|
699
|
-
const
|
|
762
|
+
const retryCount = efdDeterminedRetries.get(testName) ?? 0
|
|
763
|
+
const isSlowAbort = efdSlowAbortedTests.has(testName)
|
|
764
|
+
const isLastEfdRetry = (isEfdRetry && numberOfExecutedRetries >= (retryCount + 1)) || isSlowAbort
|
|
700
765
|
const isFinalEfdTestExecution = isEfdActive && isLastEfdRetry
|
|
701
766
|
|
|
702
767
|
let finalStatus
|
|
@@ -931,8 +996,11 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
931
996
|
if (!err) {
|
|
932
997
|
isCodeCoverageEnabled = libraryConfig.isCodeCoverageEnabled
|
|
933
998
|
isSuitesSkippingEnabled = libraryConfig.isSuitesSkippingEnabled
|
|
999
|
+
isKeepingCoverageConfiguration =
|
|
1000
|
+
libraryConfig.isKeepingCoverageConfiguration ?? isKeepingCoverageConfiguration
|
|
934
1001
|
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
935
1002
|
earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
1003
|
+
earlyFlakeDetectionSlowTestRetries = libraryConfig.earlyFlakeDetectionSlowTestRetries ?? {}
|
|
936
1004
|
earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold
|
|
937
1005
|
isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
|
|
938
1006
|
isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
|
|
@@ -1263,9 +1331,10 @@ function coverageReporterWrapper (coverageReporter) {
|
|
|
1263
1331
|
*/
|
|
1264
1332
|
// `_addUntestedFiles` is an async function
|
|
1265
1333
|
shimmer.wrap(CoverageReporter.prototype, '_addUntestedFiles', addUntestedFiles => function () {
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1334
|
+
if (isKeepingCoverageConfiguration) {
|
|
1335
|
+
return addUntestedFiles.apply(this, arguments)
|
|
1336
|
+
}
|
|
1337
|
+
if (isCodeCoverageEnabledBecauseOfUs) {
|
|
1269
1338
|
return Promise.resolve()
|
|
1270
1339
|
}
|
|
1271
1340
|
return addUntestedFiles.apply(this, arguments)
|
|
@@ -1445,12 +1514,13 @@ function configureTestEnvironment (readConfigsResult) {
|
|
|
1445
1514
|
}
|
|
1446
1515
|
|
|
1447
1516
|
isUserCodeCoverageEnabled = !!readConfigsResult.globalConfig.collectCoverage
|
|
1517
|
+
isCodeCoverageEnabledBecauseOfUs = isCodeCoverageEnabled && !isUserCodeCoverageEnabled
|
|
1448
1518
|
|
|
1449
1519
|
if (readConfigsResult.globalConfig.forceExit) {
|
|
1450
1520
|
log.warn("Jest's '--forceExit' flag has been passed. This may cause loss of data.")
|
|
1451
1521
|
}
|
|
1452
1522
|
|
|
1453
|
-
if (
|
|
1523
|
+
if (isCodeCoverageEnabledBecauseOfUs) {
|
|
1454
1524
|
const globalConfig = {
|
|
1455
1525
|
...readConfigsResult.globalConfig,
|
|
1456
1526
|
collectCoverage: true,
|
|
@@ -1458,14 +1528,18 @@ function configureTestEnvironment (readConfigsResult) {
|
|
|
1458
1528
|
readConfigsResult.globalConfig = globalConfig
|
|
1459
1529
|
}
|
|
1460
1530
|
if (isSuitesSkippingEnabled) {
|
|
1461
|
-
// If suite skipping is enabled,
|
|
1462
|
-
// so we do not show them.
|
|
1463
|
-
// Also, we might skip every test, so we need to pass `passWithNoTests`
|
|
1531
|
+
// If suite skipping is enabled, we pass `passWithNoTests` in case every test gets skipped.
|
|
1464
1532
|
const globalConfig = {
|
|
1465
1533
|
...readConfigsResult.globalConfig,
|
|
1466
|
-
coverageReporters: ['none'],
|
|
1467
1534
|
passWithNoTests: true,
|
|
1468
1535
|
}
|
|
1536
|
+
if (isCodeCoverageEnabledBecauseOfUs && !isKeepingCoverageConfiguration) {
|
|
1537
|
+
globalConfig.coverageReporters = ['none']
|
|
1538
|
+
readConfigsResult.configs = configs.map(config => ({
|
|
1539
|
+
...config,
|
|
1540
|
+
coverageReporters: ['none'],
|
|
1541
|
+
}))
|
|
1542
|
+
}
|
|
1469
1543
|
readConfigsResult.globalConfig = globalConfig
|
|
1470
1544
|
}
|
|
1471
1545
|
|
|
@@ -1488,49 +1562,97 @@ function jestConfigSyncWrapper (jestConfig) {
|
|
|
1488
1562
|
})
|
|
1489
1563
|
}
|
|
1490
1564
|
|
|
1565
|
+
const DD_TEST_ENVIRONMENT_OPTION_KEYS = [
|
|
1566
|
+
'_ddTestModuleId',
|
|
1567
|
+
'_ddTestSessionId',
|
|
1568
|
+
'_ddTestCommand',
|
|
1569
|
+
'_ddTestSessionName',
|
|
1570
|
+
'_ddForcedToRun',
|
|
1571
|
+
'_ddUnskippable',
|
|
1572
|
+
'_ddItrCorrelationId',
|
|
1573
|
+
'_ddKnownTests',
|
|
1574
|
+
'_ddIsEarlyFlakeDetectionEnabled',
|
|
1575
|
+
'_ddEarlyFlakeDetectionSlowTestRetries',
|
|
1576
|
+
'_ddRepositoryRoot',
|
|
1577
|
+
'_ddIsFlakyTestRetriesEnabled',
|
|
1578
|
+
'_ddFlakyTestRetriesCount',
|
|
1579
|
+
'_ddIsDiEnabled',
|
|
1580
|
+
'_ddIsKnownTestsEnabled',
|
|
1581
|
+
'_ddIsTestManagementTestsEnabled',
|
|
1582
|
+
'_ddTestManagementTests',
|
|
1583
|
+
'_ddTestManagementAttemptToFixRetries',
|
|
1584
|
+
'_ddModifiedFiles',
|
|
1585
|
+
]
|
|
1586
|
+
|
|
1587
|
+
function removeDatadogTestEnvironmentOptions (testEnvironmentOptions) {
|
|
1588
|
+
const removedEntries = []
|
|
1589
|
+
|
|
1590
|
+
for (const key of DD_TEST_ENVIRONMENT_OPTION_KEYS) {
|
|
1591
|
+
if (!Object.hasOwn(testEnvironmentOptions, key)) {
|
|
1592
|
+
continue
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
removedEntries.push([key, testEnvironmentOptions[key]])
|
|
1596
|
+
delete testEnvironmentOptions[key]
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
return function restoreDatadogTestEnvironmentOptions () {
|
|
1600
|
+
for (const [key, value] of removedEntries) {
|
|
1601
|
+
testEnvironmentOptions[key] = value
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
/**
|
|
1607
|
+
* Wrap `createScriptTransformer` to temporarily hide Datadog-specific
|
|
1608
|
+
* `testEnvironmentOptions` keys while Jest builds its transform config.
|
|
1609
|
+
*
|
|
1610
|
+
* @param {Function} createScriptTransformer
|
|
1611
|
+
* @returns {Function}
|
|
1612
|
+
*/
|
|
1613
|
+
function wrapCreateScriptTransformer (createScriptTransformer) {
|
|
1614
|
+
return function (config) {
|
|
1615
|
+
const testEnvironmentOptions = config?.testEnvironmentOptions
|
|
1616
|
+
|
|
1617
|
+
if (!testEnvironmentOptions) {
|
|
1618
|
+
return createScriptTransformer.apply(this, arguments)
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
const restoreTestEnvironmentOptions = removeDatadogTestEnvironmentOptions(testEnvironmentOptions)
|
|
1622
|
+
|
|
1623
|
+
try {
|
|
1624
|
+
const result = createScriptTransformer.apply(this, arguments)
|
|
1625
|
+
|
|
1626
|
+
if (result?.then) {
|
|
1627
|
+
return result.finally(restoreTestEnvironmentOptions)
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
restoreTestEnvironmentOptions()
|
|
1631
|
+
return result
|
|
1632
|
+
} catch (e) {
|
|
1633
|
+
restoreTestEnvironmentOptions()
|
|
1634
|
+
throw e
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1491
1639
|
addHook({
|
|
1492
1640
|
name: '@jest/transform',
|
|
1493
|
-
versions: ['>=24.8.0'],
|
|
1641
|
+
versions: ['>=24.8.0 <30.0.0'],
|
|
1494
1642
|
file: 'build/ScriptTransformer.js',
|
|
1495
1643
|
}, transformPackage => {
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
// `createScriptTransformer` is an async function
|
|
1499
|
-
transformPackage.createScriptTransformer = function (config) {
|
|
1500
|
-
const { testEnvironmentOptions, ...restOfConfig } = config
|
|
1501
|
-
const {
|
|
1502
|
-
_ddTestModuleId,
|
|
1503
|
-
_ddTestSessionId,
|
|
1504
|
-
_ddTestCommand,
|
|
1505
|
-
_ddTestSessionName,
|
|
1506
|
-
_ddForcedToRun,
|
|
1507
|
-
_ddUnskippable,
|
|
1508
|
-
_ddItrCorrelationId,
|
|
1509
|
-
_ddKnownTests,
|
|
1510
|
-
_ddIsEarlyFlakeDetectionEnabled,
|
|
1511
|
-
_ddEarlyFlakeDetectionNumRetries,
|
|
1512
|
-
_ddRepositoryRoot,
|
|
1513
|
-
_ddIsFlakyTestRetriesEnabled,
|
|
1514
|
-
_ddFlakyTestRetriesCount,
|
|
1515
|
-
_ddIsDiEnabled,
|
|
1516
|
-
_ddIsKnownTestsEnabled,
|
|
1517
|
-
_ddIsTestManagementTestsEnabled,
|
|
1518
|
-
_ddTestManagementTests,
|
|
1519
|
-
_ddTestManagementAttemptToFixRetries,
|
|
1520
|
-
_ddModifiedFiles,
|
|
1521
|
-
...restOfTestEnvironmentOptions
|
|
1522
|
-
} = testEnvironmentOptions
|
|
1523
|
-
|
|
1524
|
-
restOfConfig.testEnvironmentOptions = restOfTestEnvironmentOptions
|
|
1525
|
-
|
|
1526
|
-
arguments[0] = restOfConfig
|
|
1527
|
-
|
|
1528
|
-
return originalCreateScriptTransformer.apply(this, arguments)
|
|
1529
|
-
}
|
|
1644
|
+
transformPackage.createScriptTransformer = wrapCreateScriptTransformer(transformPackage.createScriptTransformer)
|
|
1530
1645
|
|
|
1531
1646
|
return transformPackage
|
|
1532
1647
|
})
|
|
1533
1648
|
|
|
1649
|
+
addHook({
|
|
1650
|
+
name: '@jest/transform',
|
|
1651
|
+
versions: ['>=30.0.0'],
|
|
1652
|
+
}, transformPackage => {
|
|
1653
|
+
return shimmer.wrap(transformPackage, 'createScriptTransformer', wrapCreateScriptTransformer, { replaceGetter: true })
|
|
1654
|
+
})
|
|
1655
|
+
|
|
1534
1656
|
/**
|
|
1535
1657
|
* Hook to remove the test paths (test suite) that are part of `skippableSuites`
|
|
1536
1658
|
*/
|
|
@@ -24,22 +24,6 @@ const batchConsumerErrorCh = channel('apm:kafkajs:consume-batch:error')
|
|
|
24
24
|
|
|
25
25
|
const disabledHeaderWeakSet = new WeakSet()
|
|
26
26
|
|
|
27
|
-
function commitsFromEvent (event) {
|
|
28
|
-
const { payload: { groupId, topics } } = event
|
|
29
|
-
const commitList = []
|
|
30
|
-
for (const { topic, partitions } of topics) {
|
|
31
|
-
for (const { partition, offset } of partitions) {
|
|
32
|
-
commitList.push({
|
|
33
|
-
groupId,
|
|
34
|
-
partition,
|
|
35
|
-
offset,
|
|
36
|
-
topic,
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
consumerCommitCh.publish(commitList)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
27
|
addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKafka) => {
|
|
44
28
|
class Kafka extends BaseKafka {
|
|
45
29
|
constructor (options) {
|
|
@@ -132,6 +116,7 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
132
116
|
}
|
|
133
117
|
|
|
134
118
|
const kafkaClusterIdPromise = getKafkaClusterId(this)
|
|
119
|
+
let resolvedClusterId = null
|
|
135
120
|
|
|
136
121
|
const eachMessageExtractor = (args, clusterId) => {
|
|
137
122
|
const { topic, partition, message } = args[0]
|
|
@@ -146,13 +131,31 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
146
131
|
|
|
147
132
|
const consumer = createConsumer.apply(this, arguments)
|
|
148
133
|
|
|
149
|
-
consumer.on(consumer.events.COMMIT_OFFSETS,
|
|
134
|
+
consumer.on(consumer.events.COMMIT_OFFSETS, (event) => {
|
|
135
|
+
const { payload: { groupId: commitGroupId, topics } } = event
|
|
136
|
+
const commitList = []
|
|
137
|
+
for (const { topic, partitions } of topics) {
|
|
138
|
+
for (const { partition, offset } of partitions) {
|
|
139
|
+
commitList.push({
|
|
140
|
+
groupId: commitGroupId,
|
|
141
|
+
partition,
|
|
142
|
+
offset,
|
|
143
|
+
topic,
|
|
144
|
+
clusterId: resolvedClusterId,
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
consumerCommitCh.publish(commitList)
|
|
149
|
+
})
|
|
150
150
|
|
|
151
151
|
const run = consumer.run
|
|
152
152
|
const groupId = arguments[0].groupId
|
|
153
153
|
|
|
154
154
|
consumer.run = function ({ eachMessage, eachBatch, ...runArgs }) {
|
|
155
155
|
const wrapConsume = (clusterId) => {
|
|
156
|
+
// In kafkajs COMMIT_OFFSETS always happens in the context of one synchronous run
|
|
157
|
+
// So this will always reference a correct cluster id
|
|
158
|
+
resolvedClusterId = clusterId
|
|
156
159
|
return run({
|
|
157
160
|
eachMessage: wrappedCallback(
|
|
158
161
|
eachMessage,
|
|
@@ -41,7 +41,7 @@ const testSuiteToTestStatuses = new Map()
|
|
|
41
41
|
const testSuiteToErrors = new Map()
|
|
42
42
|
const testsToTestStatuses = new Map()
|
|
43
43
|
|
|
44
|
-
const RUM_FLUSH_WAIT_TIME = Number(getValueFromEnvSources('DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS')) ||
|
|
44
|
+
const RUM_FLUSH_WAIT_TIME = Number(getValueFromEnvSources('DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS')) || 500
|
|
45
45
|
|
|
46
46
|
let applyRepeatEachIndex = null
|
|
47
47
|
|
|
@@ -9,6 +9,19 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
|
|
|
9
9
|
static id = 'amqplib'
|
|
10
10
|
static operation = 'consume'
|
|
11
11
|
|
|
12
|
+
start (ctx) {
|
|
13
|
+
if (!this.config.dsmEnabled) return
|
|
14
|
+
const { fields = {}, message, queue } = ctx
|
|
15
|
+
if (!message?.properties?.headers) return
|
|
16
|
+
|
|
17
|
+
const { span } = ctx.currentStore
|
|
18
|
+
const queueName = queue || fields.queue || fields.routingKey
|
|
19
|
+
const payloadSize = getAmqpMessageSize({ headers: message.properties.headers, content: message.content })
|
|
20
|
+
this.tracer.decodeDataStreamsContext(message.properties.headers)
|
|
21
|
+
this.tracer
|
|
22
|
+
.setCheckpoint(['direction:in', `topic:${queueName}`, 'type:rabbitmq'], span, payloadSize)
|
|
23
|
+
}
|
|
24
|
+
|
|
12
25
|
bindStart (ctx) {
|
|
13
26
|
const { method, fields = {}, message, queue } = ctx
|
|
14
27
|
|
|
@@ -17,7 +30,7 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
|
|
|
17
30
|
const childOf = extract(this.tracer, message)
|
|
18
31
|
|
|
19
32
|
const queueName = queue || fields.queue || fields.routingKey
|
|
20
|
-
|
|
33
|
+
this.startSpan({
|
|
21
34
|
childOf,
|
|
22
35
|
resource: getResourceName(method, fields),
|
|
23
36
|
type: 'worker',
|
|
@@ -31,15 +44,6 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
|
|
|
31
44
|
},
|
|
32
45
|
}, ctx)
|
|
33
46
|
|
|
34
|
-
if (
|
|
35
|
-
this.config.dsmEnabled && message?.properties?.headers
|
|
36
|
-
) {
|
|
37
|
-
const payloadSize = getAmqpMessageSize({ headers: message.properties.headers, content: message.content })
|
|
38
|
-
this.tracer.decodeDataStreamsContext(message.properties.headers)
|
|
39
|
-
this.tracer
|
|
40
|
-
.setCheckpoint(['direction:in', `topic:${queueName}`, 'type:rabbitmq'], span, payloadSize)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
47
|
return ctx.currentStore
|
|
44
48
|
}
|
|
45
49
|
}
|
|
@@ -10,8 +10,30 @@ class AmqplibProducerPlugin extends ProducerPlugin {
|
|
|
10
10
|
static id = 'amqplib'
|
|
11
11
|
static operation = 'publish'
|
|
12
12
|
|
|
13
|
+
start (ctx) {
|
|
14
|
+
if (!this.config.dsmEnabled) return
|
|
15
|
+
const { fields, message } = ctx
|
|
16
|
+
const { span } = ctx.currentStore
|
|
17
|
+
|
|
18
|
+
const hasRoutingKey = fields.routingKey != null
|
|
19
|
+
const payloadSize = getAmqpMessageSize({ content: message, headers: fields.headers })
|
|
20
|
+
|
|
21
|
+
// there are two ways to send messages in RabbitMQ:
|
|
22
|
+
// 1. using an exchange and a routing key in which DSM connects via the exchange
|
|
23
|
+
// 2. using an unnamed exchange and a routing key in which DSM connects via the topic
|
|
24
|
+
const exchangeOrTopicTag = hasRoutingKey && !fields.exchange
|
|
25
|
+
? `topic:${fields.routingKey}`
|
|
26
|
+
: `exchange:${fields.exchange}`
|
|
27
|
+
|
|
28
|
+
const dataStreamsContext = this.tracer.setCheckpoint(
|
|
29
|
+
['direction:out', exchangeOrTopicTag, `has_routing_key:${hasRoutingKey}`, 'type:rabbitmq'],
|
|
30
|
+
span, payloadSize
|
|
31
|
+
)
|
|
32
|
+
DsmPathwayCodec.encode(dataStreamsContext, fields.headers)
|
|
33
|
+
}
|
|
34
|
+
|
|
13
35
|
bindStart (ctx) {
|
|
14
|
-
const { channel = {}, method, fields
|
|
36
|
+
const { channel = {}, method, fields } = ctx
|
|
15
37
|
|
|
16
38
|
if (method !== 'basic.publish') return
|
|
17
39
|
|
|
@@ -34,24 +56,6 @@ class AmqplibProducerPlugin extends ProducerPlugin {
|
|
|
34
56
|
|
|
35
57
|
this.tracer.inject(span, TEXT_MAP, fields.headers)
|
|
36
58
|
|
|
37
|
-
if (this.config.dsmEnabled) {
|
|
38
|
-
const hasRoutingKey = fields.routingKey != null
|
|
39
|
-
const payloadSize = getAmqpMessageSize({ content: message, headers: fields.headers })
|
|
40
|
-
|
|
41
|
-
// there are two ways to send messages in RabbitMQ:
|
|
42
|
-
// 1. using an exchange and a routing key in which DSM connects via the exchange
|
|
43
|
-
// 2. using an unnamed exchange and a routing key in which DSM connects via the topic
|
|
44
|
-
const exchangeOrTopicTag = hasRoutingKey && !fields.exchange
|
|
45
|
-
? `topic:${fields.routingKey}`
|
|
46
|
-
: `exchange:${fields.exchange}`
|
|
47
|
-
|
|
48
|
-
const dataStreamsContext = this.tracer
|
|
49
|
-
.setCheckpoint(
|
|
50
|
-
['direction:out', exchangeOrTopicTag, `has_routing_key:${hasRoutingKey}`, 'type:rabbitmq']
|
|
51
|
-
, span, payloadSize)
|
|
52
|
-
DsmPathwayCodec.encode(dataStreamsContext, fields.headers)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
59
|
return ctx.currentStore
|
|
56
60
|
}
|
|
57
61
|
}
|
|
@@ -11,17 +11,24 @@ class BullmqConsumerPlugin extends ConsumerPlugin {
|
|
|
11
11
|
ctx.currentStore?.span?.finish()
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
start (ctx) {
|
|
15
|
+
if (!this.config.dsmEnabled) return
|
|
16
|
+
const { span } = ctx.currentStore
|
|
17
|
+
this.setConsumerCheckpoint(span, ctx)
|
|
18
|
+
}
|
|
19
|
+
|
|
14
20
|
bindStart (ctx) {
|
|
15
21
|
const job = ctx.arguments?.[0]
|
|
16
22
|
const queueName = job?.queueName || job?.queue?.name || 'bullmq'
|
|
17
23
|
|
|
18
24
|
let childOf
|
|
19
|
-
const
|
|
20
|
-
if (
|
|
21
|
-
|
|
25
|
+
const ddCarrier = this._extractDatadog(job)
|
|
26
|
+
if (ddCarrier) {
|
|
27
|
+
ctx._ddCarrier = ddCarrier
|
|
28
|
+
childOf = this.tracer.extract('text_map', ddCarrier)
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
|
|
31
|
+
this.startSpan({
|
|
25
32
|
childOf,
|
|
26
33
|
resource: queueName,
|
|
27
34
|
meta: {
|
|
@@ -33,10 +40,6 @@ class BullmqConsumerPlugin extends ConsumerPlugin {
|
|
|
33
40
|
},
|
|
34
41
|
}, ctx)
|
|
35
42
|
|
|
36
|
-
if (this.config.dsmEnabled) {
|
|
37
|
-
this.setConsumerCheckpoint(span, ctx)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
43
|
return ctx.currentStore
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -47,14 +50,33 @@ class BullmqConsumerPlugin extends ConsumerPlugin {
|
|
|
47
50
|
const queueName = job.queueName || job.queue?.name || 'bullmq'
|
|
48
51
|
const payloadSize = job.data ? getMessageSize(job.data) : 0
|
|
49
52
|
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
this.tracer.decodeDataStreamsContext(
|
|
53
|
+
const ddCarrier = ctx._ddCarrier
|
|
54
|
+
if (ddCarrier) {
|
|
55
|
+
this.tracer.decodeDataStreamsContext(ddCarrier)
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
const edgeTags = ['direction:in', `topic:${queueName}`, 'type:bullmq']
|
|
56
59
|
this.tracer.setCheckpoint(edgeTags, span, payloadSize)
|
|
57
60
|
}
|
|
61
|
+
|
|
62
|
+
_extractDatadog (job) {
|
|
63
|
+
const metadataStr = job?.opts?.telemetry?.metadata
|
|
64
|
+
if (!metadataStr) return
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const metadata = JSON.parse(metadataStr)
|
|
68
|
+
const ddCarrier = metadata._datadog
|
|
69
|
+
if (!ddCarrier) return
|
|
70
|
+
|
|
71
|
+
// Clean up only our _datadog key, preserve other metadata
|
|
72
|
+
delete metadata._datadog
|
|
73
|
+
job.opts.telemetry.metadata = JSON.stringify(metadata)
|
|
74
|
+
|
|
75
|
+
return ddCarrier
|
|
76
|
+
} catch {
|
|
77
|
+
// Ignore malformed metadata
|
|
78
|
+
}
|
|
79
|
+
}
|
|
58
80
|
}
|
|
59
81
|
|
|
60
82
|
module.exports = BullmqConsumerPlugin
|