dd-trace 5.18.0 → 5.20.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 -2
- package/ext/formats.d.ts +1 -0
- package/ext/formats.js +2 -1
- package/index.d.ts +61 -39
- package/init.js +3 -15
- package/package.json +9 -12
- package/packages/datadog-instrumentations/src/child_process.js +2 -2
- package/packages/datadog-instrumentations/src/fs.js +1 -1
- package/packages/datadog-instrumentations/src/hapi.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +13 -11
- package/packages/datadog-instrumentations/src/http/client.js +8 -2
- package/packages/datadog-instrumentations/src/http/server.js +50 -13
- package/packages/datadog-instrumentations/src/jest.js +17 -2
- package/packages/datadog-instrumentations/src/kafkajs.js +1 -1
- package/packages/datadog-instrumentations/src/ldapjs.js +2 -2
- package/packages/datadog-instrumentations/src/mocha/main.js +21 -8
- package/packages/datadog-instrumentations/src/mquery.js +2 -2
- package/packages/datadog-instrumentations/src/next.js +1 -1
- package/packages/datadog-instrumentations/src/pg.js +2 -2
- package/packages/datadog-instrumentations/src/playwright.js +46 -32
- package/packages/datadog-instrumentations/src/process.js +29 -0
- package/packages/datadog-instrumentations/src/restify.js +1 -1
- package/packages/datadog-instrumentations/src/vitest.js +98 -28
- package/packages/datadog-plugin-aws-sdk/src/base.js +16 -2
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.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 +3 -3
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -4
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +114 -48
- package/packages/datadog-plugin-cypress/src/plugin.js +4 -3
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +7 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -1
- package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/index.js +5 -5
- package/packages/datadog-plugin-playwright/src/index.js +4 -1
- package/packages/datadog-plugin-sharedb/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +19 -7
- package/packages/dd-trace/src/analytics_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/blocking.js +10 -1
- package/packages/dd-trace/src/appsec/channels.js +4 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +16 -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 +2 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +11 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/code-injection-sensitive-analyzer.js +25 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +3 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +15 -10
- package/packages/dd-trace/src/appsec/passport.js +1 -1
- package/packages/dd-trace/src/appsec/rasp.js +121 -7
- package/packages/dd-trace/src/appsec/recommended.json +220 -2
- package/packages/dd-trace/src/appsec/reporter.js +0 -4
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +1 -1
- package/packages/dd-trace/src/config.js +68 -66
- package/packages/dd-trace/src/data_streams.js +44 -0
- package/packages/dd-trace/src/datastreams/pathway.js +4 -2
- package/packages/dd-trace/src/datastreams/processor.js +1 -1
- package/packages/dd-trace/src/log/index.js +32 -0
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +6 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +43 -0
- package/packages/dd-trace/src/opentracing/tracer.js +10 -6
- package/packages/dd-trace/src/plugins/ci_plugin.js +9 -2
- package/packages/dd-trace/src/plugins/plugin.js +12 -1
- package/packages/dd-trace/src/proxy.js +1 -0
- package/packages/dd-trace/src/tracer.js +2 -0
|
@@ -35,7 +35,7 @@ function wrapQuery (query) {
|
|
|
35
35
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
36
36
|
const processId = this.processID
|
|
37
37
|
|
|
38
|
-
const pgQuery = arguments[0] && typeof arguments[0] === 'object'
|
|
38
|
+
const pgQuery = arguments[0] !== null && typeof arguments[0] === 'object'
|
|
39
39
|
? arguments[0]
|
|
40
40
|
: { text: arguments[0] }
|
|
41
41
|
|
|
@@ -109,7 +109,7 @@ function wrapPoolQuery (query) {
|
|
|
109
109
|
|
|
110
110
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
111
111
|
|
|
112
|
-
const pgQuery = arguments[0] && typeof arguments[0] === 'object' ? arguments[0] : { text: arguments[0] }
|
|
112
|
+
const pgQuery = arguments[0] !== null && typeof arguments[0] === 'object' ? arguments[0] : { text: arguments[0] }
|
|
113
113
|
|
|
114
114
|
return asyncResource.runInAsyncScope(() => {
|
|
115
115
|
startPoolQueryCh.publish({
|
|
@@ -2,7 +2,7 @@ const semver = require('semver')
|
|
|
2
2
|
|
|
3
3
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
4
4
|
const shimmer = require('../../datadog-shimmer')
|
|
5
|
-
const { parseAnnotations, getTestSuitePath } = require('../../dd-trace/src/plugins/util/test')
|
|
5
|
+
const { parseAnnotations, getTestSuitePath, NUM_FAILED_TEST_RETRIES } = require('../../dd-trace/src/plugins/util/test')
|
|
6
6
|
const log = require('../../dd-trace/src/log')
|
|
7
7
|
|
|
8
8
|
const testStartCh = channel('ci:playwright:test:start')
|
|
@@ -21,6 +21,7 @@ const testToAr = new WeakMap()
|
|
|
21
21
|
const testSuiteToAr = new Map()
|
|
22
22
|
const testSuiteToTestStatuses = new Map()
|
|
23
23
|
const testSuiteToErrors = new Map()
|
|
24
|
+
const testSessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
24
25
|
|
|
25
26
|
let applyRepeatEachIndex = null
|
|
26
27
|
|
|
@@ -35,6 +36,7 @@ const STATUS_TO_TEST_STATUS = {
|
|
|
35
36
|
|
|
36
37
|
let remainingTestsByFile = {}
|
|
37
38
|
let isEarlyFlakeDetectionEnabled = false
|
|
39
|
+
let isFlakyTestRetriesEnabled = false
|
|
38
40
|
let earlyFlakeDetectionNumRetries = 0
|
|
39
41
|
let knownTests = {}
|
|
40
42
|
let rootDir = ''
|
|
@@ -196,6 +198,31 @@ function getTestSuiteError (testSuiteAbsolutePath) {
|
|
|
196
198
|
return new Error(`${errors.length} errors in this test suite:\n${errors.map(e => e.message).join('\n------\n')}`)
|
|
197
199
|
}
|
|
198
200
|
|
|
201
|
+
function getTestByTestId (dispatcher, testId) {
|
|
202
|
+
if (dispatcher._testById) {
|
|
203
|
+
return dispatcher._testById.get(testId)?.test
|
|
204
|
+
}
|
|
205
|
+
const allTests = dispatcher._allTests || dispatcher._ddAllTests
|
|
206
|
+
if (allTests) {
|
|
207
|
+
return allTests.find(({ id }) => id === testId)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function getChannelPromise (channelToPublishTo) {
|
|
212
|
+
return new Promise(resolve => {
|
|
213
|
+
testSessionAsyncResource.runInAsyncScope(() => {
|
|
214
|
+
channelToPublishTo.publish({ onDone: resolve })
|
|
215
|
+
})
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
// eslint-disable-next-line
|
|
219
|
+
// Inspired by https://github.com/microsoft/playwright/blob/2b77ed4d7aafa85a600caa0b0d101b72c8437eeb/packages/playwright/src/reporters/base.ts#L293
|
|
220
|
+
// We can't use test.outcome() directly because it's set on follow up handlers:
|
|
221
|
+
// our `testEndHandler` is called before the outcome is set.
|
|
222
|
+
function testWillRetry (test, testStatus) {
|
|
223
|
+
return testStatus === 'fail' && test.results.length <= test.retries
|
|
224
|
+
}
|
|
225
|
+
|
|
199
226
|
function testBeginHandler (test, browserName) {
|
|
200
227
|
const {
|
|
201
228
|
_requireFile: testSuiteAbsolutePath,
|
|
@@ -250,6 +277,7 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout) {
|
|
|
250
277
|
testFinishCh.publish({
|
|
251
278
|
testStatus,
|
|
252
279
|
steps: testResult?.steps || [],
|
|
280
|
+
isRetry: testResult?.retry > 0,
|
|
253
281
|
error,
|
|
254
282
|
extraTags: annotationTags,
|
|
255
283
|
isNew: test._ddIsNew,
|
|
@@ -267,8 +295,10 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout) {
|
|
|
267
295
|
addErrorToTestSuite(testSuiteAbsolutePath, error)
|
|
268
296
|
}
|
|
269
297
|
|
|
270
|
-
|
|
271
|
-
|
|
298
|
+
if (!testWillRetry(test, testStatus)) {
|
|
299
|
+
remainingTestsByFile[testSuiteAbsolutePath] = remainingTestsByFile[testSuiteAbsolutePath]
|
|
300
|
+
.filter(currentTest => currentTest !== test)
|
|
301
|
+
}
|
|
272
302
|
|
|
273
303
|
// Last test, we finish the suite
|
|
274
304
|
if (!remainingTestsByFile[testSuiteAbsolutePath].length) {
|
|
@@ -335,16 +365,6 @@ function dispatcherHook (dispatcherExport) {
|
|
|
335
365
|
return dispatcherExport
|
|
336
366
|
}
|
|
337
367
|
|
|
338
|
-
function getTestByTestId (dispatcher, testId) {
|
|
339
|
-
if (dispatcher._testById) {
|
|
340
|
-
return dispatcher._testById.get(testId)?.test
|
|
341
|
-
}
|
|
342
|
-
const allTests = dispatcher._allTests || dispatcher._ddAllTests
|
|
343
|
-
if (allTests) {
|
|
344
|
-
return allTests.find(({ id }) => id === testId)
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
368
|
function dispatcherHookNew (dispatcherExport, runWrapper) {
|
|
349
369
|
shimmer.wrap(dispatcherExport.Dispatcher.prototype, 'run', runWrapper)
|
|
350
370
|
shimmer.wrap(dispatcherExport.Dispatcher.prototype, '_createWorker', createWorker => function () {
|
|
@@ -373,8 +393,6 @@ function runnerHook (runnerExport, playwrightVersion) {
|
|
|
373
393
|
shimmer.wrap(runnerExport.Runner.prototype, 'runAllTests', runAllTests => async function () {
|
|
374
394
|
let onDone
|
|
375
395
|
|
|
376
|
-
const testSessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
377
|
-
|
|
378
396
|
rootDir = getRootDir(this)
|
|
379
397
|
|
|
380
398
|
const processArgv = process.argv.slice(2).join(' ')
|
|
@@ -383,46 +401,42 @@ function runnerHook (runnerExport, playwrightVersion) {
|
|
|
383
401
|
testSessionStartCh.publish({ command, frameworkVersion: playwrightVersion, rootDir })
|
|
384
402
|
})
|
|
385
403
|
|
|
386
|
-
const configurationPromise = new Promise((resolve) => {
|
|
387
|
-
onDone = resolve
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
testSessionAsyncResource.runInAsyncScope(() => {
|
|
391
|
-
libraryConfigurationCh.publish({ onDone })
|
|
392
|
-
})
|
|
393
|
-
|
|
394
404
|
try {
|
|
395
|
-
const { err, libraryConfig } = await
|
|
405
|
+
const { err, libraryConfig } = await getChannelPromise(libraryConfigurationCh)
|
|
396
406
|
if (!err) {
|
|
397
407
|
isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
398
408
|
earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
|
|
409
|
+
isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
|
|
399
410
|
}
|
|
400
411
|
} catch (e) {
|
|
412
|
+
isEarlyFlakeDetectionEnabled = false
|
|
401
413
|
log.error(e)
|
|
402
414
|
}
|
|
403
415
|
|
|
404
416
|
if (isEarlyFlakeDetectionEnabled && semver.gte(playwrightVersion, MINIMUM_SUPPORTED_VERSION_EFD)) {
|
|
405
|
-
const knownTestsPromise = new Promise((resolve) => {
|
|
406
|
-
onDone = resolve
|
|
407
|
-
})
|
|
408
|
-
testSessionAsyncResource.runInAsyncScope(() => {
|
|
409
|
-
knownTestsCh.publish({ onDone })
|
|
410
|
-
})
|
|
411
|
-
|
|
412
417
|
try {
|
|
413
|
-
const { err, knownTests: receivedKnownTests } = await
|
|
418
|
+
const { err, knownTests: receivedKnownTests } = await getChannelPromise(knownTestsCh)
|
|
414
419
|
if (!err) {
|
|
415
420
|
knownTests = receivedKnownTests
|
|
416
421
|
} else {
|
|
417
422
|
isEarlyFlakeDetectionEnabled = false
|
|
418
423
|
}
|
|
419
424
|
} catch (err) {
|
|
425
|
+
isEarlyFlakeDetectionEnabled = false
|
|
420
426
|
log.error(err)
|
|
421
427
|
}
|
|
422
428
|
}
|
|
423
429
|
|
|
424
430
|
const projects = getProjectsFromRunner(this)
|
|
425
431
|
|
|
432
|
+
if (isFlakyTestRetriesEnabled) {
|
|
433
|
+
projects.forEach(project => {
|
|
434
|
+
if (project.retries === 0) { // Only if it hasn't been set by the user
|
|
435
|
+
project.retries = NUM_FAILED_TEST_RETRIES
|
|
436
|
+
}
|
|
437
|
+
})
|
|
438
|
+
}
|
|
439
|
+
|
|
426
440
|
const runAllTestsReturn = await runAllTests.apply(this, arguments)
|
|
427
441
|
|
|
428
442
|
Object.values(remainingTestsByFile).forEach(tests => {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { channel } = require('dc-polyfill')
|
|
5
|
+
|
|
6
|
+
const startSetUncaughtExceptionCaptureCallback = channel('datadog:process:setUncaughtExceptionCaptureCallback:start')
|
|
7
|
+
|
|
8
|
+
if (process.setUncaughtExceptionCaptureCallback) {
|
|
9
|
+
let currentCallback
|
|
10
|
+
|
|
11
|
+
shimmer.wrap(process, 'setUncaughtExceptionCaptureCallback',
|
|
12
|
+
function wrapSetUncaughtExceptionCaptureCallback (originalSetUncaughtExceptionCaptureCallback) {
|
|
13
|
+
return function setUncaughtExceptionCaptureCallback (newCallback) {
|
|
14
|
+
if (startSetUncaughtExceptionCaptureCallback.hasSubscribers) {
|
|
15
|
+
const abortController = new AbortController()
|
|
16
|
+
startSetUncaughtExceptionCaptureCallback.publish({ newCallback, currentCallback, abortController })
|
|
17
|
+
if (abortController.signal.aborted) {
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const result = originalSetUncaughtExceptionCaptureCallback.apply(this, arguments)
|
|
23
|
+
|
|
24
|
+
currentCallback = newCallback
|
|
25
|
+
|
|
26
|
+
return result
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
@@ -51,7 +51,7 @@ function wrapFn (fn) {
|
|
|
51
51
|
|
|
52
52
|
try {
|
|
53
53
|
const result = fn.apply(this, arguments)
|
|
54
|
-
if (result && typeof result === 'object' && typeof result.then === 'function') {
|
|
54
|
+
if (result !== null && typeof result === 'object' && typeof result.then === 'function') {
|
|
55
55
|
return result.then(function () {
|
|
56
56
|
nextChannel.publish({ req })
|
|
57
57
|
finishChannel.publish({ req })
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
2
2
|
const shimmer = require('../../datadog-shimmer')
|
|
3
|
+
const { NUM_FAILED_TEST_RETRIES } = require('../../dd-trace/src/plugins/util/test')
|
|
3
4
|
|
|
4
5
|
// test hooks
|
|
5
6
|
const testStartCh = channel('ci:vitest:test:start')
|
|
@@ -16,6 +17,7 @@ const testSuiteErrorCh = channel('ci:vitest:test-suite:error')
|
|
|
16
17
|
// test session hooks
|
|
17
18
|
const testSessionStartCh = channel('ci:vitest:session:start')
|
|
18
19
|
const testSessionFinishCh = channel('ci:vitest:session:finish')
|
|
20
|
+
const libraryConfigurationCh = channel('ci:vitest:library-configuration')
|
|
19
21
|
|
|
20
22
|
const taskToAsync = new WeakMap()
|
|
21
23
|
|
|
@@ -30,6 +32,18 @@ function isReporterPackageNew (vitestPackage) {
|
|
|
30
32
|
return vitestPackage.e?.name === 'BaseSequencer'
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
function isReporterPackageNewest (vitestPackage) {
|
|
36
|
+
return vitestPackage.h?.name === 'BaseSequencer'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getChannelPromise (channelToPublishTo) {
|
|
40
|
+
return new Promise(resolve => {
|
|
41
|
+
sessionAsyncResource.runInAsyncScope(() => {
|
|
42
|
+
channelToPublishTo.publish({ onDone: resolve })
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
33
47
|
function getSessionStatus (state) {
|
|
34
48
|
if (state.getCountOfFailedTests() > 0) {
|
|
35
49
|
return 'fail'
|
|
@@ -90,6 +104,23 @@ function getSortWrapper (sort) {
|
|
|
90
104
|
if (!testSessionFinishCh.hasSubscribers) {
|
|
91
105
|
return sort.apply(this, arguments)
|
|
92
106
|
}
|
|
107
|
+
// There isn't any other async function that we seem to be able to hook into
|
|
108
|
+
// So we will use the sort from BaseSequencer. This means that a custom sequencer
|
|
109
|
+
// will not work. This will be a known limitation.
|
|
110
|
+
let isFlakyTestRetriesEnabled = false
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const { err, libraryConfig } = await getChannelPromise(libraryConfigurationCh)
|
|
114
|
+
if (!err) {
|
|
115
|
+
isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
|
|
116
|
+
}
|
|
117
|
+
} catch (e) {
|
|
118
|
+
isFlakyTestRetriesEnabled = false
|
|
119
|
+
}
|
|
120
|
+
if (isFlakyTestRetriesEnabled && !this.ctx.config.retry) {
|
|
121
|
+
this.ctx.config.retry = NUM_FAILED_TEST_RETRIES
|
|
122
|
+
}
|
|
123
|
+
|
|
93
124
|
shimmer.wrap(this.ctx, 'exit', exit => async function () {
|
|
94
125
|
let onFinish
|
|
95
126
|
|
|
@@ -119,6 +150,21 @@ function getSortWrapper (sort) {
|
|
|
119
150
|
}
|
|
120
151
|
}
|
|
121
152
|
|
|
153
|
+
function getCreateCliWrapper (vitestPackage, frameworkVersion) {
|
|
154
|
+
shimmer.wrap(vitestPackage, 'c', oldCreateCli => function () {
|
|
155
|
+
if (!testSessionStartCh.hasSubscribers) {
|
|
156
|
+
return oldCreateCli.apply(this, arguments)
|
|
157
|
+
}
|
|
158
|
+
sessionAsyncResource.runInAsyncScope(() => {
|
|
159
|
+
const processArgv = process.argv.slice(2).join(' ')
|
|
160
|
+
testSessionStartCh.publish({ command: `vitest ${processArgv}`, frameworkVersion })
|
|
161
|
+
})
|
|
162
|
+
return oldCreateCli.apply(this, arguments)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
return vitestPackage
|
|
166
|
+
}
|
|
167
|
+
|
|
122
168
|
addHook({
|
|
123
169
|
name: 'vitest',
|
|
124
170
|
versions: ['>=1.6.0'],
|
|
@@ -126,15 +172,31 @@ addHook({
|
|
|
126
172
|
}, (vitestPackage) => {
|
|
127
173
|
const { VitestTestRunner } = vitestPackage
|
|
128
174
|
// test start (only tests that are not marked as skip or todo)
|
|
129
|
-
shimmer.wrap(VitestTestRunner.prototype, 'onBeforeTryTask', onBeforeTryTask => async function (task) {
|
|
175
|
+
shimmer.wrap(VitestTestRunner.prototype, 'onBeforeTryTask', onBeforeTryTask => async function (task, retryInfo) {
|
|
130
176
|
if (!testStartCh.hasSubscribers) {
|
|
131
177
|
return onBeforeTryTask.apply(this, arguments)
|
|
132
178
|
}
|
|
179
|
+
const { retry: numAttempt } = retryInfo
|
|
180
|
+
// We finish the previous test here because we know it has failed already
|
|
181
|
+
if (numAttempt > 0) {
|
|
182
|
+
const asyncResource = taskToAsync.get(task)
|
|
183
|
+
const testError = task.result?.errors?.[0]
|
|
184
|
+
if (asyncResource) {
|
|
185
|
+
asyncResource.runInAsyncScope(() => {
|
|
186
|
+
testErrorCh.publish({ error: testError })
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
133
191
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
134
192
|
taskToAsync.set(task, asyncResource)
|
|
135
193
|
|
|
136
194
|
asyncResource.runInAsyncScope(() => {
|
|
137
|
-
testStartCh.publish({
|
|
195
|
+
testStartCh.publish({
|
|
196
|
+
testName: getTestName(task),
|
|
197
|
+
testSuiteAbsolutePath: task.file.filepath,
|
|
198
|
+
isRetry: numAttempt > 0
|
|
199
|
+
})
|
|
138
200
|
})
|
|
139
201
|
return onBeforeTryTask.apply(this, arguments)
|
|
140
202
|
})
|
|
@@ -163,12 +225,25 @@ addHook({
|
|
|
163
225
|
return vitestPackage
|
|
164
226
|
})
|
|
165
227
|
|
|
228
|
+
// There are multiple index* files across different versions of vitest,
|
|
229
|
+
// so we check for the existence of BaseSequencer to determine if we are in the right file
|
|
166
230
|
addHook({
|
|
167
231
|
name: 'vitest',
|
|
168
|
-
versions: ['>=2.0.0'],
|
|
232
|
+
versions: ['>=1.6.0 <2.0.0'],
|
|
233
|
+
filePattern: 'dist/vendor/index.*'
|
|
234
|
+
}, (vitestPackage) => {
|
|
235
|
+
if (isReporterPackage(vitestPackage)) {
|
|
236
|
+
shimmer.wrap(vitestPackage.B.prototype, 'sort', getSortWrapper)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return vitestPackage
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
addHook({
|
|
243
|
+
name: 'vitest',
|
|
244
|
+
versions: ['>=2.0.0 <2.0.5'],
|
|
169
245
|
filePattern: 'dist/vendor/index.*'
|
|
170
246
|
}, (vitestPackage) => {
|
|
171
|
-
// there are multiple index* files so we have to check the exported values
|
|
172
247
|
if (isReporterPackageNew(vitestPackage)) {
|
|
173
248
|
shimmer.wrap(vitestPackage.e.prototype, 'sort', getSortWrapper)
|
|
174
249
|
}
|
|
@@ -178,12 +253,11 @@ addHook({
|
|
|
178
253
|
|
|
179
254
|
addHook({
|
|
180
255
|
name: 'vitest',
|
|
181
|
-
versions: ['>=
|
|
182
|
-
filePattern: 'dist/
|
|
256
|
+
versions: ['>=2.0.5'],
|
|
257
|
+
filePattern: 'dist/chunks/index.*'
|
|
183
258
|
}, (vitestPackage) => {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
shimmer.wrap(vitestPackage.B.prototype, 'sort', getSortWrapper)
|
|
259
|
+
if (isReporterPackageNewest(vitestPackage)) {
|
|
260
|
+
shimmer.wrap(vitestPackage.h.prototype, 'sort', getSortWrapper)
|
|
187
261
|
}
|
|
188
262
|
|
|
189
263
|
return vitestPackage
|
|
@@ -192,22 +266,15 @@ addHook({
|
|
|
192
266
|
// Can't specify file because compiled vitest includes hashes in their files
|
|
193
267
|
addHook({
|
|
194
268
|
name: 'vitest',
|
|
195
|
-
versions: ['>=1.6.0'],
|
|
269
|
+
versions: ['>=1.6.0 <2.0.5'],
|
|
196
270
|
filePattern: 'dist/vendor/cac.*'
|
|
197
|
-
},
|
|
198
|
-
shimmer.wrap(vitestPackage, 'c', oldCreateCli => function () {
|
|
199
|
-
if (!testSessionStartCh.hasSubscribers) {
|
|
200
|
-
return oldCreateCli.apply(this, arguments)
|
|
201
|
-
}
|
|
202
|
-
sessionAsyncResource.runInAsyncScope(() => {
|
|
203
|
-
const processArgv = process.argv.slice(2).join(' ')
|
|
204
|
-
testSessionStartCh.publish({ command: `vitest ${processArgv}`, frameworkVersion })
|
|
205
|
-
})
|
|
206
|
-
return oldCreateCli.apply(this, arguments)
|
|
207
|
-
})
|
|
271
|
+
}, getCreateCliWrapper)
|
|
208
272
|
|
|
209
|
-
|
|
210
|
-
|
|
273
|
+
addHook({
|
|
274
|
+
name: 'vitest',
|
|
275
|
+
versions: ['>=2.0.5'],
|
|
276
|
+
filePattern: 'dist/chunks/cac.*'
|
|
277
|
+
}, getCreateCliWrapper)
|
|
211
278
|
|
|
212
279
|
// test suite start and finish
|
|
213
280
|
// only relevant for workers
|
|
@@ -215,7 +282,7 @@ addHook({
|
|
|
215
282
|
name: '@vitest/runner',
|
|
216
283
|
versions: ['>=1.6.0'],
|
|
217
284
|
file: 'dist/index.js'
|
|
218
|
-
}, vitestPackage => {
|
|
285
|
+
}, (vitestPackage, frameworkVersion) => {
|
|
219
286
|
shimmer.wrap(vitestPackage, 'startTests', startTests => async function (testPath) {
|
|
220
287
|
let testSuiteError = null
|
|
221
288
|
if (!testSuiteStartCh.hasSubscribers) {
|
|
@@ -224,7 +291,7 @@ addHook({
|
|
|
224
291
|
|
|
225
292
|
const testSuiteAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
226
293
|
testSuiteAsyncResource.runInAsyncScope(() => {
|
|
227
|
-
testSuiteStartCh.publish(testPath[0])
|
|
294
|
+
testSuiteStartCh.publish({ testSuiteAbsolutePath: testPath[0], frameworkVersion })
|
|
228
295
|
})
|
|
229
296
|
const startTestsResponse = await startTests.apply(this, arguments)
|
|
230
297
|
|
|
@@ -235,6 +302,7 @@ addHook({
|
|
|
235
302
|
|
|
236
303
|
const testTasks = getTypeTasks(startTestsResponse[0].tasks)
|
|
237
304
|
|
|
305
|
+
// Only one test task per test, even if there are retries
|
|
238
306
|
testTasks.forEach(task => {
|
|
239
307
|
const testAsyncResource = taskToAsync.get(task)
|
|
240
308
|
const { result } = task
|
|
@@ -242,7 +310,7 @@ addHook({
|
|
|
242
310
|
if (result) {
|
|
243
311
|
const { state, duration, errors } = result
|
|
244
312
|
if (state === 'skip') { // programmatic skip
|
|
245
|
-
testSkipCh.publish({ testName: getTestName(task), testSuiteAbsolutePath: task.
|
|
313
|
+
testSkipCh.publish({ testName: getTestName(task), testSuiteAbsolutePath: task.file.filepath })
|
|
246
314
|
} else if (state === 'pass') {
|
|
247
315
|
if (testAsyncResource) {
|
|
248
316
|
testAsyncResource.runInAsyncScope(() => {
|
|
@@ -258,8 +326,10 @@ addHook({
|
|
|
258
326
|
}
|
|
259
327
|
|
|
260
328
|
if (testAsyncResource) {
|
|
329
|
+
const isRetry = task.result?.retryCount > 0
|
|
330
|
+
// `duration` is the duration of all the retries, so it can't be used if there are retries
|
|
261
331
|
testAsyncResource.runInAsyncScope(() => {
|
|
262
|
-
testErrorCh.publish({ duration, error: testError })
|
|
332
|
+
testErrorCh.publish({ duration: !isRetry ? duration : undefined, error: testError })
|
|
263
333
|
})
|
|
264
334
|
}
|
|
265
335
|
if (errors?.length) {
|
|
@@ -267,7 +337,7 @@ addHook({
|
|
|
267
337
|
}
|
|
268
338
|
}
|
|
269
339
|
} else { // test.skip or test.todo
|
|
270
|
-
testSkipCh.publish({ testName: getTestName(task), testSuiteAbsolutePath: task.
|
|
340
|
+
testSkipCh.publish({ testName: getTestName(task), testSuiteAbsolutePath: task.file.filepath })
|
|
271
341
|
}
|
|
272
342
|
})
|
|
273
343
|
|
|
@@ -4,6 +4,7 @@ const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
|
4
4
|
const ClientPlugin = require('../../dd-trace/src/plugins/client')
|
|
5
5
|
const { storage } = require('../../datadog-core')
|
|
6
6
|
const { isTrue } = require('../../dd-trace/src/util')
|
|
7
|
+
const coalesce = require('koalas')
|
|
7
8
|
|
|
8
9
|
class BaseAwsSdkPlugin extends ClientPlugin {
|
|
9
10
|
static get id () { return 'aws' }
|
|
@@ -73,7 +74,7 @@ class BaseAwsSdkPlugin extends ClientPlugin {
|
|
|
73
74
|
if (!cbExists && this.serviceIdentifier === 'sqs') {
|
|
74
75
|
const params = response.request.params
|
|
75
76
|
const operation = response.request.operation
|
|
76
|
-
this.responseExtractDSMContext(operation, params, response.data, span)
|
|
77
|
+
this.responseExtractDSMContext(operation, params, response.data ?? response, span)
|
|
77
78
|
}
|
|
78
79
|
this.addResponseTags(span, response)
|
|
79
80
|
this.finish(span, response, response.error)
|
|
@@ -163,9 +164,22 @@ function normalizeConfig (config, serviceIdentifier) {
|
|
|
163
164
|
break
|
|
164
165
|
}
|
|
165
166
|
|
|
167
|
+
// check if AWS batch propagation or AWS_[SERVICE] batch propagation is enabled via env variable
|
|
168
|
+
const serviceId = serviceIdentifier.toUpperCase()
|
|
169
|
+
const batchPropagationEnabled = isTrue(
|
|
170
|
+
coalesce(
|
|
171
|
+
specificConfig.batchPropagationEnabled,
|
|
172
|
+
process.env[`DD_TRACE_AWS_SDK_${serviceId}_BATCH_PROPAGATION_ENABLED`],
|
|
173
|
+
config.batchPropagationEnabled,
|
|
174
|
+
process.env.DD_TRACE_AWS_SDK_BATCH_PROPAGATION_ENABLED,
|
|
175
|
+
false
|
|
176
|
+
)
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
// Merge the specific config back into the main config
|
|
166
180
|
return Object.assign({}, config, specificConfig, {
|
|
167
181
|
splitByAwsService: config.splitByAwsService !== false,
|
|
168
|
-
batchPropagationEnabled
|
|
182
|
+
batchPropagationEnabled,
|
|
169
183
|
hooks
|
|
170
184
|
})
|
|
171
185
|
}
|
|
@@ -21,7 +21,7 @@ class DynamoDb extends BaseAwsSdkPlugin {
|
|
|
21
21
|
// batch operations have different format, collect table name for batch
|
|
22
22
|
// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#batchGetItem-property`
|
|
23
23
|
// dynamoDB batch TableName
|
|
24
|
-
if (params.RequestItems) {
|
|
24
|
+
if (params.RequestItems !== null) {
|
|
25
25
|
if (typeof params.RequestItems === 'object') {
|
|
26
26
|
if (Object.keys(params.RequestItems).length === 1) {
|
|
27
27
|
const tableName = Object.keys(params.RequestItems)[0]
|
|
@@ -157,8 +157,8 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
157
157
|
if (attributes.StringValue) {
|
|
158
158
|
const textMap = attributes.StringValue
|
|
159
159
|
return JSON.parse(textMap)
|
|
160
|
-
} else if (attributes.Type === 'Binary') {
|
|
161
|
-
const buffer = Buffer.from(attributes.Value, 'base64')
|
|
160
|
+
} else if (attributes.Type === 'Binary' || attributes.DataType === 'Binary') {
|
|
161
|
+
const buffer = Buffer.from(attributes.Value ?? attributes.BinaryValue, 'base64')
|
|
162
162
|
return JSON.parse(buffer)
|
|
163
163
|
}
|
|
164
164
|
} catch (e) {
|
|
@@ -222,7 +222,7 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
222
222
|
span,
|
|
223
223
|
params.Entries[i],
|
|
224
224
|
params.QueueUrl,
|
|
225
|
-
i === 0 || (this.config.
|
|
225
|
+
i === 0 || (this.config.batchPropagationEnabled)
|
|
226
226
|
)
|
|
227
227
|
}
|
|
228
228
|
break
|
|
@@ -47,7 +47,7 @@ class Stepfunctions extends BaseAwsSdkPlugin {
|
|
|
47
47
|
|
|
48
48
|
try {
|
|
49
49
|
const inputObj = JSON.parse(input)
|
|
50
|
-
if (inputObj && typeof inputObj === 'object') {
|
|
50
|
+
if (inputObj !== null && typeof inputObj === 'object') {
|
|
51
51
|
// We've parsed the input JSON string
|
|
52
52
|
inputObj._datadog = {}
|
|
53
53
|
this.tracer.inject(span, 'text_map', inputObj._datadog)
|
|
@@ -7,10 +7,10 @@ const PROCESS_DENYLIST = ['md5']
|
|
|
7
7
|
|
|
8
8
|
const VARNAMES_REGEX = /\$([\w\d_]*)(?:[^\w\d_]|$)/gmi
|
|
9
9
|
// eslint-disable-next-line max-len
|
|
10
|
-
const PARAM_PATTERN = '^-{0,2}(?:p(?:ass(?:w(?:or)?d)?)?|
|
|
10
|
+
const PARAM_PATTERN = '^-{0,2}(?:p(?:ass(?:w(?:or)?d)?)?|address|api[-_]?key|e?mail|secret(?:[-_]?key)?|a(?:ccess|uth)[-_]?token|mysql_pwd|credentials|(?:stripe)?token)$'
|
|
11
11
|
const regexParam = new RegExp(PARAM_PATTERN, 'i')
|
|
12
12
|
const ENV_PATTERN = '^(\\w+=\\w+;)*\\w+=\\w+;?$'
|
|
13
|
-
const
|
|
13
|
+
const envVarRegex = new RegExp(ENV_PATTERN)
|
|
14
14
|
const REDACTED = '?'
|
|
15
15
|
|
|
16
16
|
function extractVarNames (expression) {
|
|
@@ -61,7 +61,9 @@ function scrubChildProcessCmd (expression) {
|
|
|
61
61
|
for (let index = 0; index < expressionTokens.length; index++) {
|
|
62
62
|
const token = expressionTokens[index]
|
|
63
63
|
|
|
64
|
-
if (
|
|
64
|
+
if (token === null) {
|
|
65
|
+
continue
|
|
66
|
+
} else if (typeof token === 'object') {
|
|
65
67
|
if (token.pattern) {
|
|
66
68
|
result.push(token.pattern)
|
|
67
69
|
} else if (token.op) {
|
|
@@ -70,7 +72,7 @@ function scrubChildProcessCmd (expression) {
|
|
|
70
72
|
result.push(`#${token.comment}`)
|
|
71
73
|
}
|
|
72
74
|
} else if (!foundBinary) {
|
|
73
|
-
if (
|
|
75
|
+
if (envVarRegex.test(token)) {
|
|
74
76
|
const envSplit = token.split('=')
|
|
75
77
|
|
|
76
78
|
if (!ALLOWED_ENV_VARIABLES.includes(envSplit[0])) {
|