dd-trace 5.8.0 → 5.10.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 -1
- package/ci/init.js +3 -3
- package/package.json +5 -6
- package/packages/datadog-esbuild/index.js +2 -2
- package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
- package/packages/datadog-instrumentations/src/apollo.js +5 -3
- package/packages/datadog-instrumentations/src/aws-sdk.js +4 -1
- package/packages/datadog-instrumentations/src/cassandra-driver.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +6 -2
- package/packages/datadog-instrumentations/src/fs.js +0 -1
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +56 -56
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
- package/packages/datadog-instrumentations/src/http/client.js +1 -0
- package/packages/datadog-instrumentations/src/jest.js +94 -15
- package/packages/datadog-instrumentations/src/kafkajs.js +6 -8
- package/packages/datadog-instrumentations/src/ldapjs.js +2 -1
- package/packages/datadog-instrumentations/src/mocha.js +1 -1
- package/packages/datadog-instrumentations/src/mongodb-core.js +3 -3
- package/packages/datadog-instrumentations/src/net.js +1 -1
- package/packages/datadog-instrumentations/src/oracledb.js +1 -1
- package/packages/datadog-instrumentations/src/passport-utils.js +1 -0
- package/packages/datadog-instrumentations/src/playwright.js +8 -2
- package/packages/datadog-instrumentations/src/rhea.js +5 -2
- package/packages/datadog-instrumentations/src/tedious.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/fetch.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/plan.js +0 -1
- package/packages/datadog-plugin-apollo/src/gateway/request.js +2 -17
- package/packages/datadog-plugin-apollo/src/gateway/validate.js +6 -2
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -3
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -2
- package/packages/datadog-plugin-child_process/src/index.js +1 -1
- package/packages/datadog-plugin-couchbase/src/index.js +2 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +1 -0
- package/packages/datadog-plugin-fetch/src/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
- package/packages/datadog-plugin-grpc/src/client.js +2 -2
- package/packages/datadog-plugin-grpc/src/server.js +2 -2
- package/packages/datadog-plugin-http/src/client.js +2 -2
- package/packages/datadog-plugin-http2/src/client.js +4 -3
- package/packages/datadog-plugin-jest/src/index.js +1 -0
- package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/index.js +4 -4
- package/packages/datadog-plugin-playwright/src/index.js +7 -2
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +1 -1
- package/packages/datadog-plugin-tedious/src/index.js +1 -1
- package/packages/dd-trace/src/appsec/blocking.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +17 -17
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +132 -132
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +6 -2
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +3 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +4 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +27 -18
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +7 -4
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +9 -3
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +1 -0
- package/packages/dd-trace/src/config.js +16 -14
- package/packages/dd-trace/src/datastreams/pathway.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +15 -15
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +2 -2
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +1 -1
- package/packages/dd-trace/src/exporters/common/request.js +1 -0
- package/packages/dd-trace/src/exporters/span-stats/writer.js +0 -1
- package/packages/dd-trace/src/external-logger/src/index.js +5 -5
- package/packages/dd-trace/src/opentelemetry/span.js +2 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -1
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/plugins/apollo.js +3 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +2 -1
- package/packages/dd-trace/src/plugins/composite.js +3 -4
- package/packages/dd-trace/src/plugins/database.js +1 -0
- package/packages/dd-trace/src/plugins/index.js +43 -43
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/git.js +33 -11
- package/packages/dd-trace/src/plugins/util/test.js +2 -1
- package/packages/dd-trace/src/plugins/util/web.js +4 -4
- package/packages/dd-trace/src/profiling/config.js +1 -1
- package/packages/dd-trace/src/profiling/loggers/console.js +1 -1
- package/packages/dd-trace/src/runtime_metrics.js +8 -5
- package/packages/dd-trace/src/serverless.js +3 -2
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +0 -1
- package/packages/dd-trace/src/span_processor.js +2 -2
- package/packages/dd-trace/src/span_stats.js +1 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +4 -5
- package/packages/dd-trace/src/telemetry/index.js +12 -13
- package/packages/dd-trace/src/telemetry/send-data.js +0 -1
- package/packages/dd-trace/src/util.js +7 -7
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -48,7 +48,6 @@ dev,eslint-config-standard,MIT,Copyright Feross Aboukhadijeh
|
|
|
48
48
|
dev,eslint-plugin-import,MIT,Copyright 2015 Ben Mosher
|
|
49
49
|
dev,eslint-plugin-mocha,MIT,Copyright 2014 Mathias Schreck
|
|
50
50
|
dev,eslint-plugin-n,MIT,Copyright 2015 Toru Nagashima
|
|
51
|
-
dev,eslint-plugin-node,MIT,Copyright 2015 Toru Nagashima
|
|
52
51
|
dev,eslint-plugin-promise,ISC,jden and other contributors
|
|
53
52
|
dev,eslint-plugin-standard,MIT,Copyright 2015 Jamund Ferguson
|
|
54
53
|
dev,express,MIT,Copyright 2009-2014 TJ Holowaychuk 2013-2014 Roman Shtylman 2014-2015 Douglas Christopher Wilson
|
package/ci/init.js
CHANGED
|
@@ -20,9 +20,9 @@ if (isAgentlessEnabled) {
|
|
|
20
20
|
exporter: 'datadog'
|
|
21
21
|
}
|
|
22
22
|
} else {
|
|
23
|
-
console.error(
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
console.error('DD_CIVISIBILITY_AGENTLESS_ENABLED is set, but neither ' +
|
|
24
|
+
'DD_API_KEY nor DATADOG_API_KEY are set in your environment, so ' +
|
|
25
|
+
'dd-trace will not be initialized.')
|
|
26
26
|
shouldInit = false
|
|
27
27
|
}
|
|
28
28
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -69,11 +69,11 @@
|
|
|
69
69
|
"node": ">=18"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@datadog/native-appsec": "7.1.
|
|
72
|
+
"@datadog/native-appsec": "7.1.1",
|
|
73
73
|
"@datadog/native-iast-rewriter": "2.3.0",
|
|
74
74
|
"@datadog/native-iast-taint-tracking": "1.7.0",
|
|
75
75
|
"@datadog/native-metrics": "^2.0.0",
|
|
76
|
-
"@datadog/pprof": "5.
|
|
76
|
+
"@datadog/pprof": "5.2.0",
|
|
77
77
|
"@datadog/sketches-js": "^2.1.0",
|
|
78
78
|
"@opentelemetry/api": "^1.0.0",
|
|
79
79
|
"@opentelemetry/core": "^1.14.0",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"node-abort-controller": "^3.1.1",
|
|
96
96
|
"opentracing": ">=0.12.1",
|
|
97
97
|
"path-to-regexp": "^0.1.2",
|
|
98
|
-
"pprof-format": "^2.0
|
|
98
|
+
"pprof-format": "^2.1.0",
|
|
99
99
|
"protobufjs": "^7.2.5",
|
|
100
100
|
"retry": "^0.13.1",
|
|
101
101
|
"semver": "^7.5.4",
|
|
@@ -116,11 +116,10 @@
|
|
|
116
116
|
"dotenv": "16.3.1",
|
|
117
117
|
"esbuild": "0.16.12",
|
|
118
118
|
"eslint": "^8.23.0",
|
|
119
|
-
"eslint-config-standard": "^
|
|
119
|
+
"eslint-config-standard": "^17.1.0",
|
|
120
120
|
"eslint-plugin-import": "^2.8.0",
|
|
121
121
|
"eslint-plugin-mocha": "^10.1.0",
|
|
122
122
|
"eslint-plugin-n": "^15.7.0",
|
|
123
|
-
"eslint-plugin-node": "^5.2.1",
|
|
124
123
|
"eslint-plugin-promise": "^3.6.0",
|
|
125
124
|
"eslint-plugin-standard": "^3.0.1",
|
|
126
125
|
"express": "^4.18.2",
|
|
@@ -89,7 +89,7 @@ module.exports.setup = function (build) {
|
|
|
89
89
|
|
|
90
90
|
let pathToPackageJson
|
|
91
91
|
try {
|
|
92
|
-
pathToPackageJson = require.resolve(`${extracted.pkg}/package.json`, { paths: [
|
|
92
|
+
pathToPackageJson = require.resolve(`${extracted.pkg}/package.json`, { paths: [args.resolveDir] })
|
|
93
93
|
} catch (err) {
|
|
94
94
|
if (err.code === 'MODULE_NOT_FOUND') {
|
|
95
95
|
if (!internal) {
|
|
@@ -173,7 +173,7 @@ function dotFriendlyResolve (path, directory) {
|
|
|
173
173
|
path = '../'
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
return require.resolve(path, { paths: [
|
|
176
|
+
return require.resolve(path, { paths: [directory] })
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
/**
|
|
@@ -14,14 +14,14 @@ const CHANNELS = {
|
|
|
14
14
|
'gateway.postprocessing': tracingChannel('apm:apollo:gateway:postprocessing')
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const executorCh = channel('apm:apollo:gateway:request:executor')
|
|
18
17
|
const generalErrorCh = channel('apm:apollo:gateway:general:error')
|
|
19
18
|
|
|
20
19
|
function wrapExecutor (executor) {
|
|
21
20
|
return function (...args) {
|
|
21
|
+
const channel = CHANNELS['gateway.request']
|
|
22
22
|
const ctx = { requestContext: args[0], gateway: this }
|
|
23
|
-
|
|
24
|
-
return
|
|
23
|
+
|
|
24
|
+
return channel.tracePromise(executor, ctx, this, ...args)
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -67,7 +67,9 @@ function wrapStartActiveSpan (startActiveSpan) {
|
|
|
67
67
|
}
|
|
68
68
|
break
|
|
69
69
|
}
|
|
70
|
+
// Patch `executor` instead so the requestContext can be captured.
|
|
70
71
|
case 'gateway.request':
|
|
72
|
+
break
|
|
71
73
|
case 'gateway.execute':
|
|
72
74
|
case 'gateway.postprocessing' :
|
|
73
75
|
case 'gateway.fetch': {
|
|
@@ -111,6 +111,7 @@ function wrapSmithySend (send) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function wrapCb (cb, serviceName, request, ar) {
|
|
114
|
+
// eslint-disable-next-line n/handle-callback-err
|
|
114
115
|
return function wrappedCb (err, response) {
|
|
115
116
|
const obj = { request, response }
|
|
116
117
|
return ar.runInAsyncScope(() => {
|
|
@@ -163,7 +164,9 @@ function getChannelSuffix (name) {
|
|
|
163
164
|
's3',
|
|
164
165
|
'sns',
|
|
165
166
|
'sqs'
|
|
166
|
-
].includes(name)
|
|
167
|
+
].includes(name)
|
|
168
|
+
? name
|
|
169
|
+
: 'default'
|
|
167
170
|
}
|
|
168
171
|
|
|
169
172
|
addHook({ name: '@smithy/smithy-client', versions: ['>=1.0.3'] }, smithy => {
|
|
@@ -10,7 +10,7 @@ const shimmer = require('../../datadog-shimmer')
|
|
|
10
10
|
const startCh = channel('apm:cassandra-driver:query:start')
|
|
11
11
|
const finishCh = channel('apm:cassandra-driver:query:finish')
|
|
12
12
|
const errorCh = channel('apm:cassandra-driver:query:error')
|
|
13
|
-
const connectCh = channel(
|
|
13
|
+
const connectCh = channel('apm:cassandra-driver:query:connect')
|
|
14
14
|
|
|
15
15
|
addHook({ name: 'cassandra-driver', versions: ['>=3.0.0'] }, cassandra => {
|
|
16
16
|
shimmer.wrap(cassandra.Client.prototype, 'batch', batch => function (queries, options, callback) {
|
|
@@ -132,7 +132,8 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
132
132
|
promise.finally(() => {
|
|
133
133
|
const result = this.getWorstStepResult()
|
|
134
134
|
const { status, skipReason, errorMessage } = isLatestVersion
|
|
135
|
-
? getStatusFromResultLatest(result)
|
|
135
|
+
? getStatusFromResultLatest(result)
|
|
136
|
+
: getStatusFromResult(result)
|
|
136
137
|
|
|
137
138
|
if (lastStatusByPickleId.has(this.pickle.id)) {
|
|
138
139
|
lastStatusByPickleId.get(this.pickle.id).push(status)
|
|
@@ -177,7 +178,8 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
177
178
|
|
|
178
179
|
promise.then((result) => {
|
|
179
180
|
const { status, skipReason, errorMessage } = isLatestVersion
|
|
180
|
-
? getStatusFromResultLatest(result)
|
|
181
|
+
? getStatusFromResultLatest(result)
|
|
182
|
+
: getStatusFromResult(result)
|
|
181
183
|
|
|
182
184
|
testFinishCh.publish({ isStep: true, status, skipReason, errorMessage })
|
|
183
185
|
})
|
|
@@ -290,6 +292,8 @@ function getWrappedStart (start, frameworkVersion) {
|
|
|
290
292
|
const knownTestsResponse = await knownTestsPromise
|
|
291
293
|
if (!knownTestsResponse.err) {
|
|
292
294
|
knownTests = knownTestsResponse.knownTests
|
|
295
|
+
} else {
|
|
296
|
+
isEarlyFlakeDetectionEnabled = false
|
|
293
297
|
}
|
|
294
298
|
}
|
|
295
299
|
|
|
@@ -11,7 +11,7 @@ const requestStartCh = channel('apm:google-cloud-pubsub:request:start')
|
|
|
11
11
|
const requestFinishCh = channel('apm:google-cloud-pubsub:request:finish')
|
|
12
12
|
const requestErrorCh = channel('apm:google-cloud-pubsub:request:error')
|
|
13
13
|
|
|
14
|
-
const receiveStartCh = channel(
|
|
14
|
+
const receiveStartCh = channel('apm:google-cloud-pubsub:receive:start')
|
|
15
15
|
const receiveFinishCh = channel('apm:google-cloud-pubsub:receive:finish')
|
|
16
16
|
const receiveErrorCh = channel('apm:google-cloud-pubsub:receive:error')
|
|
17
17
|
|
|
@@ -23,62 +23,62 @@ module.exports = {
|
|
|
23
23
|
'@opentelemetry/sdk-trace-node': () => require('../otel-sdk-trace'),
|
|
24
24
|
'@redis/client': () => require('../redis'),
|
|
25
25
|
'@smithy/smithy-client': () => require('../aws-sdk'),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
aerospike: () => require('../aerospike'),
|
|
27
|
+
amqp10: () => require('../amqp10'),
|
|
28
|
+
amqplib: () => require('../amqplib'),
|
|
29
29
|
'aws-sdk': () => require('../aws-sdk'),
|
|
30
|
-
|
|
30
|
+
bluebird: () => require('../bluebird'),
|
|
31
31
|
'body-parser': () => require('../body-parser'),
|
|
32
|
-
|
|
32
|
+
bunyan: () => require('../bunyan'),
|
|
33
33
|
'cassandra-driver': () => require('../cassandra-driver'),
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
child_process: () => require('../child_process'),
|
|
35
|
+
connect: () => require('../connect'),
|
|
36
|
+
cookie: () => require('../cookie'),
|
|
37
37
|
'cookie-parser': () => require('../cookie-parser'),
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
couchbase: () => require('../couchbase'),
|
|
39
|
+
crypto: () => require('../crypto'),
|
|
40
|
+
cypress: () => require('../cypress'),
|
|
41
|
+
dns: () => require('../dns'),
|
|
42
|
+
elasticsearch: () => require('../elasticsearch'),
|
|
43
|
+
express: () => require('../express'),
|
|
44
44
|
'express-mongo-sanitize': () => require('../express-mongo-sanitize'),
|
|
45
|
-
|
|
45
|
+
fastify: () => require('../fastify'),
|
|
46
46
|
'find-my-way': () => require('../find-my-way'),
|
|
47
|
-
|
|
47
|
+
fs: () => require('../fs'),
|
|
48
48
|
'generic-pool': () => require('../generic-pool'),
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
graphql: () => require('../graphql'),
|
|
50
|
+
grpc: () => require('../grpc'),
|
|
51
|
+
hapi: () => require('../hapi'),
|
|
52
|
+
http: () => require('../http'),
|
|
53
|
+
http2: () => require('../http2'),
|
|
54
|
+
https: () => require('../http'),
|
|
55
|
+
ioredis: () => require('../ioredis'),
|
|
56
56
|
'jest-circus': () => require('../jest'),
|
|
57
57
|
'jest-config': () => require('../jest'),
|
|
58
58
|
'jest-environment-node': () => require('../jest'),
|
|
59
59
|
'jest-environment-jsdom': () => require('../jest'),
|
|
60
60
|
'jest-jasmine2': () => require('../jest'),
|
|
61
61
|
'jest-worker': () => require('../jest'),
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
knex: () => require('../knex'),
|
|
63
|
+
koa: () => require('../koa'),
|
|
64
64
|
'koa-router': () => require('../koa'),
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
kafkajs: () => require('../kafkajs'),
|
|
66
|
+
ldapjs: () => require('../ldapjs'),
|
|
67
67
|
'limitd-client': () => require('../limitd-client'),
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
mariadb: () => require('../mariadb'),
|
|
69
|
+
memcached: () => require('../memcached'),
|
|
70
70
|
'microgateway-core': () => require('../microgateway-core'),
|
|
71
|
-
|
|
71
|
+
mocha: () => require('../mocha'),
|
|
72
72
|
'mocha-each': () => require('../mocha'),
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
moleculer: () => require('../moleculer'),
|
|
74
|
+
mongodb: () => require('../mongodb'),
|
|
75
75
|
'mongodb-core': () => require('../mongodb-core'),
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
mongoose: () => require('../mongoose'),
|
|
77
|
+
mquery: () => require('../mquery'),
|
|
78
|
+
mysql: () => require('../mysql'),
|
|
79
|
+
mysql2: () => require('../mysql2'),
|
|
80
|
+
net: () => require('../net'),
|
|
81
|
+
next: () => require('../next'),
|
|
82
82
|
'node:child_process': () => require('../child_process'),
|
|
83
83
|
'node:crypto': () => require('../crypto'),
|
|
84
84
|
'node:dns': () => require('../dns'),
|
|
@@ -86,26 +86,26 @@ module.exports = {
|
|
|
86
86
|
'node:http2': () => require('../http2'),
|
|
87
87
|
'node:https': () => require('../http'),
|
|
88
88
|
'node:net': () => require('../net'),
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
oracledb: () => require('../oracledb'),
|
|
90
|
+
openai: () => require('../openai'),
|
|
91
|
+
paperplane: () => require('../paperplane'),
|
|
92
92
|
'passport-http': () => require('../passport-http'),
|
|
93
93
|
'passport-local': () => require('../passport-local'),
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
pg: () => require('../pg'),
|
|
95
|
+
pino: () => require('../pino'),
|
|
96
96
|
'pino-pretty': () => require('../pino'),
|
|
97
|
-
|
|
97
|
+
playwright: () => require('../playwright'),
|
|
98
98
|
'promise-js': () => require('../promise-js'),
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
99
|
+
promise: () => require('../promise'),
|
|
100
|
+
q: () => require('../q'),
|
|
101
|
+
qs: () => require('../qs'),
|
|
102
|
+
redis: () => require('../redis'),
|
|
103
|
+
restify: () => require('../restify'),
|
|
104
|
+
rhea: () => require('../rhea'),
|
|
105
|
+
router: () => require('../router'),
|
|
106
|
+
sharedb: () => require('../sharedb'),
|
|
107
|
+
sequelize: () => require('../sequelize'),
|
|
108
|
+
tedious: () => require('../tedious'),
|
|
109
|
+
when: () => require('../when'),
|
|
110
|
+
winston: () => require('../winston')
|
|
111
111
|
}
|
|
@@ -56,13 +56,13 @@ if (semver.satisfies(process.versions.node, '>=17.8.0')) {
|
|
|
56
56
|
bound = this.runInAsyncScope.bind(this, fn, thisArg)
|
|
57
57
|
}
|
|
58
58
|
Object.defineProperties(bound, {
|
|
59
|
-
|
|
59
|
+
length: {
|
|
60
60
|
configurable: true,
|
|
61
61
|
enumerable: false,
|
|
62
62
|
value: fn.length,
|
|
63
63
|
writable: false
|
|
64
64
|
},
|
|
65
|
-
|
|
65
|
+
asyncResource: {
|
|
66
66
|
configurable: true,
|
|
67
67
|
enumerable: true,
|
|
68
68
|
value: this,
|
|
@@ -10,7 +10,7 @@ const {
|
|
|
10
10
|
getTestLineStart,
|
|
11
11
|
getTestSuitePath,
|
|
12
12
|
getTestParametersString,
|
|
13
|
-
|
|
13
|
+
addEfdStringToTestName,
|
|
14
14
|
removeEfdStringFromTestName
|
|
15
15
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
16
16
|
const {
|
|
@@ -44,11 +44,14 @@ const knownTestsCh = channel('ci:jest:known-tests')
|
|
|
44
44
|
|
|
45
45
|
const itrSkippedSuitesCh = channel('ci:jest:itr:skipped-suites')
|
|
46
46
|
|
|
47
|
+
// Message sent by jest's main process to workers to run a test suite (=test file)
|
|
48
|
+
// https://github.com/jestjs/jest/blob/1d682f21c7a35da4d3ab3a1436a357b980ebd0fa/packages/jest-worker/src/types.ts#L37
|
|
49
|
+
const CHILD_MESSAGE_CALL = 1
|
|
47
50
|
// Maximum time we'll wait for the tracer to flush
|
|
48
51
|
const FLUSH_TIMEOUT = 10000
|
|
49
52
|
|
|
50
53
|
let skippableSuites = []
|
|
51
|
-
let knownTests =
|
|
54
|
+
let knownTests = {}
|
|
52
55
|
let isCodeCoverageEnabled = false
|
|
53
56
|
let isSuitesSkippingEnabled = false
|
|
54
57
|
let isUserCodeCoverageEnabled = false
|
|
@@ -63,16 +66,17 @@ let hasFilteredSkippableSuites = false
|
|
|
63
66
|
const sessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
64
67
|
|
|
65
68
|
const specStatusToTestStatus = {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
pending: 'skip',
|
|
70
|
+
disabled: 'skip',
|
|
71
|
+
todo: 'skip',
|
|
72
|
+
passed: 'pass',
|
|
73
|
+
failed: 'fail'
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
const asyncResources = new WeakMap()
|
|
74
77
|
const originalTestFns = new WeakMap()
|
|
75
78
|
const retriedTestsToNumAttempts = new Map()
|
|
79
|
+
const newTestsTestStatuses = new Map()
|
|
76
80
|
|
|
77
81
|
// based on https://github.com/facebook/jest/blob/main/packages/jest-circus/src/formatNodeAssertErrors.ts#L41
|
|
78
82
|
function formatJestError (errors) {
|
|
@@ -101,8 +105,11 @@ function getTestEnvironmentOptions (config) {
|
|
|
101
105
|
return {}
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
function
|
|
105
|
-
return
|
|
108
|
+
function getEfdStats (testStatuses) {
|
|
109
|
+
return testStatuses.reduce((acc, testStatus) => {
|
|
110
|
+
acc[testStatus]++
|
|
111
|
+
return acc
|
|
112
|
+
}, { pass: 0, fail: 0 })
|
|
106
113
|
}
|
|
107
114
|
|
|
108
115
|
function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
@@ -127,9 +134,12 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
127
134
|
this.isEarlyFlakeDetectionEnabled = this.testEnvironmentOptions._ddIsEarlyFlakeDetectionEnabled
|
|
128
135
|
|
|
129
136
|
if (this.isEarlyFlakeDetectionEnabled) {
|
|
137
|
+
const hasKnownTests = !!knownTests.jest
|
|
130
138
|
earlyFlakeDetectionNumRetries = this.testEnvironmentOptions._ddEarlyFlakeDetectionNumRetries
|
|
131
139
|
try {
|
|
132
|
-
this.knownTestsForThisSuite =
|
|
140
|
+
this.knownTestsForThisSuite = hasKnownTests
|
|
141
|
+
? (knownTests.jest[this.testSuite] || [])
|
|
142
|
+
: this.getKnownTestsForSuite(this.testEnvironmentOptions._ddKnownTests)
|
|
133
143
|
} catch (e) {
|
|
134
144
|
// If there has been an error parsing the tests, we'll disable Early Flake Deteciton
|
|
135
145
|
this.isEarlyFlakeDetectionEnabled = false
|
|
@@ -149,14 +159,15 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
149
159
|
if (typeof knownTestsForSuite === 'string') {
|
|
150
160
|
knownTestsForSuite = JSON.parse(knownTestsForSuite)
|
|
151
161
|
}
|
|
152
|
-
return knownTestsForSuite
|
|
162
|
+
return knownTestsForSuite
|
|
153
163
|
}
|
|
154
164
|
|
|
155
165
|
// Add the `add_test` event we don't have the test object yet, so
|
|
156
166
|
// we use its describe block to get the full name
|
|
157
167
|
getTestNameFromAddTestEvent (event, state) {
|
|
158
168
|
const describeSuffix = getJestTestName(state.currentDescribeBlock)
|
|
159
|
-
|
|
169
|
+
const fullTestName = describeSuffix ? `${describeSuffix} ${event.testName}` : event.testName
|
|
170
|
+
return removeEfdStringFromTestName(fullTestName)
|
|
160
171
|
}
|
|
161
172
|
|
|
162
173
|
async handleTestEvent (event, state) {
|
|
@@ -197,7 +208,6 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
197
208
|
retriedTestsToNumAttempts.set(originalTestName, numEfdRetry + 1)
|
|
198
209
|
}
|
|
199
210
|
}
|
|
200
|
-
|
|
201
211
|
asyncResource.runInAsyncScope(() => {
|
|
202
212
|
testStartCh.publish({
|
|
203
213
|
name: removeEfdStringFromTestName(testName),
|
|
@@ -223,7 +233,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
223
233
|
retriedTestsToNumAttempts.set(testName, 0)
|
|
224
234
|
for (let retryIndex = 0; retryIndex < earlyFlakeDetectionNumRetries; retryIndex++) {
|
|
225
235
|
if (this.global.test) {
|
|
226
|
-
this.global.test(
|
|
236
|
+
this.global.test(addEfdStringToTestName(event.testName, retryIndex), event.fn, event.timeout)
|
|
227
237
|
} else {
|
|
228
238
|
log.error('Early flake detection could not retry test because global.test is undefined')
|
|
229
239
|
}
|
|
@@ -246,6 +256,19 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
246
256
|
})
|
|
247
257
|
// restore in case it is retried
|
|
248
258
|
event.test.fn = originalTestFns.get(event.test)
|
|
259
|
+
// We'll store the test statuses of the retries
|
|
260
|
+
if (this.isEarlyFlakeDetectionEnabled) {
|
|
261
|
+
const testName = getJestTestName(event.test)
|
|
262
|
+
const originalTestName = removeEfdStringFromTestName(testName)
|
|
263
|
+
const isNewTest = retriedTestsToNumAttempts.has(originalTestName)
|
|
264
|
+
if (isNewTest) {
|
|
265
|
+
if (newTestsTestStatuses.has(originalTestName)) {
|
|
266
|
+
newTestsTestStatuses.get(originalTestName).push(status)
|
|
267
|
+
} else {
|
|
268
|
+
newTestsTestStatuses.set(originalTestName, [status])
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
249
272
|
})
|
|
250
273
|
}
|
|
251
274
|
if (event.name === 'test_skip' || event.name === 'test_todo') {
|
|
@@ -405,6 +428,9 @@ function cliWrapper (cli, jestVersion) {
|
|
|
405
428
|
const { err, knownTests: receivedKnownTests } = await knownTestsPromise
|
|
406
429
|
if (!err) {
|
|
407
430
|
knownTests = receivedKnownTests
|
|
431
|
+
} else {
|
|
432
|
+
// We disable EFD if there has been an error in the known tests request
|
|
433
|
+
isEarlyFlakeDetectionEnabled = false
|
|
408
434
|
}
|
|
409
435
|
} catch (err) {
|
|
410
436
|
log.error(err)
|
|
@@ -509,6 +535,28 @@ function cliWrapper (cli, jestVersion) {
|
|
|
509
535
|
|
|
510
536
|
numSkippedSuites = 0
|
|
511
537
|
|
|
538
|
+
/**
|
|
539
|
+
* If Early Flake Detection (EFD) is enabled the logic is as follows:
|
|
540
|
+
* - If all attempts for a test are failing, the test has failed and we will let the test process fail.
|
|
541
|
+
* - If just a single attempt passes, we will prevent the test process from failing.
|
|
542
|
+
* The rationale behind is the following: you may still be able to block your CI pipeline by gating
|
|
543
|
+
* on flakiness (the test will be considered flaky), but you may choose to unblock the pipeline too.
|
|
544
|
+
*/
|
|
545
|
+
|
|
546
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
547
|
+
let numFailedTestsToIgnore = 0
|
|
548
|
+
for (const testStatuses of newTestsTestStatuses.values()) {
|
|
549
|
+
const { pass, fail } = getEfdStats(testStatuses)
|
|
550
|
+
if (pass > 0) { // as long as one passes, we'll consider the test passed
|
|
551
|
+
numFailedTestsToIgnore += fail
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// If every test that failed was an EFD retry, we'll consider the suite passed
|
|
555
|
+
if (numFailedTestsToIgnore !== 0 && result.results.numFailedTests === numFailedTestsToIgnore) {
|
|
556
|
+
result.results.success = true
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
512
560
|
return result
|
|
513
561
|
})
|
|
514
562
|
|
|
@@ -620,7 +668,6 @@ function configureTestEnvironment (readConfigsResult) {
|
|
|
620
668
|
// because `jestAdapterWrapper` runs in a different process. We have to go through `testEnvironmentOptions`
|
|
621
669
|
configs.forEach(config => {
|
|
622
670
|
config.testEnvironmentOptions._ddTestCodeCoverageEnabled = isCodeCoverageEnabled
|
|
623
|
-
config.testEnvironmentOptions._ddKnownTests = knownTests
|
|
624
671
|
})
|
|
625
672
|
|
|
626
673
|
isUserCodeCoverageEnabled = !!readConfigsResult.globalConfig.collectCoverage
|
|
@@ -796,6 +843,38 @@ addHook({
|
|
|
796
843
|
file: 'build/workers/ChildProcessWorker.js'
|
|
797
844
|
}, (childProcessWorker) => {
|
|
798
845
|
const ChildProcessWorker = childProcessWorker.default
|
|
846
|
+
shimmer.wrap(ChildProcessWorker.prototype, 'send', send => function (request) {
|
|
847
|
+
if (!isEarlyFlakeDetectionEnabled) {
|
|
848
|
+
return send.apply(this, arguments)
|
|
849
|
+
}
|
|
850
|
+
const [type] = request
|
|
851
|
+
// eslint-disable-next-line
|
|
852
|
+
// https://github.com/jestjs/jest/blob/1d682f21c7a35da4d3ab3a1436a357b980ebd0fa/packages/jest-worker/src/workers/ChildProcessWorker.ts#L424
|
|
853
|
+
if (type === CHILD_MESSAGE_CALL) {
|
|
854
|
+
// This is the message that the main process sends to the worker to run a test suite (=test file).
|
|
855
|
+
// In here we modify the config.testEnvironmentOptions to include the known tests for the suite.
|
|
856
|
+
// This way the suite only knows about the tests that are part of it.
|
|
857
|
+
const args = request[request.length - 1]
|
|
858
|
+
if (args.length > 1) {
|
|
859
|
+
return send.apply(this, arguments)
|
|
860
|
+
}
|
|
861
|
+
if (!args[0]?.config) {
|
|
862
|
+
return send.apply(this, arguments)
|
|
863
|
+
}
|
|
864
|
+
const [{ globalConfig, config, path: testSuiteAbsolutePath }] = args
|
|
865
|
+
const testSuite = getTestSuitePath(testSuiteAbsolutePath, globalConfig.rootDir || process.cwd())
|
|
866
|
+
const suiteKnownTests = knownTests.jest?.[testSuite] || []
|
|
867
|
+
args[0].config = {
|
|
868
|
+
...config,
|
|
869
|
+
testEnvironmentOptions: {
|
|
870
|
+
...config.testEnvironmentOptions,
|
|
871
|
+
_ddKnownTests: suiteKnownTests
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
return send.apply(this, arguments)
|
|
877
|
+
})
|
|
799
878
|
shimmer.wrap(ChildProcessWorker.prototype, '_onMessage', _onMessage => function () {
|
|
800
879
|
const [code, data] = arguments[0]
|
|
801
880
|
if (code === JEST_WORKER_TRACE_PAYLOAD_CODE) { // datadog trace payload
|
|
@@ -38,7 +38,8 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
38
38
|
constructor (options) {
|
|
39
39
|
super(options)
|
|
40
40
|
this._brokers = (options.brokers && typeof options.brokers !== 'function')
|
|
41
|
-
? options.brokers.join(',')
|
|
41
|
+
? options.brokers.join(',')
|
|
42
|
+
: undefined
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -67,7 +68,10 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
67
68
|
const result = send.apply(this, arguments)
|
|
68
69
|
|
|
69
70
|
result.then(
|
|
70
|
-
innerAsyncResource.bind(
|
|
71
|
+
innerAsyncResource.bind(res => {
|
|
72
|
+
producerFinishCh.publish(undefined)
|
|
73
|
+
producerCommitCh.publish(res)
|
|
74
|
+
}),
|
|
71
75
|
innerAsyncResource.bind(err => {
|
|
72
76
|
if (err) {
|
|
73
77
|
producerErrorCh.publish(err)
|
|
@@ -76,12 +80,6 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
76
80
|
})
|
|
77
81
|
)
|
|
78
82
|
|
|
79
|
-
result.then(res => {
|
|
80
|
-
if (producerCommitCh.hasSubscribers) {
|
|
81
|
-
producerCommitCh.publish(res)
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
|
|
85
83
|
return result
|
|
86
84
|
} catch (e) {
|
|
87
85
|
producerErrorCh.publish(e)
|
|
@@ -76,8 +76,9 @@ addHook({ name: 'ldapjs', versions: ['>=2'] }, ldapjs => {
|
|
|
76
76
|
const callbackIndex = getCallbackArgIndex(arguments)
|
|
77
77
|
if (callbackIndex > -1) {
|
|
78
78
|
const callback = arguments[callbackIndex]
|
|
79
|
+
// eslint-disable-next-line n/handle-callback-err
|
|
79
80
|
arguments[callbackIndex] = shimmer.wrap(callback, function (err, corkedEmitter) {
|
|
80
|
-
if (typeof corkedEmitter === 'object' && typeof corkedEmitter
|
|
81
|
+
if (typeof corkedEmitter === 'object' && typeof corkedEmitter.on === 'function') {
|
|
81
82
|
wrapEmitter(corkedEmitter)
|
|
82
83
|
}
|
|
83
84
|
callback.apply(this, arguments)
|
|
@@ -483,7 +483,7 @@ addHook({
|
|
|
483
483
|
*/
|
|
484
484
|
shimmer.wrap(Mocha.prototype, 'run', run => function () {
|
|
485
485
|
if (this.options.parallel) {
|
|
486
|
-
log.warn(
|
|
486
|
+
log.warn('Unable to initialize CI Visibility because Mocha is running in parallel mode.')
|
|
487
487
|
return run.apply(this, arguments)
|
|
488
488
|
}
|
|
489
489
|
|