dd-trace 5.21.0 → 5.23.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 +2 -0
- package/index.d.ts +20 -8
- package/package.json +11 -5
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
- package/packages/datadog-instrumentations/src/aws-sdk.js +4 -4
- package/packages/datadog-instrumentations/src/body-parser.js +4 -4
- package/packages/datadog-instrumentations/src/cassandra-driver.js +2 -2
- package/packages/datadog-instrumentations/src/child_process.js +2 -2
- package/packages/datadog-instrumentations/src/connect.js +4 -4
- package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
- package/packages/datadog-instrumentations/src/couchbase.js +12 -12
- package/packages/datadog-instrumentations/src/cucumber.js +294 -56
- package/packages/datadog-instrumentations/src/dns.js +10 -10
- package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
- package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +3 -3
- package/packages/datadog-instrumentations/src/express.js +4 -4
- package/packages/datadog-instrumentations/src/fastify.js +6 -6
- package/packages/datadog-instrumentations/src/fetch.js +1 -1
- package/packages/datadog-instrumentations/src/find-my-way.js +2 -2
- package/packages/datadog-instrumentations/src/fs.js +2 -2
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +2 -2
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -6
- package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
- package/packages/datadog-instrumentations/src/hapi.js +10 -13
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/http/client.js +3 -3
- package/packages/datadog-instrumentations/src/jest.js +8 -5
- package/packages/datadog-instrumentations/src/kafkajs.js +67 -31
- package/packages/datadog-instrumentations/src/knex.js +2 -2
- package/packages/datadog-instrumentations/src/koa.js +5 -5
- package/packages/datadog-instrumentations/src/ldapjs.js +1 -1
- package/packages/datadog-instrumentations/src/mariadb.js +8 -8
- package/packages/datadog-instrumentations/src/memcached.js +2 -2
- package/packages/datadog-instrumentations/src/microgateway-core.js +7 -5
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +139 -53
- package/packages/datadog-instrumentations/src/mocha/utils.js +37 -18
- package/packages/datadog-instrumentations/src/mocha/worker.js +29 -1
- package/packages/datadog-instrumentations/src/mocha.js +4 -0
- package/packages/datadog-instrumentations/src/moleculer/server.js +2 -2
- package/packages/datadog-instrumentations/src/mongodb-core.js +7 -7
- package/packages/datadog-instrumentations/src/mongoose.js +5 -6
- package/packages/datadog-instrumentations/src/mysql.js +3 -3
- package/packages/datadog-instrumentations/src/mysql2.js +6 -6
- package/packages/datadog-instrumentations/src/net.js +2 -2
- package/packages/datadog-instrumentations/src/next.js +5 -5
- package/packages/datadog-instrumentations/src/openai.js +62 -71
- package/packages/datadog-instrumentations/src/oracledb.js +8 -8
- package/packages/datadog-instrumentations/src/passport-http.js +1 -1
- package/packages/datadog-instrumentations/src/passport-local.js +1 -1
- package/packages/datadog-instrumentations/src/passport-utils.js +1 -1
- package/packages/datadog-instrumentations/src/pg.js +60 -5
- package/packages/datadog-instrumentations/src/pino.js +4 -4
- package/packages/datadog-instrumentations/src/playwright.js +6 -4
- package/packages/datadog-instrumentations/src/redis.js +2 -2
- package/packages/datadog-instrumentations/src/restify.js +4 -4
- package/packages/datadog-instrumentations/src/rhea.js +4 -4
- package/packages/datadog-instrumentations/src/router.js +5 -5
- package/packages/datadog-instrumentations/src/sharedb.js +2 -2
- package/packages/datadog-instrumentations/src/vitest.js +188 -12
- package/packages/datadog-instrumentations/src/winston.js +2 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +1 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +33 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +24 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +39 -10
- package/packages/datadog-plugin-cypress/src/support.js +4 -1
- package/packages/datadog-plugin-hapi/src/index.js +2 -2
- package/packages/datadog-plugin-http/src/client.js +1 -42
- package/packages/datadog-plugin-http2/src/client.js +1 -26
- package/packages/datadog-plugin-jest/src/index.js +18 -1
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +20 -0
- package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -2
- package/packages/datadog-plugin-kafkajs/src/index.js +3 -1
- package/packages/datadog-plugin-mocha/src/index.js +18 -0
- package/packages/datadog-plugin-openai/src/index.js +85 -65
- package/packages/datadog-plugin-playwright/src/index.js +9 -0
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -3
- package/packages/datadog-plugin-vitest/src/index.js +68 -3
- package/packages/datadog-shimmer/src/shimmer.js +144 -10
- package/packages/dd-trace/src/appsec/addresses.js +3 -1
- package/packages/dd-trace/src/appsec/blocking.js +23 -17
- package/packages/dd-trace/src/appsec/channels.js +4 -2
- package/packages/dd-trace/src/appsec/graphql.js +3 -1
- package/packages/dd-trace/src/appsec/iast/iast-log.js +2 -1
- package/packages/dd-trace/src/appsec/rasp/index.js +103 -0
- package/packages/dd-trace/src/appsec/rasp/sql_injection.js +86 -0
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +37 -0
- package/packages/dd-trace/src/appsec/rasp/utils.js +63 -0
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -0
- package/packages/dd-trace/src/appsec/remote_config/index.js +16 -7
- package/packages/dd-trace/src/appsec/remote_config/manager.js +93 -52
- package/packages/dd-trace/src/appsec/rule_manager.js +8 -0
- package/packages/dd-trace/src/appsec/telemetry.js +3 -3
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +33 -14
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +4 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +15 -1
- package/packages/dd-trace/src/config.js +100 -40
- package/packages/dd-trace/src/constants.js +11 -1
- package/packages/dd-trace/src/data_streams_context.js +3 -0
- package/packages/dd-trace/src/datastreams/fnv.js +23 -0
- package/packages/dd-trace/src/datastreams/pathway.js +12 -5
- package/packages/dd-trace/src/datastreams/processor.js +35 -0
- package/packages/dd-trace/src/datastreams/schemas/schema.js +8 -0
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +125 -0
- package/packages/dd-trace/src/datastreams/schemas/schema_sampler.js +29 -0
- package/packages/dd-trace/src/debugger/devtools_client/config.js +24 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +57 -0
- package/packages/dd-trace/src/debugger/devtools_client/inspector_promises_polyfill.js +23 -0
- package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +164 -0
- package/packages/dd-trace/src/debugger/devtools_client/send.js +28 -0
- package/packages/dd-trace/src/debugger/devtools_client/session.js +7 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +47 -0
- package/packages/dd-trace/src/debugger/devtools_client/status.js +109 -0
- package/packages/dd-trace/src/debugger/index.js +92 -0
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +29 -2
- package/packages/dd-trace/src/exporters/common/request.js +1 -1
- package/packages/dd-trace/src/lambda/handler.js +1 -0
- package/packages/dd-trace/src/lambda/index.js +12 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -6
- package/packages/dd-trace/src/payload-tagging/config/aws.json +30 -0
- package/packages/dd-trace/src/payload-tagging/config/index.js +30 -0
- package/packages/dd-trace/src/payload-tagging/index.js +93 -0
- package/packages/dd-trace/src/payload-tagging/tagging.js +83 -0
- package/packages/dd-trace/src/plugin_manager.js +11 -10
- package/packages/dd-trace/src/plugins/ci_plugin.js +33 -8
- package/packages/dd-trace/src/plugins/util/env.js +5 -2
- package/packages/dd-trace/src/plugins/util/test.js +24 -4
- package/packages/dd-trace/src/profiler.js +15 -5
- package/packages/dd-trace/src/profiling/config.js +7 -4
- package/packages/dd-trace/src/profiling/exporter_cli.js +13 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +8 -2
- package/packages/dd-trace/src/profiling/profiler.js +0 -9
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +13 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +16 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +16 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +24 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +16 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +48 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +24 -0
- package/packages/dd-trace/src/profiling/profilers/events.js +108 -32
- package/packages/dd-trace/src/profiling/profilers/shared.js +5 -0
- package/packages/dd-trace/src/profiling/profilers/wall.js +9 -3
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +59 -60
- package/packages/dd-trace/src/proxy.js +31 -24
- package/packages/dd-trace/src/span_stats.js +4 -2
- package/packages/dd-trace/src/telemetry/index.js +23 -6
- package/packages/dd-trace/src/telemetry/logs/index.js +20 -0
- package/packages/dd-trace/src/appsec/rasp.js +0 -176
|
@@ -11,12 +11,12 @@ const {
|
|
|
11
11
|
fromCoverageMapToCoverage,
|
|
12
12
|
getCoveredFilenamesFromCoverage,
|
|
13
13
|
mergeCoverage,
|
|
14
|
-
resetCoverage
|
|
14
|
+
resetCoverage,
|
|
15
|
+
getIsFaultyEarlyFlakeDetection
|
|
15
16
|
} = require('../../../dd-trace/src/plugins/util/test')
|
|
16
17
|
|
|
17
18
|
const {
|
|
18
19
|
isNewTest,
|
|
19
|
-
retryTest,
|
|
20
20
|
getSuitesByTestFile,
|
|
21
21
|
runnableWrapper,
|
|
22
22
|
getOnTestHandler,
|
|
@@ -25,22 +25,21 @@ const {
|
|
|
25
25
|
getOnHookEndHandler,
|
|
26
26
|
getOnFailHandler,
|
|
27
27
|
getOnPendingHandler,
|
|
28
|
-
testFileToSuiteAr
|
|
28
|
+
testFileToSuiteAr,
|
|
29
|
+
newTests,
|
|
30
|
+
getTestFullName,
|
|
31
|
+
getRunTestsWrapper
|
|
29
32
|
} = require('./utils')
|
|
33
|
+
|
|
30
34
|
require('./common')
|
|
31
35
|
|
|
32
36
|
const testSessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
33
37
|
const patched = new WeakSet()
|
|
34
|
-
|
|
35
|
-
let suitesToSkip = []
|
|
38
|
+
|
|
36
39
|
const unskippableSuites = []
|
|
40
|
+
let suitesToSkip = []
|
|
37
41
|
let isSuitesSkipped = false
|
|
38
42
|
let skippedSuites = []
|
|
39
|
-
let isEarlyFlakeDetectionEnabled = false
|
|
40
|
-
let isSuitesSkippingEnabled = false
|
|
41
|
-
let isFlakyTestRetriesEnabled = false
|
|
42
|
-
let earlyFlakeDetectionNumRetries = 0
|
|
43
|
-
let knownTests = []
|
|
44
43
|
let itrCorrelationId = ''
|
|
45
44
|
let isForcedToRun = false
|
|
46
45
|
const config = {}
|
|
@@ -69,6 +68,17 @@ const itrSkippedSuitesCh = channel('ci:mocha:itr:skipped-suites')
|
|
|
69
68
|
|
|
70
69
|
const getCodeCoverageCh = channel('ci:nyc:get-coverage')
|
|
71
70
|
|
|
71
|
+
// Tests from workers do not come with `isFailed` method
|
|
72
|
+
function isTestFailed (test) {
|
|
73
|
+
if (test.isFailed) {
|
|
74
|
+
return test.isFailed()
|
|
75
|
+
}
|
|
76
|
+
if (test.isPending) {
|
|
77
|
+
return !test.isPending() && test.state !== 'failed'
|
|
78
|
+
}
|
|
79
|
+
return false
|
|
80
|
+
}
|
|
81
|
+
|
|
72
82
|
function getFilteredSuites (originalSuites) {
|
|
73
83
|
return originalSuites.reduce((acc, suite) => {
|
|
74
84
|
const testPath = getTestSuitePath(suite.file, process.cwd())
|
|
@@ -107,7 +117,7 @@ function getOnEndHandler (isParallel) {
|
|
|
107
117
|
status = 'fail'
|
|
108
118
|
}
|
|
109
119
|
|
|
110
|
-
if (
|
|
120
|
+
if (config.isEarlyFlakeDetectionEnabled) {
|
|
111
121
|
/**
|
|
112
122
|
* If Early Flake Detection (EFD) is enabled the logic is as follows:
|
|
113
123
|
* - If all attempts for a test are failing, the test has failed and we will let the test process fail.
|
|
@@ -116,7 +126,7 @@ function getOnEndHandler (isParallel) {
|
|
|
116
126
|
* on flakiness (the test will be considered flaky), but you may choose to unblock the pipeline too.
|
|
117
127
|
*/
|
|
118
128
|
for (const tests of Object.values(newTests)) {
|
|
119
|
-
const failingNewTests = tests.filter(test => test
|
|
129
|
+
const failingNewTests = tests.filter(test => isTestFailed(test))
|
|
120
130
|
const areAllNewTestsFailing = failingNewTests.length === tests.length
|
|
121
131
|
if (failingNewTests.length && !areAllNewTestsFailing) {
|
|
122
132
|
this.stats.failures -= failingNewTests.length
|
|
@@ -153,13 +163,14 @@ function getOnEndHandler (isParallel) {
|
|
|
153
163
|
hasForcedToRunSuites: isForcedToRun,
|
|
154
164
|
hasUnskippableSuites: !!unskippableSuites.length,
|
|
155
165
|
error,
|
|
156
|
-
isEarlyFlakeDetectionEnabled,
|
|
166
|
+
isEarlyFlakeDetectionEnabled: config.isEarlyFlakeDetectionEnabled,
|
|
167
|
+
isEarlyFlakeDetectionFaulty: config.isEarlyFlakeDetectionFaulty,
|
|
157
168
|
isParallel
|
|
158
169
|
})
|
|
159
170
|
})
|
|
160
171
|
}
|
|
161
172
|
|
|
162
|
-
function getExecutionConfiguration (runner, onFinishRequest) {
|
|
173
|
+
function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
|
|
163
174
|
const mochaRunAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
164
175
|
|
|
165
176
|
const onReceivedSkippableSuites = ({ err, skippableSuites, itrCorrelationId: responseItrCorrelationId }) => {
|
|
@@ -186,15 +197,15 @@ function getExecutionConfiguration (runner, onFinishRequest) {
|
|
|
186
197
|
onFinishRequest()
|
|
187
198
|
}
|
|
188
199
|
|
|
189
|
-
const onReceivedKnownTests = ({ err, knownTests
|
|
200
|
+
const onReceivedKnownTests = ({ err, knownTests }) => {
|
|
190
201
|
if (err) {
|
|
191
|
-
knownTests = []
|
|
192
|
-
isEarlyFlakeDetectionEnabled = false
|
|
202
|
+
config.knownTests = []
|
|
203
|
+
config.isEarlyFlakeDetectionEnabled = false
|
|
193
204
|
} else {
|
|
194
|
-
knownTests =
|
|
205
|
+
config.knownTests = knownTests
|
|
195
206
|
}
|
|
196
207
|
|
|
197
|
-
if (isSuitesSkippingEnabled) {
|
|
208
|
+
if (config.isSuitesSkippingEnabled) {
|
|
198
209
|
skippableSuitesCh.publish({
|
|
199
210
|
onDone: mochaRunAsyncResource.bind(onReceivedSkippableSuites)
|
|
200
211
|
})
|
|
@@ -208,21 +219,19 @@ function getExecutionConfiguration (runner, onFinishRequest) {
|
|
|
208
219
|
return onFinishRequest()
|
|
209
220
|
}
|
|
210
221
|
|
|
211
|
-
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
config.
|
|
217
|
-
config.
|
|
218
|
-
config.earlyFlakeDetectionNumRetries = earlyFlakeDetectionNumRetries
|
|
219
|
-
config.isFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
|
|
222
|
+
config.isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
223
|
+
config.earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
224
|
+
config.earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold
|
|
225
|
+
// ITR and auto test retries are not supported in parallel mode yet
|
|
226
|
+
config.isSuitesSkippingEnabled = !isParallel && libraryConfig.isSuitesSkippingEnabled
|
|
227
|
+
config.isFlakyTestRetriesEnabled = !isParallel && libraryConfig.isFlakyTestRetriesEnabled
|
|
228
|
+
config.flakyTestRetriesCount = !isParallel && libraryConfig.flakyTestRetriesCount
|
|
220
229
|
|
|
221
|
-
if (isEarlyFlakeDetectionEnabled) {
|
|
230
|
+
if (config.isEarlyFlakeDetectionEnabled) {
|
|
222
231
|
knownTestsCh.publish({
|
|
223
232
|
onDone: mochaRunAsyncResource.bind(onReceivedKnownTests)
|
|
224
233
|
})
|
|
225
|
-
} else if (isSuitesSkippingEnabled) {
|
|
234
|
+
} else if (config.isSuitesSkippingEnabled) {
|
|
226
235
|
skippableSuitesCh.publish({
|
|
227
236
|
onDone: mochaRunAsyncResource.bind(onReceivedSkippableSuites)
|
|
228
237
|
})
|
|
@@ -250,8 +259,8 @@ addHook({
|
|
|
250
259
|
return run.apply(this, arguments)
|
|
251
260
|
}
|
|
252
261
|
|
|
253
|
-
// `options.delay` does not work in parallel mode, so
|
|
254
|
-
//
|
|
262
|
+
// `options.delay` does not work in parallel mode, so we can't delay the execution this way
|
|
263
|
+
// This needs to be both here and in `runMocha` hook. Read the comment in `runMocha` hook for more info.
|
|
255
264
|
this.options.delay = true
|
|
256
265
|
|
|
257
266
|
const runner = run.apply(this, arguments)
|
|
@@ -263,7 +272,19 @@ addHook({
|
|
|
263
272
|
}
|
|
264
273
|
})
|
|
265
274
|
|
|
266
|
-
getExecutionConfiguration(runner, () => {
|
|
275
|
+
getExecutionConfiguration(runner, false, () => {
|
|
276
|
+
if (config.isEarlyFlakeDetectionEnabled) {
|
|
277
|
+
const testSuites = this.files.map(file => getTestSuitePath(file, process.cwd()))
|
|
278
|
+
const isFaulty = getIsFaultyEarlyFlakeDetection(
|
|
279
|
+
testSuites,
|
|
280
|
+
config.knownTests?.mocha || {},
|
|
281
|
+
config.earlyFlakeDetectionFaultyThreshold
|
|
282
|
+
)
|
|
283
|
+
if (isFaulty) {
|
|
284
|
+
config.isEarlyFlakeDetectionEnabled = false
|
|
285
|
+
config.isEarlyFlakeDetectionFaulty = true
|
|
286
|
+
}
|
|
287
|
+
}
|
|
267
288
|
if (getCodeCoverageCh.hasSubscribers) {
|
|
268
289
|
getCodeCoverageCh.publish({
|
|
269
290
|
onDone: (receivedCodeCoverage) => {
|
|
@@ -281,9 +302,6 @@ addHook({
|
|
|
281
302
|
return Mocha
|
|
282
303
|
})
|
|
283
304
|
|
|
284
|
-
// Only used to set `mocha.options.delay` to true in serial mode. When the mocha CLI is used,
|
|
285
|
-
// setting options.delay in Mocha#run is not enough to delay the execution.
|
|
286
|
-
// TODO: modify this hook to grab the data in parallel mode, so that ITR and EFD can work.
|
|
287
305
|
addHook({
|
|
288
306
|
name: 'mocha',
|
|
289
307
|
versions: ['>=5.2.0'],
|
|
@@ -293,15 +311,20 @@ addHook({
|
|
|
293
311
|
if (!testStartCh.hasSubscribers) {
|
|
294
312
|
return runMocha.apply(this, arguments)
|
|
295
313
|
}
|
|
296
|
-
|
|
297
314
|
const mocha = arguments[0]
|
|
315
|
+
|
|
298
316
|
/**
|
|
299
317
|
* This attaches `run` to the global context, which we'll call after
|
|
300
|
-
* our configuration and skippable suites requests
|
|
318
|
+
* our configuration and skippable suites requests.
|
|
319
|
+
* You need this both here and in Mocha#run hook: the programmatic API
|
|
320
|
+
* does not call `runMocha`, so it needs to be in Mocha#run. When using
|
|
321
|
+
* the CLI, modifying `options.delay` in Mocha#run is not enough (it's too late),
|
|
322
|
+
* so it also needs to be here.
|
|
301
323
|
*/
|
|
302
324
|
if (!mocha.options.parallel) {
|
|
303
325
|
mocha.options.delay = true
|
|
304
326
|
}
|
|
327
|
+
|
|
305
328
|
return runMocha.apply(this, arguments)
|
|
306
329
|
})
|
|
307
330
|
return run
|
|
@@ -318,18 +341,7 @@ addHook({
|
|
|
318
341
|
|
|
319
342
|
patched.add(Runner)
|
|
320
343
|
|
|
321
|
-
shimmer.wrap(Runner.prototype, 'runTests', runTests =>
|
|
322
|
-
if (isEarlyFlakeDetectionEnabled) {
|
|
323
|
-
// by the time we reach `this.on('test')`, it is too late. We need to add retries here
|
|
324
|
-
suite.tests.forEach(test => {
|
|
325
|
-
if (!test.isPending() && isNewTest(test, knownTests)) {
|
|
326
|
-
test._ddIsNew = true
|
|
327
|
-
retryTest(test, earlyFlakeDetectionNumRetries)
|
|
328
|
-
}
|
|
329
|
-
})
|
|
330
|
-
}
|
|
331
|
-
return runTests.apply(this, arguments)
|
|
332
|
-
})
|
|
344
|
+
shimmer.wrap(Runner.prototype, 'runTests', runTests => getRunTestsWrapper(runTests, config))
|
|
333
345
|
|
|
334
346
|
shimmer.wrap(Runner.prototype, 'run', run => function () {
|
|
335
347
|
if (!testStartCh.hasSubscribers) {
|
|
@@ -513,10 +525,10 @@ addHook({
|
|
|
513
525
|
// Used to start and finish test session and test module
|
|
514
526
|
addHook({
|
|
515
527
|
name: 'mocha',
|
|
516
|
-
versions: ['>=
|
|
528
|
+
versions: ['>=8.0.0'],
|
|
517
529
|
file: 'lib/nodejs/parallel-buffered-runner.js'
|
|
518
530
|
}, (ParallelBufferedRunner, frameworkVersion) => {
|
|
519
|
-
shimmer.wrap(ParallelBufferedRunner.prototype, 'run', run => function () {
|
|
531
|
+
shimmer.wrap(ParallelBufferedRunner.prototype, 'run', run => function (cb, { files }) {
|
|
520
532
|
if (!testStartCh.hasSubscribers) {
|
|
521
533
|
return run.apply(this, arguments)
|
|
522
534
|
}
|
|
@@ -524,8 +536,82 @@ addHook({
|
|
|
524
536
|
this.once('start', getOnStartHandler(true, frameworkVersion))
|
|
525
537
|
this.once('end', getOnEndHandler(true))
|
|
526
538
|
|
|
527
|
-
|
|
539
|
+
getExecutionConfiguration(this, true, () => {
|
|
540
|
+
if (config.isEarlyFlakeDetectionEnabled) {
|
|
541
|
+
const testSuites = files.map(file => getTestSuitePath(file, process.cwd()))
|
|
542
|
+
const isFaulty = getIsFaultyEarlyFlakeDetection(
|
|
543
|
+
testSuites,
|
|
544
|
+
config.knownTests?.mocha || {},
|
|
545
|
+
config.earlyFlakeDetectionFaultyThreshold
|
|
546
|
+
)
|
|
547
|
+
if (isFaulty) {
|
|
548
|
+
config.isEarlyFlakeDetectionEnabled = false
|
|
549
|
+
config.isEarlyFlakeDetectionFaulty = true
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
run.apply(this, arguments)
|
|
553
|
+
})
|
|
554
|
+
|
|
555
|
+
return this
|
|
528
556
|
})
|
|
529
557
|
|
|
530
558
|
return ParallelBufferedRunner
|
|
531
559
|
})
|
|
560
|
+
|
|
561
|
+
// Only in parallel mode: BufferedWorkerPool#run is used to run a test file in a worker
|
|
562
|
+
// If Early Flake Detection is enabled,
|
|
563
|
+
// In this hook we pass the known tests to the worker and collect the new tests that run
|
|
564
|
+
addHook({
|
|
565
|
+
name: 'mocha',
|
|
566
|
+
versions: ['>=8.0.0'],
|
|
567
|
+
file: 'lib/nodejs/buffered-worker-pool.js'
|
|
568
|
+
}, (BufferedWorkerPoolPackage) => {
|
|
569
|
+
const { BufferedWorkerPool } = BufferedWorkerPoolPackage
|
|
570
|
+
|
|
571
|
+
shimmer.wrap(BufferedWorkerPool.prototype, 'run', run => async function (testSuiteAbsolutePath, workerArgs) {
|
|
572
|
+
if (!testStartCh.hasSubscribers || !config.isEarlyFlakeDetectionEnabled) {
|
|
573
|
+
return run.apply(this, arguments)
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
const testPath = getTestSuitePath(testSuiteAbsolutePath, process.cwd())
|
|
577
|
+
const testSuiteKnownTests = config.knownTests.mocha?.[testPath] || []
|
|
578
|
+
|
|
579
|
+
// We pass the known tests for the test file to the worker
|
|
580
|
+
const testFileResult = await run.apply(
|
|
581
|
+
this,
|
|
582
|
+
[
|
|
583
|
+
testSuiteAbsolutePath,
|
|
584
|
+
{
|
|
585
|
+
...workerArgs,
|
|
586
|
+
_ddEfdNumRetries: config.earlyFlakeDetectionNumRetries,
|
|
587
|
+
_ddKnownTests: {
|
|
588
|
+
mocha: {
|
|
589
|
+
[testPath]: testSuiteKnownTests
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
]
|
|
594
|
+
)
|
|
595
|
+
const tests = testFileResult
|
|
596
|
+
.events
|
|
597
|
+
.filter(event => event.eventName === 'test end')
|
|
598
|
+
.map(event => event.data)
|
|
599
|
+
|
|
600
|
+
// `newTests` is filled in the worker process, so we need to use the test results to fill it here too.
|
|
601
|
+
for (const test of tests) {
|
|
602
|
+
if (isNewTest(test, config.knownTests)) {
|
|
603
|
+
const testFullName = getTestFullName(test)
|
|
604
|
+
const tests = newTests[testFullName]
|
|
605
|
+
|
|
606
|
+
if (!tests) {
|
|
607
|
+
newTests[testFullName] = [test]
|
|
608
|
+
} else {
|
|
609
|
+
tests.push(test)
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return testFileResult
|
|
614
|
+
})
|
|
615
|
+
|
|
616
|
+
return BufferedWorkerPoolPackage
|
|
617
|
+
})
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
const {
|
|
4
4
|
getTestSuitePath,
|
|
5
5
|
removeEfdStringFromTestName,
|
|
6
|
-
addEfdStringToTestName
|
|
7
|
-
NUM_FAILED_TEST_RETRIES
|
|
6
|
+
addEfdStringToTestName
|
|
8
7
|
} = require('../../../dd-trace/src/plugins/util/test')
|
|
9
8
|
const { channel, AsyncResource } = require('../helpers/instrument')
|
|
10
9
|
const shimmer = require('../../../datadog-shimmer')
|
|
@@ -25,6 +24,7 @@ const originalFns = new WeakMap()
|
|
|
25
24
|
const testToStartLine = new WeakMap()
|
|
26
25
|
const testFileToSuiteAr = new Map()
|
|
27
26
|
const wrappedFunctions = new WeakSet()
|
|
27
|
+
const newTests = {}
|
|
28
28
|
|
|
29
29
|
function isNewTest (test, knownTests) {
|
|
30
30
|
const testSuite = getTestSuitePath(test.file, process.cwd())
|
|
@@ -114,7 +114,7 @@ function runnableWrapper (RunnablePackage, libraryConfig) {
|
|
|
114
114
|
}
|
|
115
115
|
// Flaky test retries does not work in parallel mode
|
|
116
116
|
if (libraryConfig?.isFlakyTestRetriesEnabled) {
|
|
117
|
-
this.retries(
|
|
117
|
+
this.retries(libraryConfig?.flakyTestRetriesCount)
|
|
118
118
|
}
|
|
119
119
|
// The reason why the wrapping logic is here is because we need to cover
|
|
120
120
|
// `afterEach` and `beforeEach` hooks as well.
|
|
@@ -152,7 +152,7 @@ function runnableWrapper (RunnablePackage, libraryConfig) {
|
|
|
152
152
|
return RunnablePackage
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
function getOnTestHandler (isMain
|
|
155
|
+
function getOnTestHandler (isMain) {
|
|
156
156
|
return function (test) {
|
|
157
157
|
const testStartLine = testToStartLine.get(test)
|
|
158
158
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
@@ -180,22 +180,22 @@ function getOnTestHandler (isMain, newTests) {
|
|
|
180
180
|
testStartLine
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
if (isMain) {
|
|
184
|
-
testInfo.isNew = isNew
|
|
185
|
-
testInfo.isEfdRetry = isEfdRetry
|
|
186
|
-
// We want to store the result of the new tests
|
|
187
|
-
if (isNew) {
|
|
188
|
-
const testFullName = getTestFullName(test)
|
|
189
|
-
if (newTests[testFullName]) {
|
|
190
|
-
newTests[testFullName].push(test)
|
|
191
|
-
} else {
|
|
192
|
-
newTests[testFullName] = [test]
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
} else {
|
|
183
|
+
if (!isMain) {
|
|
196
184
|
testInfo.isParallel = true
|
|
197
185
|
}
|
|
198
186
|
|
|
187
|
+
testInfo.isNew = isNew
|
|
188
|
+
testInfo.isEfdRetry = isEfdRetry
|
|
189
|
+
// We want to store the result of the new tests
|
|
190
|
+
if (isNew) {
|
|
191
|
+
const testFullName = getTestFullName(test)
|
|
192
|
+
if (newTests[testFullName]) {
|
|
193
|
+
newTests[testFullName].push(test)
|
|
194
|
+
} else {
|
|
195
|
+
newTests[testFullName] = [test]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
199
|
asyncResource.runInAsyncScope(() => {
|
|
200
200
|
testStartCh.publish(testInfo)
|
|
201
201
|
})
|
|
@@ -328,6 +328,23 @@ function getOnPendingHandler () {
|
|
|
328
328
|
}
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
|
+
|
|
332
|
+
// Hook to add retries to tests if EFD is enabled
|
|
333
|
+
function getRunTestsWrapper (runTests, config) {
|
|
334
|
+
return function (suite, fn) {
|
|
335
|
+
if (config.isEarlyFlakeDetectionEnabled) {
|
|
336
|
+
// by the time we reach `this.on('test')`, it is too late. We need to add retries here
|
|
337
|
+
suite.tests.forEach(test => {
|
|
338
|
+
if (!test.isPending() && isNewTest(test, config.knownTests)) {
|
|
339
|
+
test._ddIsNew = true
|
|
340
|
+
retryTest(test, config.earlyFlakeDetectionNumRetries)
|
|
341
|
+
}
|
|
342
|
+
})
|
|
343
|
+
}
|
|
344
|
+
return runTests.apply(this, arguments)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
331
348
|
module.exports = {
|
|
332
349
|
isNewTest,
|
|
333
350
|
retryTest,
|
|
@@ -346,5 +363,7 @@ module.exports = {
|
|
|
346
363
|
getOnHookEndHandler,
|
|
347
364
|
getOnFailHandler,
|
|
348
365
|
getOnPendingHandler,
|
|
349
|
-
testFileToSuiteAr
|
|
366
|
+
testFileToSuiteAr,
|
|
367
|
+
getRunTestsWrapper,
|
|
368
|
+
newTests
|
|
350
369
|
}
|
|
@@ -9,19 +9,47 @@ const {
|
|
|
9
9
|
getOnTestEndHandler,
|
|
10
10
|
getOnHookEndHandler,
|
|
11
11
|
getOnFailHandler,
|
|
12
|
-
getOnPendingHandler
|
|
12
|
+
getOnPendingHandler,
|
|
13
|
+
getRunTestsWrapper
|
|
13
14
|
} = require('./utils')
|
|
14
15
|
require('./common')
|
|
15
16
|
|
|
16
17
|
const workerFinishCh = channel('ci:mocha:worker:finish')
|
|
17
18
|
|
|
19
|
+
const config = {}
|
|
20
|
+
|
|
21
|
+
addHook({
|
|
22
|
+
name: 'mocha',
|
|
23
|
+
versions: ['>=8.0.0'],
|
|
24
|
+
file: 'lib/mocha.js'
|
|
25
|
+
}, (Mocha) => {
|
|
26
|
+
shimmer.wrap(Mocha.prototype, 'run', run => function () {
|
|
27
|
+
if (this.options._ddKnownTests) {
|
|
28
|
+
// EFD is enabled if there's a list of known tests
|
|
29
|
+
config.isEarlyFlakeDetectionEnabled = true
|
|
30
|
+
config.knownTests = this.options._ddKnownTests
|
|
31
|
+
config.earlyFlakeDetectionNumRetries = this.options._ddEfdNumRetries
|
|
32
|
+
delete this.options._ddKnownTests
|
|
33
|
+
delete this.options._ddEfdNumRetries
|
|
34
|
+
}
|
|
35
|
+
return run.apply(this, arguments)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
return Mocha
|
|
39
|
+
})
|
|
40
|
+
|
|
18
41
|
// Runner is also hooked in mocha/main.js, but in here we only generate test events.
|
|
19
42
|
addHook({
|
|
20
43
|
name: 'mocha',
|
|
21
44
|
versions: ['>=5.2.0'],
|
|
22
45
|
file: 'lib/runner.js'
|
|
23
46
|
}, function (Runner) {
|
|
47
|
+
shimmer.wrap(Runner.prototype, 'runTests', runTests => getRunTestsWrapper(runTests, config))
|
|
48
|
+
|
|
24
49
|
shimmer.wrap(Runner.prototype, 'run', run => function () {
|
|
50
|
+
if (!workerFinishCh.hasSubscribers) {
|
|
51
|
+
return run.apply(this, arguments)
|
|
52
|
+
}
|
|
25
53
|
// We flush when the worker ends with its test file (a mocha instance in a worker runs a single test file)
|
|
26
54
|
this.on('end', () => {
|
|
27
55
|
workerFinishCh.publish()
|
|
@@ -3,3 +3,7 @@ if (process.env.MOCHA_WORKER_ID) {
|
|
|
3
3
|
} else {
|
|
4
4
|
require('./mocha/main')
|
|
5
5
|
}
|
|
6
|
+
|
|
7
|
+
// TODO add appropriate calls to wrapFunction whenever we're adding a callback
|
|
8
|
+
// wrapper. Right now this is less of an issue since that only has effect in
|
|
9
|
+
// SSI, where CI Vis isn't supported.
|
|
@@ -24,7 +24,7 @@ function createMiddleware () {
|
|
|
24
24
|
localAction (next, action) {
|
|
25
25
|
const broker = this
|
|
26
26
|
|
|
27
|
-
return function datadogMiddleware (ctx) {
|
|
27
|
+
return shimmer.wrapFunction(next, next => function datadogMiddleware (ctx) {
|
|
28
28
|
const actionResource = new AsyncResource('bound-anonymous-fn')
|
|
29
29
|
|
|
30
30
|
return actionResource.runInAsyncScope(() => {
|
|
@@ -47,7 +47,7 @@ function createMiddleware () {
|
|
|
47
47
|
finishChannel.publish()
|
|
48
48
|
}
|
|
49
49
|
})
|
|
50
|
-
}
|
|
50
|
+
})
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -92,7 +92,7 @@ function wrapUnifiedCommand (command, operation, name) {
|
|
|
92
92
|
}
|
|
93
93
|
return instrument(operation, command, this, arguments, server, ns, ops, { name })
|
|
94
94
|
}
|
|
95
|
-
return
|
|
95
|
+
return wrapped
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function wrapConnectionCommand (command, operation, name, instrumentFn = instrument) {
|
|
@@ -109,7 +109,7 @@ function wrapConnectionCommand (command, operation, name, instrumentFn = instrum
|
|
|
109
109
|
ns = `${ns.db}.${ns.collection}`
|
|
110
110
|
return instrumentFn(operation, command, this, arguments, topology, ns, ops, { name })
|
|
111
111
|
}
|
|
112
|
-
return
|
|
112
|
+
return wrapped
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
function wrapQuery (query, operation, name) {
|
|
@@ -123,7 +123,7 @@ function wrapQuery (query, operation, name) {
|
|
|
123
123
|
return instrument(operation, query, this, arguments, pool, ns, ops)
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
return
|
|
126
|
+
return wrapped
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function wrapCursor (cursor, operation, name) {
|
|
@@ -135,7 +135,7 @@ function wrapCursor (cursor, operation, name) {
|
|
|
135
135
|
const ns = this.ns
|
|
136
136
|
return instrument(operation, cursor, this, arguments, pool, ns, {}, { name })
|
|
137
137
|
}
|
|
138
|
-
return
|
|
138
|
+
return wrapped
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
function wrapCommand (command, operation, name) {
|
|
@@ -145,7 +145,7 @@ function wrapCommand (command, operation, name) {
|
|
|
145
145
|
}
|
|
146
146
|
return instrument(operation, command, this, arguments, this, ns, ops, { name })
|
|
147
147
|
}
|
|
148
|
-
return
|
|
148
|
+
return wrapped
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
function instrument (operation, command, ctx, args, server, ns, ops, options = {}) {
|
|
@@ -164,7 +164,7 @@ function instrument (operation, command, ctx, args, server, ns, ops, options = {
|
|
|
164
164
|
return asyncResource.runInAsyncScope(() => {
|
|
165
165
|
startCh.publish({ ns, ops, options: serverInfo, name })
|
|
166
166
|
|
|
167
|
-
args[index] = asyncResource.bind(function (err, res) {
|
|
167
|
+
args[index] = shimmer.wrapFunction(callback, callback => asyncResource.bind(function (err, res) {
|
|
168
168
|
if (err) {
|
|
169
169
|
errorCh.publish(err)
|
|
170
170
|
}
|
|
@@ -174,7 +174,7 @@ function instrument (operation, command, ctx, args, server, ns, ops, options = {
|
|
|
174
174
|
if (callback) {
|
|
175
175
|
return callback.apply(this, arguments)
|
|
176
176
|
}
|
|
177
|
-
})
|
|
177
|
+
}))
|
|
178
178
|
|
|
179
179
|
try {
|
|
180
180
|
return command.apply(ctx, args)
|
|
@@ -128,22 +128,21 @@ addHook({
|
|
|
128
128
|
const resolve = arguments[0]
|
|
129
129
|
const reject = arguments[1]
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
arguments[0] = function wrappedResolve () {
|
|
131
|
+
arguments[0] = shimmer.wrapFunction(resolve, resolve => function wrappedResolve () {
|
|
133
132
|
finish()
|
|
134
133
|
|
|
135
134
|
if (resolve) {
|
|
136
135
|
return resolve.apply(this, arguments)
|
|
137
136
|
}
|
|
138
|
-
}
|
|
137
|
+
})
|
|
139
138
|
|
|
140
|
-
arguments[1] = function wrappedReject () {
|
|
139
|
+
arguments[1] = shimmer.wrapFunction(reject, reject => function wrappedReject () {
|
|
141
140
|
finish()
|
|
142
141
|
|
|
143
142
|
if (reject) {
|
|
144
143
|
return reject.apply(this, arguments)
|
|
145
144
|
}
|
|
146
|
-
}
|
|
145
|
+
})
|
|
147
146
|
|
|
148
147
|
return originalThen.apply(this, arguments)
|
|
149
148
|
}
|
|
@@ -169,7 +168,7 @@ addHook({
|
|
|
169
168
|
versions: ['6', '>=7'],
|
|
170
169
|
file: 'lib/helpers/query/sanitizeFilter.js'
|
|
171
170
|
}, sanitizeFilter => {
|
|
172
|
-
return shimmer.
|
|
171
|
+
return shimmer.wrapFunction(sanitizeFilter, sanitizeFilter => function wrappedSanitizeFilter () {
|
|
173
172
|
const sanitizedObject = sanitizeFilter.apply(this, arguments)
|
|
174
173
|
|
|
175
174
|
if (sanitizeFilterFinishCh.hasSubscribers) {
|
|
@@ -37,14 +37,14 @@ addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connect
|
|
|
37
37
|
|
|
38
38
|
if (res._callback) {
|
|
39
39
|
const cb = callbackResource.bind(res._callback)
|
|
40
|
-
res._callback = asyncResource.bind(function (error, result) {
|
|
40
|
+
res._callback = shimmer.wrapFunction(cb, cb => asyncResource.bind(function (error, result) {
|
|
41
41
|
if (error) {
|
|
42
42
|
errorCh.publish(error)
|
|
43
43
|
}
|
|
44
44
|
finishCh.publish(result)
|
|
45
45
|
|
|
46
46
|
return cb.apply(this, arguments)
|
|
47
|
-
})
|
|
47
|
+
}))
|
|
48
48
|
} else {
|
|
49
49
|
const cb = asyncResource.bind(function () {
|
|
50
50
|
finishCh.publish(undefined)
|
|
@@ -92,7 +92,7 @@ addHook({ name: 'mysql', file: 'lib/Pool.js', versions: ['>=2'] }, Pool => {
|
|
|
92
92
|
|
|
93
93
|
const cb = arguments[arguments.length - 1]
|
|
94
94
|
if (typeof cb === 'function') {
|
|
95
|
-
arguments[arguments.length - 1] = shimmer.
|
|
95
|
+
arguments[arguments.length - 1] = shimmer.wrapFunction(cb, cb => function () {
|
|
96
96
|
finish()
|
|
97
97
|
return cb.apply(this, arguments)
|
|
98
98
|
})
|
|
@@ -31,19 +31,19 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
|
|
|
31
31
|
return Connection
|
|
32
32
|
|
|
33
33
|
function bindExecute (cmd, execute, asyncResource) {
|
|
34
|
-
return asyncResource.bind(function executeWithTrace (packet, connection) {
|
|
34
|
+
return shimmer.wrapFunction(execute, execute => asyncResource.bind(function executeWithTrace (packet, connection) {
|
|
35
35
|
if (this.onResult) {
|
|
36
36
|
this.onResult = asyncResource.bind(this.onResult)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
return execute.apply(this, arguments)
|
|
40
|
-
}, cmd)
|
|
40
|
+
}, cmd))
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
function wrapExecute (cmd, execute, asyncResource, config) {
|
|
44
44
|
const callbackResource = new AsyncResource('bound-anonymous-fn')
|
|
45
45
|
|
|
46
|
-
return asyncResource.bind(function executeWithTrace (packet, connection) {
|
|
46
|
+
return shimmer.wrapFunction(execute, execute => asyncResource.bind(function executeWithTrace (packet, connection) {
|
|
47
47
|
const sql = cmd.statement ? cmd.statement.query : cmd.sql
|
|
48
48
|
const payload = { sql, conf: config }
|
|
49
49
|
startCh.publish(payload)
|
|
@@ -57,13 +57,13 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
|
|
|
57
57
|
if (this.onResult) {
|
|
58
58
|
const onResult = callbackResource.bind(this.onResult)
|
|
59
59
|
|
|
60
|
-
this.onResult = asyncResource.bind(function (error) {
|
|
60
|
+
this.onResult = shimmer.wrapFunction(onResult, onResult => asyncResource.bind(function (error) {
|
|
61
61
|
if (error) {
|
|
62
62
|
errorCh.publish(error)
|
|
63
63
|
}
|
|
64
64
|
finishCh.publish(undefined)
|
|
65
65
|
onResult.apply(this, arguments)
|
|
66
|
-
}, 'bound-anonymous-fn', this)
|
|
66
|
+
}, 'bound-anonymous-fn', this))
|
|
67
67
|
} else {
|
|
68
68
|
this.on('error', asyncResource.bind(error => errorCh.publish(error)))
|
|
69
69
|
this.on('end', asyncResource.bind(() => finishCh.publish(undefined)))
|
|
@@ -76,6 +76,6 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
|
|
|
76
76
|
} catch (err) {
|
|
77
77
|
errorCh.publish(err)
|
|
78
78
|
}
|
|
79
|
-
}, cmd)
|
|
79
|
+
}, cmd))
|
|
80
80
|
}
|
|
81
81
|
})
|