dd-trace 5.51.0 → 5.53.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 -6
- package/README.md +5 -0
- package/index.d.ts +88 -6
- package/package.json +3 -9
- package/packages/datadog-instrumentations/src/amqplib.js +8 -5
- package/packages/datadog-instrumentations/src/child_process.js +2 -1
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +406 -0
- package/packages/datadog-instrumentations/src/couchbase.js +2 -1
- package/packages/datadog-instrumentations/src/cucumber.js +43 -45
- package/packages/datadog-instrumentations/src/dns.js +16 -14
- package/packages/datadog-instrumentations/src/express.js +2 -6
- package/packages/datadog-instrumentations/src/fs.js +43 -51
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +17 -12
- package/packages/datadog-instrumentations/src/http/client.js +2 -1
- package/packages/datadog-instrumentations/src/iovalkey.js +51 -0
- package/packages/datadog-instrumentations/src/jest.js +53 -40
- package/packages/datadog-instrumentations/src/kafkajs.js +21 -8
- package/packages/datadog-instrumentations/src/mocha/main.js +33 -46
- package/packages/datadog-instrumentations/src/mocha/utils.js +76 -74
- package/packages/datadog-instrumentations/src/mysql2.js +3 -1
- package/packages/datadog-instrumentations/src/net.js +27 -29
- package/packages/datadog-instrumentations/src/next.js +6 -14
- package/packages/datadog-instrumentations/src/pg.js +15 -7
- package/packages/datadog-instrumentations/src/playwright.js +64 -67
- package/packages/datadog-instrumentations/src/url.js +9 -17
- package/packages/datadog-instrumentations/src/vitest.js +66 -72
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +11 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +11 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +19 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +11 -0
- package/packages/datadog-plugin-cucumber/src/index.js +32 -18
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +3 -0
- package/packages/datadog-plugin-dns/src/lookup.js +10 -5
- package/packages/datadog-plugin-dns/src/lookup_service.js +6 -2
- package/packages/datadog-plugin-dns/src/resolve.js +5 -2
- package/packages/datadog-plugin-dns/src/reverse.js +6 -2
- package/packages/datadog-plugin-fs/src/index.js +9 -2
- package/packages/datadog-plugin-iovalkey/src/index.js +18 -0
- package/packages/datadog-plugin-jest/src/index.js +17 -8
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -1
- package/packages/datadog-plugin-kafkajs/src/consumer.js +12 -21
- package/packages/datadog-plugin-kafkajs/src/producer.js +12 -5
- package/packages/datadog-plugin-kafkajs/src/utils.js +27 -0
- package/packages/datadog-plugin-langchain/src/index.js +0 -1
- package/packages/datadog-plugin-mocha/src/index.js +58 -35
- package/packages/datadog-plugin-net/src/ipc.js +6 -4
- package/packages/datadog-plugin-net/src/tcp.js +15 -9
- package/packages/datadog-plugin-pg/src/index.js +5 -1
- package/packages/datadog-plugin-playwright/src/index.js +29 -20
- package/packages/datadog-plugin-redis/src/index.js +8 -3
- package/packages/datadog-plugin-vitest/src/index.js +67 -44
- package/packages/datadog-shimmer/src/shimmer.js +164 -33
- package/packages/dd-trace/src/appsec/api_security_sampler.js +20 -12
- package/packages/dd-trace/src/appsec/graphql.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +14 -9
- package/packages/dd-trace/src/appsec/index.js +15 -12
- package/packages/dd-trace/src/appsec/rasp/index.js +4 -2
- package/packages/dd-trace/src/appsec/rasp/utils.js +11 -6
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
- package/packages/dd-trace/src/appsec/telemetry/index.js +1 -2
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +0 -9
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -6
- package/packages/dd-trace/src/baggage.js +36 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
- package/packages/dd-trace/src/config.js +14 -2
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +61 -7
- package/packages/dd-trace/src/debugger/devtools_client/index.js +10 -26
- package/packages/dd-trace/src/debugger/devtools_client/send.js +8 -7
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +15 -7
- package/packages/dd-trace/src/debugger/devtools_client/state.js +22 -2
- package/packages/dd-trace/src/dogstatsd.js +2 -0
- package/packages/dd-trace/src/exporters/common/docker.js +13 -31
- package/packages/dd-trace/src/guardrails/telemetry.js +2 -5
- package/packages/dd-trace/src/llmobs/tagger.js +3 -3
- package/packages/dd-trace/src/llmobs/writers/base.js +33 -12
- package/packages/dd-trace/src/noop/proxy.js +5 -0
- package/packages/dd-trace/src/opentelemetry/context_manager.js +2 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -9
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/index.js +4 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +9 -20
- package/packages/dd-trace/src/plugins/outbound.js +11 -3
- package/packages/dd-trace/src/plugins/tracing.js +8 -4
- package/packages/dd-trace/src/plugins/util/test.js +1 -1
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +15 -14
- package/packages/dd-trace/src/proxy.js +12 -4
- package/packages/dd-trace/src/serverless.js +0 -48
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/standalone/product.js +3 -5
|
@@ -70,7 +70,7 @@ function wrapRenderToHTML (renderToHTML) {
|
|
|
70
70
|
|
|
71
71
|
function wrapRenderErrorToHTML (renderErrorToHTML) {
|
|
72
72
|
return function (err, req, res, pathname, query) {
|
|
73
|
-
return instrument(req, res,
|
|
73
|
+
return instrument(req, res, () => renderErrorToHTML.apply(this, arguments), err)
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -82,7 +82,7 @@ function wrapRenderToResponse (renderToResponse) {
|
|
|
82
82
|
|
|
83
83
|
function wrapRenderErrorToResponse (renderErrorToResponse) {
|
|
84
84
|
return function (ctx, err) {
|
|
85
|
-
return instrument(ctx.req, ctx.res,
|
|
85
|
+
return instrument(ctx.req, ctx.res, () => renderErrorToResponse.apply(this, arguments), err)
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -121,12 +121,7 @@ function getRequestMeta (req, key) {
|
|
|
121
121
|
return typeof key === 'string' ? meta[key] : meta
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
function instrument (req, res,
|
|
125
|
-
if (typeof error === 'function') {
|
|
126
|
-
handler = error
|
|
127
|
-
error = null
|
|
128
|
-
}
|
|
129
|
-
|
|
124
|
+
function instrument (req, res, handler, error) {
|
|
130
125
|
req = req.originalRequest || req
|
|
131
126
|
res = res.originalResponse || res
|
|
132
127
|
|
|
@@ -216,13 +211,13 @@ addHook({
|
|
|
216
211
|
name: 'next',
|
|
217
212
|
versions: ['>=11.1'],
|
|
218
213
|
file: 'dist/server/serve-static.js'
|
|
219
|
-
}, serveStatic => shimmer.wrap(serveStatic, 'serveStatic', wrapServeStatic))
|
|
214
|
+
}, serveStatic => shimmer.wrap(serveStatic, 'serveStatic', wrapServeStatic, { replaceGetter: true }))
|
|
220
215
|
|
|
221
216
|
addHook({
|
|
222
217
|
name: 'next',
|
|
223
218
|
versions: ['>=10.2 <11.1'],
|
|
224
219
|
file: 'dist/next-server/server/serve-static.js'
|
|
225
|
-
}, serveStatic => shimmer.wrap(serveStatic, 'serveStatic', wrapServeStatic))
|
|
220
|
+
}, serveStatic => shimmer.wrap(serveStatic, 'serveStatic', wrapServeStatic, { replaceGetter: true }))
|
|
226
221
|
|
|
227
222
|
addHook({ name: 'next', versions: ['>=11.1'], file: 'dist/server/next-server.js' }, nextServer => {
|
|
228
223
|
const Server = nextServer.default
|
|
@@ -282,8 +277,7 @@ addHook({
|
|
|
282
277
|
versions: ['>=13'],
|
|
283
278
|
file: 'dist/server/web/spec-extension/request.js'
|
|
284
279
|
}, request => {
|
|
285
|
-
|
|
286
|
-
shimmer.wrap(nextUrlDescriptor, 'get', function (originalGet) {
|
|
280
|
+
shimmer.wrap(request.NextRequest.prototype, 'nextUrl', function (originalGet) {
|
|
287
281
|
return function wrappedGet () {
|
|
288
282
|
const nextUrl = originalGet.apply(this, arguments)
|
|
289
283
|
if (queryParsedChannel.hasSubscribers) {
|
|
@@ -300,8 +294,6 @@ addHook({
|
|
|
300
294
|
}
|
|
301
295
|
})
|
|
302
296
|
|
|
303
|
-
Object.defineProperty(request.NextRequest.prototype, 'nextUrl', nextUrlDescriptor)
|
|
304
|
-
|
|
305
297
|
shimmer.massWrap(request.NextRequest.prototype, ['text', 'json'], function (originalMethod) {
|
|
306
298
|
return async function wrappedJson () {
|
|
307
299
|
const body = await originalMethod.apply(this, arguments)
|
|
@@ -14,6 +14,8 @@ const errorCh = channel('apm:pg:query:error')
|
|
|
14
14
|
const startPoolQueryCh = channel('datadog:pg:pool:query:start')
|
|
15
15
|
const finishPoolQueryCh = channel('datadog:pg:pool:query:finish')
|
|
16
16
|
|
|
17
|
+
const { errorMonitor } = require('node:events')
|
|
18
|
+
|
|
17
19
|
addHook({ name: 'pg', versions: ['>=8.0.3'] }, pg => {
|
|
18
20
|
shimmer.wrap(pg.Client.prototype, 'query', query => wrapQuery(query))
|
|
19
21
|
shimmer.wrap(pg.Pool.prototype, 'query', query => wrapPoolQuery(query))
|
|
@@ -39,13 +41,15 @@ function wrapQuery (query) {
|
|
|
39
41
|
? arguments[0]
|
|
40
42
|
: { text: arguments[0] }
|
|
41
43
|
|
|
42
|
-
const
|
|
44
|
+
const textPropObj = pgQuery.cursor ?? pgQuery
|
|
45
|
+
const textProp = Object.getOwnPropertyDescriptor(textPropObj, 'text')
|
|
46
|
+
const stream = typeof textPropObj.read === 'function'
|
|
43
47
|
|
|
44
|
-
// Only alter `text` property if safe to do so.
|
|
48
|
+
// Only alter `text` property if safe to do so. Initially, it's a property, not a getter.
|
|
45
49
|
if (!textProp || textProp.configurable) {
|
|
46
|
-
const originalText =
|
|
50
|
+
const originalText = textPropObj.text
|
|
47
51
|
|
|
48
|
-
Object.defineProperty(
|
|
52
|
+
Object.defineProperty(textPropObj, 'text', {
|
|
49
53
|
get () {
|
|
50
54
|
return this?.__ddInjectableQuery || originalText
|
|
51
55
|
}
|
|
@@ -57,9 +61,10 @@ function wrapQuery (query) {
|
|
|
57
61
|
|
|
58
62
|
startCh.publish({
|
|
59
63
|
params: this.connectionParameters,
|
|
60
|
-
query:
|
|
64
|
+
query: textPropObj,
|
|
61
65
|
processId,
|
|
62
|
-
abortController
|
|
66
|
+
abortController,
|
|
67
|
+
stream
|
|
63
68
|
})
|
|
64
69
|
|
|
65
70
|
const finish = asyncResource.bind(function (error, res) {
|
|
@@ -124,9 +129,12 @@ function wrapQuery (query) {
|
|
|
124
129
|
}
|
|
125
130
|
} else if (newQuery.once) {
|
|
126
131
|
newQuery
|
|
127
|
-
.once(
|
|
132
|
+
.once(errorMonitor, finish)
|
|
128
133
|
.once('end', (res) => finish(null, res))
|
|
129
134
|
} else {
|
|
135
|
+
// TODO: This code is never reached in our tests.
|
|
136
|
+
// Internally, pg always uses callbacks or streams, even for promise based queries.
|
|
137
|
+
// Investigate if this code should just be removed.
|
|
130
138
|
newQuery.then((res) => finish(null, res), finish)
|
|
131
139
|
}
|
|
132
140
|
|
|
@@ -25,8 +25,8 @@ const testSuiteFinishCh = channel('ci:playwright:test-suite:finish')
|
|
|
25
25
|
const workerReportCh = channel('ci:playwright:worker:report')
|
|
26
26
|
const testPageGotoCh = channel('ci:playwright:test:page-goto')
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const testToCtx = new WeakMap()
|
|
29
|
+
const testSuiteToCtx = new Map()
|
|
30
30
|
const testSuiteToTestStatuses = new Map()
|
|
31
31
|
const testSuiteToErrors = new Map()
|
|
32
32
|
const testsToTestStatuses = new Map()
|
|
@@ -279,11 +279,9 @@ function testBeginHandler (test, browserName, isMainProcess) {
|
|
|
279
279
|
|
|
280
280
|
if (isNewTestSuite) {
|
|
281
281
|
startedSuites.push(testSuiteAbsolutePath)
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
testSuiteStartCh.publish(testSuiteAbsolutePath)
|
|
286
|
-
})
|
|
282
|
+
const testSuiteCtx = { testSuiteAbsolutePath }
|
|
283
|
+
testSuiteToCtx.set(testSuiteAbsolutePath, testSuiteCtx)
|
|
284
|
+
testSuiteStartCh.runStores(testSuiteCtx, () => { })
|
|
287
285
|
}
|
|
288
286
|
|
|
289
287
|
// We disable retries by default if attemptToFix is true
|
|
@@ -293,19 +291,17 @@ function testBeginHandler (test, browserName, isMainProcess) {
|
|
|
293
291
|
|
|
294
292
|
// this handles tests that do not go through the worker process (because they're skipped)
|
|
295
293
|
if (isMainProcess) {
|
|
296
|
-
const testAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
297
|
-
testToAr.set(test, testAsyncResource)
|
|
298
294
|
const testName = getTestFullname(test)
|
|
295
|
+
const testCtx = {
|
|
296
|
+
testName,
|
|
297
|
+
testSuiteAbsolutePath,
|
|
298
|
+
testSourceLine,
|
|
299
|
+
browserName,
|
|
300
|
+
isDisabled: test._ddIsDisabled
|
|
301
|
+
}
|
|
302
|
+
testToCtx.set(test, testCtx)
|
|
299
303
|
|
|
300
|
-
|
|
301
|
-
testStartCh.publish({
|
|
302
|
-
testName,
|
|
303
|
-
testSuiteAbsolutePath,
|
|
304
|
-
testSourceLine,
|
|
305
|
-
browserName,
|
|
306
|
-
isDisabled: test._ddIsDisabled
|
|
307
|
-
})
|
|
308
|
-
})
|
|
304
|
+
testStartCh.runStores(testCtx, () => { })
|
|
309
305
|
}
|
|
310
306
|
}
|
|
311
307
|
|
|
@@ -337,6 +333,9 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
|
|
|
337
333
|
}
|
|
338
334
|
|
|
339
335
|
if (testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
336
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
337
|
+
test._ddHasFailedAttemptToFixRetries = true
|
|
338
|
+
}
|
|
340
339
|
if (testStatuses.every(status => status === 'fail')) {
|
|
341
340
|
test._ddHasFailedAllRetries = true
|
|
342
341
|
} else if (testStatuses.every(status => status === 'pass')) {
|
|
@@ -347,27 +346,27 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
|
|
|
347
346
|
// this handles tests that do not go through the worker process (because they're skipped)
|
|
348
347
|
if (isMainProcess) {
|
|
349
348
|
const testResult = results[results.length - 1]
|
|
350
|
-
const
|
|
349
|
+
const testCtx = testToCtx.get(test)
|
|
351
350
|
const isAtrRetry = testResult?.retry > 0 &&
|
|
352
351
|
isFlakyTestRetriesEnabled &&
|
|
353
352
|
!test._ddIsAttemptToFix &&
|
|
354
353
|
!test._ddIsEfdRetry
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
354
|
+
testFinishCh.publish({
|
|
355
|
+
testStatus,
|
|
356
|
+
steps: testResult?.steps || [],
|
|
357
|
+
isRetry: testResult?.retry > 0,
|
|
358
|
+
error,
|
|
359
|
+
extraTags: annotationTags,
|
|
360
|
+
isNew: test._ddIsNew,
|
|
361
|
+
isAttemptToFix: test._ddIsAttemptToFix,
|
|
362
|
+
isAttemptToFixRetry: test._ddIsAttemptToFixRetry,
|
|
363
|
+
isQuarantined: test._ddIsQuarantined,
|
|
364
|
+
isEfdRetry: test._ddIsEfdRetry,
|
|
365
|
+
hasFailedAllRetries: test._ddHasFailedAllRetries,
|
|
366
|
+
hasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
|
|
367
|
+
hasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
|
|
368
|
+
isAtrRetry,
|
|
369
|
+
...testCtx.currentStore
|
|
371
370
|
})
|
|
372
371
|
}
|
|
373
372
|
|
|
@@ -397,10 +396,8 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
|
|
|
397
396
|
}
|
|
398
397
|
|
|
399
398
|
const suiteError = getTestSuiteError(testSuiteAbsolutePath)
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
testSuiteFinishCh.publish({ status: testSuiteStatus, error: suiteError })
|
|
403
|
-
})
|
|
399
|
+
const testSuiteCtx = testSuiteToCtx.get(testSuiteAbsolutePath)
|
|
400
|
+
testSuiteFinishCh.publish({ status: testSuiteStatus, error: suiteError, ...testSuiteCtx.currentStore })
|
|
404
401
|
}
|
|
405
402
|
}
|
|
406
403
|
|
|
@@ -492,6 +489,7 @@ function dispatcherHookNew (dispatcherExport, runWrapper) {
|
|
|
492
489
|
_ddIsEfdRetry: test._ddIsEfdRetry,
|
|
493
490
|
_ddHasFailedAllRetries: test._ddHasFailedAllRetries,
|
|
494
491
|
_ddHasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
|
|
492
|
+
_ddHasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
|
|
495
493
|
_ddIsAtrRetry: isAtrRetry
|
|
496
494
|
}
|
|
497
495
|
})
|
|
@@ -605,7 +603,7 @@ function runnerHook (runnerExport, playwrightVersion) {
|
|
|
605
603
|
totalAttemptToFixFailedTestCount += testStatuses.filter(status => status === 'fail').length
|
|
606
604
|
}
|
|
607
605
|
|
|
608
|
-
if (totalFailedTestCount === totalAttemptToFixFailedTestCount) {
|
|
606
|
+
if (totalFailedTestCount > 0 && totalFailedTestCount === totalAttemptToFixFailedTestCount) {
|
|
609
607
|
runAllTestsReturn = 'passed'
|
|
610
608
|
}
|
|
611
609
|
}
|
|
@@ -868,17 +866,16 @@ addHook({
|
|
|
868
866
|
// If test events are created in the worker process I need to stop creating it in the main process
|
|
869
867
|
// Probably yet another test worker exporter is needed in addition to the ones for mocha, jest and cucumber
|
|
870
868
|
// it's probably hard to tell that's a playwright worker though, as I don't think there is a specific env variable
|
|
871
|
-
const
|
|
869
|
+
const testCtx = {
|
|
870
|
+
testName,
|
|
871
|
+
testSuiteAbsolutePath,
|
|
872
|
+
testSourceLine,
|
|
873
|
+
browserName
|
|
874
|
+
}
|
|
875
|
+
testToCtx.set(test, testCtx)
|
|
872
876
|
// TODO - In the future we may need to implement a mechanism to send test properties
|
|
873
877
|
// to the worker process before _runTest is called
|
|
874
|
-
|
|
875
|
-
testStartCh.publish({
|
|
876
|
-
testName,
|
|
877
|
-
testSuiteAbsolutePath,
|
|
878
|
-
testSourceLine,
|
|
879
|
-
browserName
|
|
880
|
-
})
|
|
881
|
-
|
|
878
|
+
testStartCh.runStores(testCtx, () => {
|
|
882
879
|
let existAfterEachHook = false
|
|
883
880
|
|
|
884
881
|
// We try to find an existing afterEach hook with _ddHook to avoid adding a new one
|
|
@@ -971,24 +968,24 @@ addHook({
|
|
|
971
968
|
// Wait for the properties to be received
|
|
972
969
|
await ddPropertiesPromise
|
|
973
970
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
971
|
+
testFinishCh.publish({
|
|
972
|
+
testStatus: STATUS_TO_TEST_STATUS[status],
|
|
973
|
+
steps: steps.filter(step => step.testId === testId),
|
|
974
|
+
error,
|
|
975
|
+
extraTags: annotationTags,
|
|
976
|
+
isNew: test._ddIsNew,
|
|
977
|
+
isRetry: retry > 0,
|
|
978
|
+
isEfdRetry: test._ddIsEfdRetry,
|
|
979
|
+
isAttemptToFix: test._ddIsAttemptToFix,
|
|
980
|
+
isDisabled: test._ddIsDisabled,
|
|
981
|
+
isQuarantined: test._ddIsQuarantined,
|
|
982
|
+
isAttemptToFixRetry: test._ddIsAttemptToFixRetry,
|
|
983
|
+
hasFailedAllRetries: test._ddHasFailedAllRetries,
|
|
984
|
+
hasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
|
|
985
|
+
hasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
|
|
986
|
+
isAtrRetry: test._ddIsAtrRetry,
|
|
987
|
+
onDone,
|
|
988
|
+
...testCtx.currentStore
|
|
992
989
|
})
|
|
993
990
|
|
|
994
991
|
await flushPromise
|
|
@@ -26,23 +26,17 @@ addHook({ name: names }, function (url) {
|
|
|
26
26
|
|
|
27
27
|
const URLPrototype = url.URL.prototype.constructor.prototype
|
|
28
28
|
instrumentedGetters.forEach(property => {
|
|
29
|
-
|
|
29
|
+
shimmer.wrap(URLPrototype, property, function (originalGet) {
|
|
30
|
+
return function get () {
|
|
31
|
+
const result = originalGet.call(this)
|
|
32
|
+
if (!urlGetterChannel.hasSubscribers) return result
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return function get () {
|
|
34
|
-
const result = originalGet.apply(this, arguments)
|
|
35
|
-
if (!urlGetterChannel.hasSubscribers) return result
|
|
34
|
+
const context = { urlObject: this, result, property }
|
|
35
|
+
urlGetterChannel.publish(context)
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return context.result
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
Object.defineProperty(URLPrototype, property, newDescriptor)
|
|
45
|
-
}
|
|
37
|
+
return context.result
|
|
38
|
+
}
|
|
39
|
+
})
|
|
46
40
|
})
|
|
47
41
|
|
|
48
42
|
shimmer.wrap(url, 'URL', (URL) => {
|
|
@@ -83,6 +77,4 @@ addHook({ name: names }, function (url) {
|
|
|
83
77
|
}
|
|
84
78
|
})
|
|
85
79
|
}
|
|
86
|
-
|
|
87
|
-
return url
|
|
88
80
|
})
|
|
@@ -26,7 +26,7 @@ const knownTestsCh = channel('ci:vitest:known-tests')
|
|
|
26
26
|
const isEarlyFlakeDetectionFaultyCh = channel('ci:vitest:is-early-flake-detection-faulty')
|
|
27
27
|
const testManagementTestsCh = channel('ci:vitest:test-management-tests')
|
|
28
28
|
|
|
29
|
-
const
|
|
29
|
+
const taskToCtx = new WeakMap()
|
|
30
30
|
const taskToStatuses = new WeakMap()
|
|
31
31
|
const newTasks = new WeakSet()
|
|
32
32
|
const disabledTasks = new WeakSet()
|
|
@@ -455,7 +455,7 @@ addHook({
|
|
|
455
455
|
// test start (only tests that are not marked as skip or todo)
|
|
456
456
|
// `onBeforeTryTask` is run for every repetition and attempt of the test
|
|
457
457
|
shimmer.wrap(VitestTestRunner.prototype, 'onBeforeTryTask', onBeforeTryTask => async function (task, retryInfo) {
|
|
458
|
-
if (!
|
|
458
|
+
if (!testPassCh.hasSubscribers && !testErrorCh.hasSubscribers && !testSkipCh.hasSubscribers) {
|
|
459
459
|
return onBeforeTryTask.apply(this, arguments)
|
|
460
460
|
}
|
|
461
461
|
const testName = getTestName(task)
|
|
@@ -500,15 +500,14 @@ addHook({
|
|
|
500
500
|
|
|
501
501
|
const promises = {}
|
|
502
502
|
const shouldSetProbe = isDiEnabled && numAttempt === 1
|
|
503
|
-
const
|
|
503
|
+
const ctx = taskToCtx.get(task)
|
|
504
504
|
const testError = task.result?.errors?.[0]
|
|
505
|
-
if (
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
})
|
|
505
|
+
if (ctx) {
|
|
506
|
+
testErrorCh.publish({
|
|
507
|
+
error: testError,
|
|
508
|
+
shouldSetProbe,
|
|
509
|
+
promises,
|
|
510
|
+
...ctx.currentStore
|
|
512
511
|
})
|
|
513
512
|
// We wait for the probe to be set
|
|
514
513
|
if (promises.setProbePromise) {
|
|
@@ -528,17 +527,13 @@ addHook({
|
|
|
528
527
|
// as long as it's not the _last_ iteration (which will be finished normally)
|
|
529
528
|
|
|
530
529
|
// TODO: check test duration (not to repeat if it's too slow)
|
|
531
|
-
const
|
|
532
|
-
if (
|
|
530
|
+
const ctx = taskToCtx.get(task)
|
|
531
|
+
if (ctx) {
|
|
533
532
|
if (lastExecutionStatus === 'fail') {
|
|
534
533
|
const testError = task.result?.errors?.[0]
|
|
535
|
-
|
|
536
|
-
testErrorCh.publish({ error: testError })
|
|
537
|
-
})
|
|
534
|
+
testErrorCh.publish({ error: testError, ...ctx.currentStore })
|
|
538
535
|
} else {
|
|
539
|
-
|
|
540
|
-
testPassCh.publish({ task })
|
|
541
|
-
})
|
|
536
|
+
testPassCh.publish({ task, ...ctx.currentStore })
|
|
542
537
|
}
|
|
543
538
|
if (shouldFlipStatus) {
|
|
544
539
|
statuses.push(lastExecutionStatus)
|
|
@@ -555,16 +550,12 @@ addHook({
|
|
|
555
550
|
statuses.push(lastExecutionStatus)
|
|
556
551
|
}
|
|
557
552
|
|
|
558
|
-
const
|
|
553
|
+
const ctx = taskToCtx.get(task)
|
|
559
554
|
if (lastExecutionStatus === 'fail') {
|
|
560
555
|
const testError = task.result?.errors?.[0]
|
|
561
|
-
|
|
562
|
-
testErrorCh.publish({ error: testError })
|
|
563
|
-
})
|
|
556
|
+
testErrorCh.publish({ error: testError, ...ctx.currentStore })
|
|
564
557
|
} else {
|
|
565
|
-
|
|
566
|
-
testPassCh.publish({ task })
|
|
567
|
-
})
|
|
558
|
+
testPassCh.publish({ task, ...ctx.currentStore })
|
|
568
559
|
}
|
|
569
560
|
}
|
|
570
561
|
|
|
@@ -573,31 +564,29 @@ addHook({
|
|
|
573
564
|
!isRetryReasonAttemptToFix &&
|
|
574
565
|
!isRetryReasonEfd
|
|
575
566
|
|
|
576
|
-
const
|
|
577
|
-
|
|
567
|
+
const ctx = {
|
|
568
|
+
testName,
|
|
569
|
+
testSuiteAbsolutePath: task.file.filepath,
|
|
570
|
+
isRetry: numAttempt > 0 || numRepetition > 0,
|
|
571
|
+
isRetryReasonEfd,
|
|
572
|
+
isRetryReasonAttemptToFix: isRetryReasonAttemptToFix && numRepetition > 0,
|
|
573
|
+
isNew,
|
|
574
|
+
mightHitProbe: isDiEnabled && numAttempt > 0,
|
|
575
|
+
isAttemptToFix: attemptToFixTasks.has(task),
|
|
576
|
+
isDisabled: disabledTasks.has(task),
|
|
577
|
+
isQuarantined,
|
|
578
|
+
isRetryReasonAtr
|
|
579
|
+
}
|
|
580
|
+
taskToCtx.set(task, ctx)
|
|
578
581
|
|
|
579
|
-
|
|
580
|
-
testStartCh.publish({
|
|
581
|
-
testName,
|
|
582
|
-
testSuiteAbsolutePath: task.file.filepath,
|
|
583
|
-
isRetry: numAttempt > 0 || numRepetition > 0,
|
|
584
|
-
isRetryReasonEfd,
|
|
585
|
-
isRetryReasonAttemptToFix: isRetryReasonAttemptToFix && numRepetition > 0,
|
|
586
|
-
isNew,
|
|
587
|
-
mightHitProbe: isDiEnabled && numAttempt > 0,
|
|
588
|
-
isAttemptToFix: attemptToFixTasks.has(task),
|
|
589
|
-
isDisabled: disabledTasks.has(task),
|
|
590
|
-
isQuarantined,
|
|
591
|
-
isRetryReasonAtr
|
|
592
|
-
})
|
|
593
|
-
})
|
|
582
|
+
testStartCh.runStores(ctx, () => { })
|
|
594
583
|
return onBeforeTryTask.apply(this, arguments)
|
|
595
584
|
})
|
|
596
585
|
|
|
597
586
|
// test finish (only passed tests)
|
|
598
587
|
shimmer.wrap(VitestTestRunner.prototype, 'onAfterTryTask', onAfterTryTask =>
|
|
599
588
|
async function (task, { retry: retryCount }) {
|
|
600
|
-
if (!
|
|
589
|
+
if (!testPassCh.hasSubscribers && !testErrorCh.hasSubscribers && !testSkipCh.hasSubscribers) {
|
|
601
590
|
return onAfterTryTask.apply(this, arguments)
|
|
602
591
|
}
|
|
603
592
|
const result = await onAfterTryTask.apply(this, arguments)
|
|
@@ -605,7 +594,7 @@ addHook({
|
|
|
605
594
|
const { testManagementAttemptToFixRetries } = getProvidedContext()
|
|
606
595
|
|
|
607
596
|
const status = getVitestTestStatus(task, retryCount)
|
|
608
|
-
const
|
|
597
|
+
const ctx = taskToCtx.get(task)
|
|
609
598
|
|
|
610
599
|
const { isDiEnabled } = getProvidedContext()
|
|
611
600
|
|
|
@@ -614,18 +603,25 @@ addHook({
|
|
|
614
603
|
}
|
|
615
604
|
|
|
616
605
|
let attemptToFixPassed = false
|
|
606
|
+
let attemptToFixFailed = false
|
|
617
607
|
if (attemptToFixTasks.has(task)) {
|
|
618
608
|
const statuses = taskToStatuses.get(task)
|
|
619
|
-
if (statuses.length === testManagementAttemptToFixRetries
|
|
620
|
-
|
|
609
|
+
if (statuses.length === testManagementAttemptToFixRetries) {
|
|
610
|
+
if (statuses.every(status => status === 'pass')) {
|
|
611
|
+
attemptToFixPassed = true
|
|
612
|
+
} else if (statuses.some(status => status === 'fail')) {
|
|
613
|
+
attemptToFixFailed = true
|
|
614
|
+
}
|
|
621
615
|
}
|
|
622
616
|
}
|
|
623
617
|
|
|
624
|
-
if (
|
|
618
|
+
if (ctx) {
|
|
625
619
|
// We don't finish here because the test might fail in a later hook (afterEach)
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
620
|
+
ctx.status = status
|
|
621
|
+
ctx.task = task
|
|
622
|
+
ctx.attemptToFixPassed = attemptToFixPassed
|
|
623
|
+
ctx.attemptToFixFailed = attemptToFixFailed
|
|
624
|
+
testFinishTimeCh.runStores(ctx, () => { })
|
|
629
625
|
}
|
|
630
626
|
|
|
631
627
|
return result
|
|
@@ -723,19 +719,14 @@ addHook({
|
|
|
723
719
|
}, (vitestPackage, frameworkVersion) => {
|
|
724
720
|
shimmer.wrap(vitestPackage, 'startTests', startTests => async function (testPaths) {
|
|
725
721
|
let testSuiteError = null
|
|
726
|
-
if (!
|
|
722
|
+
if (!testSuiteFinishCh.hasSubscribers) {
|
|
727
723
|
return startTests.apply(this, arguments)
|
|
728
724
|
}
|
|
729
725
|
// From >=3.0.1, the first arguments changes from a string to an object containing the filepath
|
|
730
726
|
const testSuiteAbsolutePath = testPaths[0]?.filepath || testPaths[0]
|
|
731
727
|
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
testSuiteStartCh.publish({
|
|
735
|
-
testSuiteAbsolutePath,
|
|
736
|
-
frameworkVersion
|
|
737
|
-
})
|
|
738
|
-
})
|
|
728
|
+
const testSuiteCtx = { testSuiteAbsolutePath, frameworkVersion }
|
|
729
|
+
testSuiteStartCh.runStores(testSuiteCtx, () => { })
|
|
739
730
|
const startTestsResponse = await startTests.apply(this, arguments)
|
|
740
731
|
|
|
741
732
|
let onFinish = null
|
|
@@ -747,7 +738,7 @@ addHook({
|
|
|
747
738
|
|
|
748
739
|
// Only one test task per test, even if there are retries
|
|
749
740
|
testTasks.forEach(task => {
|
|
750
|
-
const
|
|
741
|
+
const testCtx = taskToCtx.get(task)
|
|
751
742
|
const { result } = task
|
|
752
743
|
// We have to trick vitest into thinking that the test has passed
|
|
753
744
|
// but we want to report it as failed if it did fail
|
|
@@ -763,10 +754,8 @@ addHook({
|
|
|
763
754
|
isDisabled: disabledTasks.has(task)
|
|
764
755
|
})
|
|
765
756
|
} else if (state === 'pass' && !isSwitchedStatus) {
|
|
766
|
-
if (
|
|
767
|
-
|
|
768
|
-
testPassCh.publish({ task })
|
|
769
|
-
})
|
|
757
|
+
if (testCtx) {
|
|
758
|
+
testPassCh.publish({ task, ...testCtx.currentStore })
|
|
770
759
|
}
|
|
771
760
|
} else if (state === 'fail' || isSwitchedStatus) {
|
|
772
761
|
let testError
|
|
@@ -776,18 +765,26 @@ addHook({
|
|
|
776
765
|
}
|
|
777
766
|
|
|
778
767
|
let hasFailedAllRetries = false
|
|
768
|
+
let attemptToFixFailed = false
|
|
779
769
|
if (attemptToFixTasks.has(task)) {
|
|
780
770
|
const statuses = taskToStatuses.get(task)
|
|
771
|
+
if (statuses.some(status => status === 'fail')) {
|
|
772
|
+
attemptToFixFailed = true
|
|
773
|
+
}
|
|
781
774
|
if (statuses.every(status => status === 'fail')) {
|
|
782
775
|
hasFailedAllRetries = true
|
|
783
776
|
}
|
|
784
777
|
}
|
|
785
778
|
|
|
786
|
-
if (
|
|
779
|
+
if (testCtx) {
|
|
787
780
|
const isRetry = task.result?.retryCount > 0
|
|
788
781
|
// `duration` is the duration of all the retries, so it can't be used if there are retries
|
|
789
|
-
|
|
790
|
-
|
|
782
|
+
testErrorCh.publish({
|
|
783
|
+
duration: !isRetry ? duration : undefined,
|
|
784
|
+
error: testError,
|
|
785
|
+
hasFailedAllRetries,
|
|
786
|
+
attemptToFixFailed,
|
|
787
|
+
...testCtx.currentStore
|
|
791
788
|
})
|
|
792
789
|
}
|
|
793
790
|
if (errors?.length) {
|
|
@@ -817,14 +814,11 @@ addHook({
|
|
|
817
814
|
}
|
|
818
815
|
|
|
819
816
|
if (testSuiteError) {
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
})
|
|
817
|
+
testSuiteCtx.error = testSuiteError
|
|
818
|
+
testSuiteErrorCh.runStores(testSuiteCtx, () => { })
|
|
823
819
|
}
|
|
824
820
|
|
|
825
|
-
|
|
826
|
-
testSuiteFinishCh.publish({ status: testSuiteResult.state, onFinish })
|
|
827
|
-
})
|
|
821
|
+
testSuiteFinishCh.publish({ status: testSuiteResult.state, onFinish, ...testSuiteCtx.currentStore })
|
|
828
822
|
|
|
829
823
|
// TODO: fix too frequent flushes
|
|
830
824
|
await onFinishPromise
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const KafkajsBatchConsumerPlugin = require('../../datadog-plugin-kafkajs/src/batch-consumer')
|
|
4
|
+
|
|
5
|
+
class ConfluentKafkaJsBatchConsumerPlugin extends KafkajsBatchConsumerPlugin {
|
|
6
|
+
static get id () {
|
|
7
|
+
return '@confluentinc/kafka-javascript'
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = ConfluentKafkaJsBatchConsumerPlugin
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const KafkajsConsumerPlugin = require('../../datadog-plugin-kafkajs/src/consumer')
|
|
4
|
+
|
|
5
|
+
class ConfluentKafkaJsConsumerPlugin extends KafkajsConsumerPlugin {
|
|
6
|
+
static get id () {
|
|
7
|
+
return '@confluentinc/kafka-javascript'
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = ConfluentKafkaJsConsumerPlugin
|