dd-trace 4.18.0 → 5.6.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/CONTRIBUTING.md +98 -0
- package/LICENSE-3rdparty.csv +4 -5
- package/MIGRATING.md +15 -0
- package/README.md +20 -140
- package/ci/cypress/after-run.js +1 -0
- package/ci/cypress/after-spec.js +1 -0
- package/ci/init.js +1 -4
- package/ext/kinds.d.ts +1 -0
- package/ext/kinds.js +2 -1
- package/ext/tags.d.ts +2 -1
- package/ext/tags.js +6 -1
- package/index.d.ts +1523 -1460
- package/package.json +19 -19
- package/packages/datadog-core/src/storage/async_resource.js +1 -1
- package/packages/datadog-core/src/utils/src/get.js +11 -0
- package/packages/datadog-core/src/utils/src/has.js +14 -0
- package/packages/datadog-core/src/utils/src/kebabcase.js +16 -0
- package/packages/datadog-core/src/utils/src/pick.js +11 -0
- package/packages/datadog-core/src/utils/src/set.js +16 -0
- package/packages/datadog-core/src/utils/src/uniq.js +5 -0
- package/packages/datadog-esbuild/index.js +1 -20
- package/packages/datadog-instrumentations/src/aerospike.js +47 -0
- package/packages/datadog-instrumentations/src/amqplib.js +2 -2
- package/packages/datadog-instrumentations/src/apollo-server-core.js +41 -0
- package/packages/datadog-instrumentations/src/apollo-server.js +83 -0
- package/packages/datadog-instrumentations/src/child_process.js +150 -0
- package/packages/datadog-instrumentations/src/couchbase.js +5 -4
- package/packages/datadog-instrumentations/src/crypto.js +2 -1
- package/packages/datadog-instrumentations/src/cucumber.js +163 -46
- package/packages/datadog-instrumentations/src/dns.js +2 -1
- package/packages/datadog-instrumentations/src/express.js +20 -0
- package/packages/datadog-instrumentations/src/graphql.js +18 -4
- package/packages/datadog-instrumentations/src/grpc/client.js +56 -36
- package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -3
- package/packages/datadog-instrumentations/src/helpers/instrument.js +9 -4
- package/packages/datadog-instrumentations/src/helpers/register.js +19 -3
- package/packages/datadog-instrumentations/src/http/client.js +12 -2
- package/packages/datadog-instrumentations/src/http/server.js +7 -4
- package/packages/datadog-instrumentations/src/http2/client.js +3 -1
- package/packages/datadog-instrumentations/src/http2/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +239 -52
- package/packages/datadog-instrumentations/src/kafkajs.js +27 -0
- package/packages/datadog-instrumentations/src/mocha.js +154 -18
- package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
- package/packages/datadog-instrumentations/src/mongoose.js +23 -10
- package/packages/datadog-instrumentations/src/mquery.js +65 -0
- package/packages/datadog-instrumentations/src/net.js +10 -2
- package/packages/datadog-instrumentations/src/next.js +35 -9
- package/packages/datadog-instrumentations/src/playwright.js +110 -16
- package/packages/datadog-instrumentations/src/restify.js +14 -1
- package/packages/datadog-instrumentations/src/rhea.js +15 -9
- package/packages/datadog-plugin-aerospike/src/index.js +113 -0
- package/packages/datadog-plugin-amqplib/src/consumer.js +14 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +13 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +163 -27
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +46 -8
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +129 -22
- package/packages/datadog-plugin-child_process/src/index.js +91 -0
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +125 -0
- package/packages/datadog-plugin-cucumber/src/index.js +70 -13
- package/packages/datadog-plugin-cypress/src/after-run.js +3 -0
- package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +625 -0
- package/packages/datadog-plugin-cypress/src/plugin.js +6 -454
- package/packages/datadog-plugin-cypress/src/support.js +50 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -0
- package/packages/datadog-plugin-graphql/src/index.js +1 -6
- package/packages/datadog-plugin-graphql/src/resolve.js +28 -18
- package/packages/datadog-plugin-grpc/src/client.js +16 -2
- package/packages/datadog-plugin-grpc/src/util.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +19 -2
- package/packages/datadog-plugin-jest/src/index.js +118 -12
- package/packages/datadog-plugin-jest/src/util.js +38 -16
- package/packages/datadog-plugin-kafkajs/src/consumer.js +76 -6
- package/packages/datadog-plugin-kafkajs/src/producer.js +64 -8
- package/packages/datadog-plugin-mocha/src/index.js +87 -17
- package/packages/datadog-plugin-next/src/index.js +40 -14
- package/packages/datadog-plugin-playwright/src/index.js +71 -8
- package/packages/datadog-plugin-rhea/src/consumer.js +16 -1
- package/packages/datadog-plugin-rhea/src/producer.js +10 -0
- package/packages/dd-trace/src/appsec/activation.js +29 -0
- package/packages/dd-trace/src/appsec/addresses.js +5 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +61 -0
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -1
- package/packages/dd-trace/src/appsec/blocking.js +95 -43
- package/packages/dd-trace/src/appsec/channels.js +7 -3
- package/packages/dd-trace/src/appsec/graphql.js +146 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +105 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +22 -17
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +7 -28
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +10 -6
- package/packages/dd-trace/src/appsec/iast/analyzers/weak-randomness-analyzer.js +19 -0
- package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +90 -0
- package/packages/dd-trace/src/appsec/iast/context/kafka-ctx-plugin.js +14 -0
- package/packages/dd-trace/src/appsec/iast/iast-log.js +1 -1
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +13 -2
- package/packages/dd-trace/src/appsec/iast/index.js +15 -5
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
- package/packages/dd-trace/src/appsec/iast/path-line.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +2 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +10 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +53 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +10 -46
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +13 -9
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +47 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +19 -6
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +3 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +41 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/constants.js +7 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +12 -19
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +20 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/json-sensitive-analyzer.js +6 -10
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +18 -25
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +79 -85
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +27 -36
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +14 -11
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +2 -0
- package/packages/dd-trace/src/appsec/index.js +49 -33
- package/packages/dd-trace/src/appsec/recommended.json +1763 -106
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +7 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +42 -16
- package/packages/dd-trace/src/appsec/remote_config/manager.js +9 -8
- package/packages/dd-trace/src/appsec/reporter.js +51 -34
- package/packages/dd-trace/src/appsec/rule_manager.js +11 -8
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +28 -13
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +0 -1
- package/packages/dd-trace/src/ci-visibility/{intelligent-test-runner/get-itr-configuration.js → early-flake-detection/get-known-tests.js} +17 -22
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +25 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +2 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +95 -37
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +134 -61
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +37 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +131 -0
- package/packages/dd-trace/src/ci-visibility/telemetry.js +130 -0
- package/packages/dd-trace/src/config.js +561 -470
- package/packages/dd-trace/src/data_streams_context.js +1 -1
- package/packages/dd-trace/src/datastreams/pathway.js +58 -1
- package/packages/dd-trace/src/datastreams/processor.js +196 -27
- package/packages/dd-trace/src/datastreams/writer.js +11 -5
- package/packages/dd-trace/src/dogstatsd.js +3 -5
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +44 -6
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +14 -0
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +4 -0
- package/packages/dd-trace/src/exporters/common/form-data.js +4 -0
- package/packages/dd-trace/src/exporters/common/request.js +21 -3
- package/packages/dd-trace/src/format.js +30 -2
- package/packages/dd-trace/src/id.js +12 -0
- package/packages/dd-trace/src/iitm.js +1 -1
- package/packages/dd-trace/src/log/channels.js +1 -1
- package/packages/dd-trace/src/noop/proxy.js +4 -0
- package/packages/dd-trace/src/noop/span.js +1 -0
- package/packages/dd-trace/src/opentelemetry/span.js +104 -4
- package/packages/dd-trace/src/opentelemetry/tracer.js +9 -10
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +16 -7
- package/packages/dd-trace/src/opentracing/span.js +48 -4
- package/packages/dd-trace/src/opentracing/span_context.js +15 -6
- package/packages/dd-trace/src/opentracing/tracer.js +4 -3
- package/packages/dd-trace/src/plugin_manager.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +78 -19
- package/packages/dd-trace/src/plugins/database.js +1 -1
- package/packages/dd-trace/src/plugins/index.js +7 -0
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +6 -19
- package/packages/dd-trace/src/plugins/util/git.js +104 -22
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +7 -6
- package/packages/dd-trace/src/plugins/util/test.js +60 -10
- package/packages/dd-trace/src/plugins/util/url.js +26 -0
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +4 -16
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/priority_sampler.js +30 -38
- package/packages/dd-trace/src/profiler.js +5 -3
- package/packages/dd-trace/src/profiling/config.js +77 -24
- package/packages/dd-trace/src/profiling/exporters/agent.js +77 -31
- package/packages/dd-trace/src/profiling/exporters/file.js +2 -1
- package/packages/dd-trace/src/profiling/profiler.js +33 -22
- package/packages/dd-trace/src/profiling/profilers/events.js +270 -0
- package/packages/dd-trace/src/profiling/profilers/shared.js +45 -0
- package/packages/dd-trace/src/profiling/profilers/space.js +18 -2
- package/packages/dd-trace/src/profiling/profilers/wall.js +146 -70
- package/packages/dd-trace/src/proxy.js +56 -24
- package/packages/dd-trace/src/ritm.js +1 -1
- package/packages/dd-trace/src/sampling_rule.js +130 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/span_processor.js +9 -1
- package/packages/dd-trace/src/span_sampler.js +6 -64
- package/packages/dd-trace/src/spanleak.js +98 -0
- package/packages/dd-trace/src/startup-log.js +7 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +56 -10
- package/packages/dd-trace/src/telemetry/index.js +182 -53
- package/packages/dd-trace/src/telemetry/logs/index.js +2 -2
- package/packages/dd-trace/src/telemetry/send-data.js +65 -7
- package/packages/dd-trace/src/tracer.js +12 -5
- package/register.js +4 -0
- package/scripts/install_plugin_modules.js +11 -3
- package/scripts/st.js +105 -0
- package/packages/datadog-instrumentations/src/child-process.js +0 -30
- package/packages/dd-trace/src/plugins/util/exec.js +0 -13
- package/packages/diagnostics_channel/index.js +0 -3
- package/packages/diagnostics_channel/src/index.js +0 -121
|
@@ -8,13 +8,31 @@ const {
|
|
|
8
8
|
const shimmer = require('../../datadog-shimmer')
|
|
9
9
|
|
|
10
10
|
const producerStartCh = channel('apm:kafkajs:produce:start')
|
|
11
|
+
const producerCommitCh = channel('apm:kafkajs:produce:commit')
|
|
11
12
|
const producerFinishCh = channel('apm:kafkajs:produce:finish')
|
|
12
13
|
const producerErrorCh = channel('apm:kafkajs:produce:error')
|
|
13
14
|
|
|
14
15
|
const consumerStartCh = channel('apm:kafkajs:consume:start')
|
|
16
|
+
const consumerCommitCh = channel('apm:kafkajs:consume:commit')
|
|
15
17
|
const consumerFinishCh = channel('apm:kafkajs:consume:finish')
|
|
16
18
|
const consumerErrorCh = channel('apm:kafkajs:consume:error')
|
|
17
19
|
|
|
20
|
+
function commitsFromEvent (event) {
|
|
21
|
+
const { payload: { groupId, topics } } = event
|
|
22
|
+
const commitList = []
|
|
23
|
+
for (const { topic, partitions } of topics) {
|
|
24
|
+
for (const { partition, offset } of partitions) {
|
|
25
|
+
commitList.push({
|
|
26
|
+
groupId,
|
|
27
|
+
partition,
|
|
28
|
+
offset,
|
|
29
|
+
topic
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
consumerCommitCh.publish(commitList)
|
|
34
|
+
}
|
|
35
|
+
|
|
18
36
|
addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKafka) => {
|
|
19
37
|
class Kafka extends BaseKafka {
|
|
20
38
|
constructor (options) {
|
|
@@ -58,6 +76,12 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
58
76
|
})
|
|
59
77
|
)
|
|
60
78
|
|
|
79
|
+
result.then(res => {
|
|
80
|
+
if (producerCommitCh.hasSubscribers) {
|
|
81
|
+
producerCommitCh.publish(res)
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
61
85
|
return result
|
|
62
86
|
} catch (e) {
|
|
63
87
|
producerErrorCh.publish(e)
|
|
@@ -75,6 +99,9 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
75
99
|
}
|
|
76
100
|
|
|
77
101
|
const consumer = createConsumer.apply(this, arguments)
|
|
102
|
+
|
|
103
|
+
consumer.on(consumer.events.COMMIT_OFFSETS, commitsFromEvent)
|
|
104
|
+
|
|
78
105
|
const run = consumer.run
|
|
79
106
|
|
|
80
107
|
const groupId = arguments[0].groupId
|
|
@@ -11,7 +11,9 @@ const {
|
|
|
11
11
|
mergeCoverage,
|
|
12
12
|
getTestSuitePath,
|
|
13
13
|
fromCoverageMapToCoverage,
|
|
14
|
-
getCallSites
|
|
14
|
+
getCallSites,
|
|
15
|
+
addEfdStringToTestName,
|
|
16
|
+
removeEfdStringFromTestName
|
|
15
17
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
16
18
|
|
|
17
19
|
const testStartCh = channel('ci:mocha:test:start')
|
|
@@ -20,7 +22,8 @@ const skipCh = channel('ci:mocha:test:skip')
|
|
|
20
22
|
const testFinishCh = channel('ci:mocha:test:finish')
|
|
21
23
|
const parameterizedTestCh = channel('ci:mocha:test:parameterize')
|
|
22
24
|
|
|
23
|
-
const
|
|
25
|
+
const libraryConfigurationCh = channel('ci:mocha:library-configuration')
|
|
26
|
+
const knownTestsCh = channel('ci:mocha:known-tests')
|
|
24
27
|
const skippableSuitesCh = channel('ci:mocha:test-suite:skippable')
|
|
25
28
|
|
|
26
29
|
const testSessionStartCh = channel('ci:mocha:session:start')
|
|
@@ -40,6 +43,7 @@ const testToAr = new WeakMap()
|
|
|
40
43
|
const originalFns = new WeakMap()
|
|
41
44
|
const testFileToSuiteAr = new Map()
|
|
42
45
|
const testToStartLine = new WeakMap()
|
|
46
|
+
const newTests = {}
|
|
43
47
|
|
|
44
48
|
// `isWorker` is true if it's a Mocha worker
|
|
45
49
|
let isWorker = false
|
|
@@ -53,6 +57,11 @@ let isSuitesSkipped = false
|
|
|
53
57
|
let skippedSuites = []
|
|
54
58
|
const unskippableSuites = []
|
|
55
59
|
let isForcedToRun = false
|
|
60
|
+
let itrCorrelationId = ''
|
|
61
|
+
let isEarlyFlakeDetectionEnabled = false
|
|
62
|
+
let earlyFlakeDetectionNumRetries = 0
|
|
63
|
+
let isSuitesSkippingEnabled = false
|
|
64
|
+
let knownTests = []
|
|
56
65
|
|
|
57
66
|
function getSuitesByTestFile (root) {
|
|
58
67
|
const suitesByTestFile = {}
|
|
@@ -92,6 +101,29 @@ function isRetry (test) {
|
|
|
92
101
|
return test._currentRetry !== undefined && test._currentRetry !== 0
|
|
93
102
|
}
|
|
94
103
|
|
|
104
|
+
function getTestFullName (test) {
|
|
105
|
+
return `mocha.${getTestSuitePath(test.file, process.cwd())}.${removeEfdStringFromTestName(test.fullTitle())}`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function isNewTest (test) {
|
|
109
|
+
const testSuite = getTestSuitePath(test.file, process.cwd())
|
|
110
|
+
const testName = removeEfdStringFromTestName(test.fullTitle())
|
|
111
|
+
const testsForSuite = knownTests.mocha?.[testSuite] || []
|
|
112
|
+
return !testsForSuite.includes(testName)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function retryTest (test) {
|
|
116
|
+
const originalTestName = test.title
|
|
117
|
+
const suite = test.parent
|
|
118
|
+
for (let retryIndex = 0; retryIndex < earlyFlakeDetectionNumRetries; retryIndex++) {
|
|
119
|
+
const clonedTest = test.clone()
|
|
120
|
+
clonedTest.title = addEfdStringToTestName(originalTestName, retryIndex + 1)
|
|
121
|
+
suite.addTest(clonedTest)
|
|
122
|
+
clonedTest._ddIsNew = true
|
|
123
|
+
clonedTest._ddIsEfdRetry = true
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
95
127
|
function getTestAsyncResource (test) {
|
|
96
128
|
if (!test.fn) {
|
|
97
129
|
return testToAr.get(test)
|
|
@@ -122,6 +154,19 @@ function mochaHook (Runner) {
|
|
|
122
154
|
|
|
123
155
|
patched.add(Runner)
|
|
124
156
|
|
|
157
|
+
shimmer.wrap(Runner.prototype, 'runTests', runTests => function (suite, fn) {
|
|
158
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
159
|
+
// by the time we reach `this.on('test')`, it is too late. We need to add retries here
|
|
160
|
+
suite.tests.forEach(test => {
|
|
161
|
+
if (!test.isPending() && isNewTest(test)) {
|
|
162
|
+
test._ddIsNew = true
|
|
163
|
+
retryTest(test)
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
return runTests.apply(this, arguments)
|
|
168
|
+
})
|
|
169
|
+
|
|
125
170
|
shimmer.wrap(Runner.prototype, 'run', run => function () {
|
|
126
171
|
if (!testStartCh.hasSubscribers || isWorker) {
|
|
127
172
|
return run.apply(this, arguments)
|
|
@@ -143,6 +188,24 @@ function mochaHook (Runner) {
|
|
|
143
188
|
status = 'fail'
|
|
144
189
|
}
|
|
145
190
|
|
|
191
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
192
|
+
/**
|
|
193
|
+
* If Early Flake Detection (EFD) is enabled the logic is as follows:
|
|
194
|
+
* - If all attempts for a test are failing, the test has failed and we will let the test process fail.
|
|
195
|
+
* - If just a single attempt passes, we will prevent the test process from failing.
|
|
196
|
+
* The rationale behind is the following: you may still be able to block your CI pipeline by gating
|
|
197
|
+
* on flakiness (the test will be considered flaky), but you may choose to unblock the pipeline too.
|
|
198
|
+
*/
|
|
199
|
+
for (const tests of Object.values(newTests)) {
|
|
200
|
+
const failingNewTests = tests.filter(test => test.isFailed())
|
|
201
|
+
const areAllNewTestsFailing = failingNewTests.length === tests.length
|
|
202
|
+
if (failingNewTests.length && !areAllNewTestsFailing) {
|
|
203
|
+
this.stats.failures -= failingNewTests.length
|
|
204
|
+
this.failures -= failingNewTests.length
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
146
209
|
if (status === 'fail') {
|
|
147
210
|
error = new Error(`Failed tests: ${this.failures}.`)
|
|
148
211
|
}
|
|
@@ -167,7 +230,8 @@ function mochaHook (Runner) {
|
|
|
167
230
|
numSkippedSuites: skippedSuites.length,
|
|
168
231
|
hasForcedToRunSuites: isForcedToRun,
|
|
169
232
|
hasUnskippableSuites: !!unskippableSuites.length,
|
|
170
|
-
error
|
|
233
|
+
error,
|
|
234
|
+
isEarlyFlakeDetectionEnabled
|
|
171
235
|
})
|
|
172
236
|
}))
|
|
173
237
|
|
|
@@ -191,7 +255,12 @@ function mochaHook (Runner) {
|
|
|
191
255
|
const isUnskippable = unskippableSuites.includes(suite.file)
|
|
192
256
|
isForcedToRun = isUnskippable && suitesToSkip.includes(getTestSuitePath(suite.file, process.cwd()))
|
|
193
257
|
asyncResource.runInAsyncScope(() => {
|
|
194
|
-
testSuiteStartCh.publish({
|
|
258
|
+
testSuiteStartCh.publish({
|
|
259
|
+
testSuite: suite.file,
|
|
260
|
+
isUnskippable,
|
|
261
|
+
isForcedToRun,
|
|
262
|
+
itrCorrelationId
|
|
263
|
+
})
|
|
195
264
|
})
|
|
196
265
|
}
|
|
197
266
|
})
|
|
@@ -247,8 +316,35 @@ function mochaHook (Runner) {
|
|
|
247
316
|
const testStartLine = testToStartLine.get(test)
|
|
248
317
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
249
318
|
testToAr.set(test.fn, asyncResource)
|
|
319
|
+
|
|
320
|
+
const {
|
|
321
|
+
file: testSuiteAbsolutePath,
|
|
322
|
+
title,
|
|
323
|
+
_ddIsNew: isNew,
|
|
324
|
+
_ddIsEfdRetry: isEfdRetry
|
|
325
|
+
} = test
|
|
326
|
+
|
|
327
|
+
const testInfo = {
|
|
328
|
+
testName: test.fullTitle(),
|
|
329
|
+
testSuiteAbsolutePath,
|
|
330
|
+
title,
|
|
331
|
+
isNew,
|
|
332
|
+
isEfdRetry,
|
|
333
|
+
testStartLine
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// We want to store the result of the new tests
|
|
337
|
+
if (isNew) {
|
|
338
|
+
const testFullName = getTestFullName(test)
|
|
339
|
+
if (newTests[testFullName]) {
|
|
340
|
+
newTests[testFullName].push(test)
|
|
341
|
+
} else {
|
|
342
|
+
newTests[testFullName] = [test]
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
250
346
|
asyncResource.runInAsyncScope(() => {
|
|
251
|
-
testStartCh.publish(
|
|
347
|
+
testStartCh.publish(testInfo)
|
|
252
348
|
})
|
|
253
349
|
})
|
|
254
350
|
|
|
@@ -317,10 +413,23 @@ function mochaHook (Runner) {
|
|
|
317
413
|
})
|
|
318
414
|
|
|
319
415
|
this.on('pending', (test) => {
|
|
416
|
+
const testStartLine = testToStartLine.get(test)
|
|
417
|
+
const {
|
|
418
|
+
file: testSuiteAbsolutePath,
|
|
419
|
+
title
|
|
420
|
+
} = test
|
|
421
|
+
|
|
422
|
+
const testInfo = {
|
|
423
|
+
testName: test.fullTitle(),
|
|
424
|
+
testSuiteAbsolutePath,
|
|
425
|
+
title,
|
|
426
|
+
testStartLine
|
|
427
|
+
}
|
|
428
|
+
|
|
320
429
|
const asyncResource = getTestAsyncResource(test)
|
|
321
430
|
if (asyncResource) {
|
|
322
431
|
asyncResource.runInAsyncScope(() => {
|
|
323
|
-
skipCh.publish(
|
|
432
|
+
skipCh.publish(testInfo)
|
|
324
433
|
})
|
|
325
434
|
} else {
|
|
326
435
|
// if there is no async resource, the test has been skipped through `test.skip`
|
|
@@ -332,7 +441,7 @@ function mochaHook (Runner) {
|
|
|
332
441
|
testToAr.set(test, skippedTestAsyncResource)
|
|
333
442
|
}
|
|
334
443
|
skippedTestAsyncResource.runInAsyncScope(() => {
|
|
335
|
-
skipCh.publish(
|
|
444
|
+
skipCh.publish(testInfo)
|
|
336
445
|
})
|
|
337
446
|
}
|
|
338
447
|
})
|
|
@@ -352,8 +461,8 @@ function mochaEachHook (mochaEach) {
|
|
|
352
461
|
const [params] = arguments
|
|
353
462
|
const { it, ...rest } = mochaEach.apply(this, arguments)
|
|
354
463
|
return {
|
|
355
|
-
it: function (
|
|
356
|
-
parameterizedTestCh.publish({
|
|
464
|
+
it: function (title) {
|
|
465
|
+
parameterizedTestCh.publish({ title, params })
|
|
357
466
|
it.apply(this, arguments)
|
|
358
467
|
},
|
|
359
468
|
...rest
|
|
@@ -378,7 +487,7 @@ addHook({
|
|
|
378
487
|
return run.apply(this, arguments)
|
|
379
488
|
}
|
|
380
489
|
|
|
381
|
-
if (!
|
|
490
|
+
if (!libraryConfigurationCh.hasSubscribers || this.isWorker) {
|
|
382
491
|
if (this.isWorker) {
|
|
383
492
|
isWorker = true
|
|
384
493
|
}
|
|
@@ -395,11 +504,12 @@ addHook({
|
|
|
395
504
|
}
|
|
396
505
|
})
|
|
397
506
|
|
|
398
|
-
const onReceivedSkippableSuites = ({ err, skippableSuites }) => {
|
|
507
|
+
const onReceivedSkippableSuites = ({ err, skippableSuites, itrCorrelationId: responseItrCorrelationId }) => {
|
|
399
508
|
if (err) {
|
|
400
509
|
suitesToSkip = []
|
|
401
510
|
} else {
|
|
402
511
|
suitesToSkip = skippableSuites
|
|
512
|
+
itrCorrelationId = responseItrCorrelationId
|
|
403
513
|
}
|
|
404
514
|
// We remove the suites that we skip through ITR
|
|
405
515
|
const filteredSuites = getFilteredSuites(runner.suite.suites)
|
|
@@ -418,21 +528,47 @@ addHook({
|
|
|
418
528
|
global.run()
|
|
419
529
|
}
|
|
420
530
|
|
|
421
|
-
const
|
|
531
|
+
const onReceivedKnownTests = ({ err, knownTests: receivedKnownTests }) => {
|
|
422
532
|
if (err) {
|
|
423
|
-
|
|
533
|
+
knownTests = []
|
|
534
|
+
isEarlyFlakeDetectionEnabled = false
|
|
535
|
+
} else {
|
|
536
|
+
knownTests = receivedKnownTests
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if (isSuitesSkippingEnabled) {
|
|
540
|
+
skippableSuitesCh.publish({
|
|
541
|
+
onDone: mochaRunAsyncResource.bind(onReceivedSkippableSuites)
|
|
542
|
+
})
|
|
543
|
+
} else {
|
|
544
|
+
global.run()
|
|
424
545
|
}
|
|
425
|
-
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const onReceivedConfiguration = ({ err, libraryConfig }) => {
|
|
549
|
+
if (err || !skippableSuitesCh.hasSubscribers || !knownTestsCh.hasSubscribers) {
|
|
426
550
|
return global.run()
|
|
427
551
|
}
|
|
428
552
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
553
|
+
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
554
|
+
isSuitesSkippingEnabled = libraryConfig.isSuitesSkippingEnabled
|
|
555
|
+
earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
556
|
+
|
|
557
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
558
|
+
knownTestsCh.publish({
|
|
559
|
+
onDone: mochaRunAsyncResource.bind(onReceivedKnownTests)
|
|
560
|
+
})
|
|
561
|
+
} else if (isSuitesSkippingEnabled) {
|
|
562
|
+
skippableSuitesCh.publish({
|
|
563
|
+
onDone: mochaRunAsyncResource.bind(onReceivedSkippableSuites)
|
|
564
|
+
})
|
|
565
|
+
} else {
|
|
566
|
+
global.run()
|
|
567
|
+
}
|
|
432
568
|
}
|
|
433
569
|
|
|
434
570
|
mochaRunAsyncResource.runInAsyncScope(() => {
|
|
435
|
-
|
|
571
|
+
libraryConfigurationCh.publish({
|
|
436
572
|
onDone: mochaRunAsyncResource.bind(onReceivedConfiguration)
|
|
437
573
|
})
|
|
438
574
|
})
|
|
@@ -32,12 +32,18 @@ addHook({ name: 'mongodb', versions: ['>=4 <4.6.0'], file: 'lib/cmap/connection.
|
|
|
32
32
|
return Connection
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
-
addHook({ name: 'mongodb', versions: ['>=4.6.0'], file: 'lib/cmap/connection.js' }, Connection => {
|
|
35
|
+
addHook({ name: 'mongodb', versions: ['>=4.6.0 <6.4.0'], file: 'lib/cmap/connection.js' }, Connection => {
|
|
36
36
|
const proto = Connection.Connection.prototype
|
|
37
37
|
shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command'))
|
|
38
38
|
return Connection
|
|
39
39
|
})
|
|
40
40
|
|
|
41
|
+
addHook({ name: 'mongodb', versions: ['>=6.4.0'], file: 'lib/cmap/connection.js' }, Connection => {
|
|
42
|
+
const proto = Connection.Connection.prototype
|
|
43
|
+
shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command', undefined, instrumentPromise))
|
|
44
|
+
return Connection
|
|
45
|
+
})
|
|
46
|
+
|
|
41
47
|
addHook({ name: 'mongodb', versions: ['>=3.3 <4'], file: 'lib/core/wireprotocol/index.js' }, wp => wrapWp(wp))
|
|
42
48
|
|
|
43
49
|
addHook({ name: 'mongodb-core', versions: ['>=3.2'], file: 'lib/wireprotocol/index.js' }, wp => wrapWp(wp))
|
|
@@ -89,7 +95,7 @@ function wrapUnifiedCommand (command, operation, name) {
|
|
|
89
95
|
return shimmer.wrap(command, wrapped)
|
|
90
96
|
}
|
|
91
97
|
|
|
92
|
-
function wrapConnectionCommand (command, operation, name) {
|
|
98
|
+
function wrapConnectionCommand (command, operation, name, instrumentFn = instrument) {
|
|
93
99
|
const wrapped = function (ns, ops) {
|
|
94
100
|
if (!startCh.hasSubscribers) {
|
|
95
101
|
return command.apply(this, arguments)
|
|
@@ -101,7 +107,7 @@ function wrapConnectionCommand (command, operation, name) {
|
|
|
101
107
|
const topology = { s: { options } }
|
|
102
108
|
|
|
103
109
|
ns = `${ns.db}.${ns.collection}`
|
|
104
|
-
return
|
|
110
|
+
return instrumentFn(operation, command, this, arguments, topology, ns, ops, { name })
|
|
105
111
|
}
|
|
106
112
|
return shimmer.wrap(command, wrapped)
|
|
107
113
|
}
|
|
@@ -179,3 +185,28 @@ function instrument (operation, command, ctx, args, server, ns, ops, options = {
|
|
|
179
185
|
}
|
|
180
186
|
})
|
|
181
187
|
}
|
|
188
|
+
|
|
189
|
+
function instrumentPromise (operation, command, ctx, args, server, ns, ops, options = {}) {
|
|
190
|
+
const name = options.name || (ops && Object.keys(ops)[0])
|
|
191
|
+
|
|
192
|
+
const serverInfo = server && server.s && server.s.options
|
|
193
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
194
|
+
|
|
195
|
+
return asyncResource.runInAsyncScope(() => {
|
|
196
|
+
startCh.publish({ ns, ops, options: serverInfo, name })
|
|
197
|
+
|
|
198
|
+
const promise = command.apply(ctx, args)
|
|
199
|
+
|
|
200
|
+
promise.then(function (res) {
|
|
201
|
+
finishCh.publish()
|
|
202
|
+
return res
|
|
203
|
+
}, function (err) {
|
|
204
|
+
errorCh.publish(err)
|
|
205
|
+
finishCh.publish()
|
|
206
|
+
|
|
207
|
+
return Promise.reject(err)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
return promise
|
|
211
|
+
})
|
|
212
|
+
}
|
|
@@ -79,21 +79,26 @@ addHook({
|
|
|
79
79
|
})
|
|
80
80
|
|
|
81
81
|
let callbackWrapped = false
|
|
82
|
-
const lastArgumentIndex = arguments.length - 1
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
shimmer.wrap(arguments, lastArgumentIndex, originalCb => {
|
|
87
|
-
return function () {
|
|
88
|
-
finish()
|
|
83
|
+
const wrapCallbackIfExist = (args) => {
|
|
84
|
+
const lastArgumentIndex = args.length - 1
|
|
89
85
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
if (typeof args[lastArgumentIndex] === 'function') {
|
|
87
|
+
// is a callback, wrap it to execute finish()
|
|
88
|
+
shimmer.wrap(args, lastArgumentIndex, originalCb => {
|
|
89
|
+
return function () {
|
|
90
|
+
finish()
|
|
91
|
+
|
|
92
|
+
return originalCb.apply(this, arguments)
|
|
93
|
+
}
|
|
94
|
+
})
|
|
93
95
|
|
|
94
|
-
|
|
96
|
+
callbackWrapped = true
|
|
97
|
+
}
|
|
95
98
|
}
|
|
96
99
|
|
|
100
|
+
wrapCallbackIfExist(arguments)
|
|
101
|
+
|
|
97
102
|
return asyncResource.runInAsyncScope(() => {
|
|
98
103
|
startCh.publish({
|
|
99
104
|
filters,
|
|
@@ -106,8 +111,16 @@ addHook({
|
|
|
106
111
|
if (!callbackWrapped) {
|
|
107
112
|
shimmer.wrap(res, 'exec', originalExec => {
|
|
108
113
|
return function wrappedExec () {
|
|
114
|
+
if (!callbackWrapped) {
|
|
115
|
+
wrapCallbackIfExist(arguments)
|
|
116
|
+
}
|
|
117
|
+
|
|
109
118
|
const execResult = originalExec.apply(this, arguments)
|
|
110
119
|
|
|
120
|
+
if (callbackWrapped || typeof execResult?.then !== 'function') {
|
|
121
|
+
return execResult
|
|
122
|
+
}
|
|
123
|
+
|
|
111
124
|
// wrap them method, wrap resolve and reject methods
|
|
112
125
|
shimmer.wrap(execResult, 'then', originalThen => {
|
|
113
126
|
return function wrappedThen () {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const dc = require('dc-polyfill')
|
|
4
|
+
const {
|
|
5
|
+
channel,
|
|
6
|
+
addHook
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
const prepareCh = channel('datadog:mquery:filter:prepare')
|
|
11
|
+
const tracingCh = dc.tracingChannel('datadog:mquery:filter')
|
|
12
|
+
|
|
13
|
+
const methods = [
|
|
14
|
+
'find',
|
|
15
|
+
'findOne',
|
|
16
|
+
'findOneAndRemove',
|
|
17
|
+
'findOneAndDelete',
|
|
18
|
+
'count',
|
|
19
|
+
'distinct',
|
|
20
|
+
'where'
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
const methodsOptionalArgs = ['findOneAndUpdate']
|
|
24
|
+
|
|
25
|
+
function getFilters (args, methodName) {
|
|
26
|
+
const [arg0, arg1] = args
|
|
27
|
+
|
|
28
|
+
const filters = arg0 && typeof arg0 === 'object' ? [arg0] : []
|
|
29
|
+
|
|
30
|
+
if (arg1 && typeof arg1 === 'object' && methodsOptionalArgs.includes(methodName)) {
|
|
31
|
+
filters.push(arg1)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return filters
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
addHook({
|
|
38
|
+
name: 'mquery',
|
|
39
|
+
versions: ['>=5.0.0']
|
|
40
|
+
}, Query => {
|
|
41
|
+
[...methods, ...methodsOptionalArgs].forEach(methodName => {
|
|
42
|
+
if (!(methodName in Query.prototype)) return
|
|
43
|
+
|
|
44
|
+
shimmer.wrap(Query.prototype, methodName, method => {
|
|
45
|
+
return function () {
|
|
46
|
+
if (prepareCh.hasSubscribers) {
|
|
47
|
+
const filters = getFilters(arguments, methodName)
|
|
48
|
+
if (filters?.length) {
|
|
49
|
+
prepareCh.publish({ filters })
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return method.apply(this, arguments)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
shimmer.wrap(Query.prototype, 'exec', originalExec => {
|
|
59
|
+
return function wrappedExec () {
|
|
60
|
+
return tracingCh.tracePromise(originalExec, {}, this, arguments)
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
return Query
|
|
65
|
+
})
|
|
@@ -17,8 +17,16 @@ const errorTCPCh = channel('apm:net:tcp:error')
|
|
|
17
17
|
|
|
18
18
|
const connectionCh = channel(`apm:net:tcp:connection`)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const names = ['net', 'node:net']
|
|
21
|
+
|
|
22
|
+
addHook({ name: names }, (net, version, name) => {
|
|
23
|
+
// explicitly require dns so that net gets an instrumented instance
|
|
24
|
+
// so that we don't miss the dns calls
|
|
25
|
+
if (name === 'net') {
|
|
26
|
+
require('dns')
|
|
27
|
+
} else {
|
|
28
|
+
require('node:dns')
|
|
29
|
+
}
|
|
22
30
|
|
|
23
31
|
shimmer.wrap(net.Socket.prototype, 'connect', connect => function () {
|
|
24
32
|
if (!startICPCh.hasSubscribers || !startTCPCh.hasSubscribers) {
|
|
@@ -65,7 +65,7 @@ function wrapRenderToHTML (renderToHTML) {
|
|
|
65
65
|
|
|
66
66
|
function wrapRenderErrorToHTML (renderErrorToHTML) {
|
|
67
67
|
return function (err, req, res, pathname, query) {
|
|
68
|
-
return instrument(req, res, () => renderErrorToHTML.apply(this, arguments))
|
|
68
|
+
return instrument(req, res, err, () => renderErrorToHTML.apply(this, arguments))
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -76,8 +76,8 @@ function wrapRenderToResponse (renderToResponse) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
function wrapRenderErrorToResponse (renderErrorToResponse) {
|
|
79
|
-
return function (ctx) {
|
|
80
|
-
return instrument(ctx.req, ctx.res, () => renderErrorToResponse.apply(this, arguments))
|
|
79
|
+
return function (ctx, err) {
|
|
80
|
+
return instrument(ctx.req, ctx.res, err, () => renderErrorToResponse.apply(this, arguments))
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -111,13 +111,23 @@ function getPageFromPath (page, dynamicRoutes = []) {
|
|
|
111
111
|
return getPagePath(page)
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
function instrument (req, res, handler) {
|
|
114
|
+
function instrument (req, res, error, handler) {
|
|
115
|
+
if (typeof error === 'function') {
|
|
116
|
+
handler = error
|
|
117
|
+
error = null
|
|
118
|
+
}
|
|
119
|
+
|
|
115
120
|
req = req.originalRequest || req
|
|
116
121
|
res = res.originalResponse || res
|
|
117
122
|
|
|
118
123
|
// TODO support middleware properly in the future?
|
|
119
124
|
const isMiddleware = req.headers[MIDDLEWARE_HEADER]
|
|
120
|
-
if (isMiddleware || requests.has(req))
|
|
125
|
+
if (isMiddleware || requests.has(req)) {
|
|
126
|
+
if (error) {
|
|
127
|
+
errorChannel.publish({ error })
|
|
128
|
+
}
|
|
129
|
+
return handler()
|
|
130
|
+
}
|
|
121
131
|
|
|
122
132
|
requests.add(req)
|
|
123
133
|
|
|
@@ -144,7 +154,9 @@ function instrument (req, res, handler) {
|
|
|
144
154
|
function wrapServeStatic (serveStatic) {
|
|
145
155
|
return function (req, res, path) {
|
|
146
156
|
return instrument(req, res, () => {
|
|
147
|
-
if (pageLoadChannel.hasSubscribers && path)
|
|
157
|
+
if (pageLoadChannel.hasSubscribers && path) {
|
|
158
|
+
pageLoadChannel.publish({ page: path, isStatic: true })
|
|
159
|
+
}
|
|
148
160
|
|
|
149
161
|
return serveStatic.apply(this, arguments)
|
|
150
162
|
})
|
|
@@ -278,9 +290,23 @@ addHook({
|
|
|
278
290
|
shimmer.massWrap(request.NextRequest.prototype, ['text', 'json'], function (originalMethod) {
|
|
279
291
|
return async function wrappedJson () {
|
|
280
292
|
const body = await originalMethod.apply(this, arguments)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
293
|
+
|
|
294
|
+
bodyParsedChannel.publish({ body })
|
|
295
|
+
|
|
296
|
+
return body
|
|
297
|
+
}
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
shimmer.wrap(request.NextRequest.prototype, 'formData', function (originalFormData) {
|
|
301
|
+
return async function wrappedFormData () {
|
|
302
|
+
const body = await originalFormData.apply(this, arguments)
|
|
303
|
+
|
|
304
|
+
let normalizedBody = body
|
|
305
|
+
if (typeof body.entries === 'function') {
|
|
306
|
+
normalizedBody = Object.fromEntries(body.entries())
|
|
307
|
+
}
|
|
308
|
+
bodyParsedChannel.publish({ body: normalizedBody })
|
|
309
|
+
|
|
284
310
|
return body
|
|
285
311
|
}
|
|
286
312
|
})
|