dd-trace 5.74.0 → 5.75.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 +1 -0
- package/index.d.ts +11 -7
- package/loader-hook.mjs +52 -1
- package/package.json +5 -16
- package/packages/datadog-esbuild/index.js +1 -0
- package/packages/datadog-instrumentations/src/cookie-parser.js +0 -2
- package/packages/datadog-instrumentations/src/cucumber.js +2 -2
- package/packages/datadog-instrumentations/src/express-session.js +0 -1
- package/packages/datadog-instrumentations/src/mariadb.js +9 -7
- package/packages/datadog-instrumentations/src/playwright.js +116 -37
- package/packages/datadog-instrumentations/src/vitest.js +44 -12
- package/packages/datadog-plugin-aws-sdk/src/base.js +0 -1
- package/packages/datadog-plugin-playwright/src/index.js +74 -31
- package/packages/datadog-shimmer/src/shimmer.js +2 -0
- package/packages/dd-trace/src/aiguard/sdk.js +25 -3
- package/packages/dd-trace/src/aiguard/tags.js +4 -1
- package/packages/dd-trace/src/config-helper.js +1 -0
- package/packages/dd-trace/src/config.js +345 -329
- package/packages/dd-trace/src/config_defaults.js +9 -0
- package/packages/dd-trace/src/proxy.js +1 -1
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +5 -3
- package/register.js +1 -11
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -14,6 +14,7 @@ require,@opentelemetry/resources,Apache license 2.0,Copyright OpenTelemetry Auth
|
|
|
14
14
|
require,@isaacs/ttlcache,ISC,Copyright (c) 2022-2023 - Isaac Z. Schlueter and Contributors
|
|
15
15
|
require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
|
|
16
16
|
require,dc-polyfill,MIT,Copyright 2023 Datadog Inc.
|
|
17
|
+
require,escape-string-regexp,MIT,Copyright Sindre Sorhus
|
|
17
18
|
require,ignore,MIT,Copyright 2013 Kael Zhang and contributors
|
|
18
19
|
require,import-in-the-middle,Apache license 2.0,Copyright 2021 Datadog Inc.
|
|
19
20
|
require,istanbul-lib-coverage,BSD-3-Clause,Copyright 2012-2015 Yahoo! Inc.
|
package/index.d.ts
CHANGED
|
@@ -181,6 +181,7 @@ interface Tracer extends opentracing.Tracer {
|
|
|
181
181
|
/** @hidden */
|
|
182
182
|
interface Plugins {
|
|
183
183
|
"aerospike": tracer.plugins.aerospike;
|
|
184
|
+
"ai": tracer.plugins.ai;
|
|
184
185
|
"amqp10": tracer.plugins.amqp10;
|
|
185
186
|
"amqplib": tracer.plugins.amqplib;
|
|
186
187
|
"anthropic": tracer.plugins.anthropic;
|
|
@@ -1642,6 +1643,12 @@ declare namespace tracer {
|
|
|
1642
1643
|
*/
|
|
1643
1644
|
interface aerospike extends Instrumentation {}
|
|
1644
1645
|
|
|
1646
|
+
/**
|
|
1647
|
+
* This plugin automatically instruments the
|
|
1648
|
+
* [Vercel AI SDK](https://ai-sdk.dev/docs/introduction) module.
|
|
1649
|
+
*/
|
|
1650
|
+
interface ai extends Instrumentation {}
|
|
1651
|
+
|
|
1645
1652
|
/**
|
|
1646
1653
|
* This plugin automatically instruments the
|
|
1647
1654
|
* [amqp10](https://github.com/noodlefrenzy/node-amqp10) module.
|
|
@@ -1698,12 +1705,6 @@ declare namespace tracer {
|
|
|
1698
1705
|
* [aws-sdk](https://github.com/aws/aws-sdk-js) module.
|
|
1699
1706
|
*/
|
|
1700
1707
|
interface aws_sdk extends Instrumentation {
|
|
1701
|
-
/**
|
|
1702
|
-
* Whether to add a suffix to the service name so that each AWS service has its own service name.
|
|
1703
|
-
* @default true
|
|
1704
|
-
*/
|
|
1705
|
-
splitByAwsService?: boolean;
|
|
1706
|
-
|
|
1707
1708
|
/**
|
|
1708
1709
|
* Whether to inject all messages during batch AWS SQS, Kinesis, and SNS send operations. Normal
|
|
1709
1710
|
* behavior is to inject the first message in batch send operations.
|
|
@@ -2821,7 +2822,10 @@ declare namespace tracer {
|
|
|
2821
2822
|
redactionValuePattern?: string,
|
|
2822
2823
|
|
|
2823
2824
|
/**
|
|
2824
|
-
* Allows to enable security controls.
|
|
2825
|
+
* Allows to enable security controls. This option is not supported when
|
|
2826
|
+
* using ESM.
|
|
2827
|
+
* @deprecated Please use the DD_IAST_SECURITY_CONTROLS_CONFIGURATION
|
|
2828
|
+
* environment variable instead.
|
|
2825
2829
|
*/
|
|
2826
2830
|
securityControlsConfiguration?: string,
|
|
2827
2831
|
|
package/loader-hook.mjs
CHANGED
|
@@ -1 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
import regexpEscape from 'escape-string-regexp'
|
|
2
|
+
import * as iitm from 'import-in-the-middle/hook.mjs'
|
|
3
|
+
import hooks from './packages/datadog-instrumentations/src/helpers/hooks.js'
|
|
4
|
+
import configHelper from './packages/dd-trace/src/config-helper.js'
|
|
5
|
+
|
|
6
|
+
// For some reason `getEnvironmentVariable` is not otherwise available to ESM.
|
|
7
|
+
const env = configHelper.getEnvironmentVariable
|
|
8
|
+
|
|
9
|
+
function initialize (data = {}) {
|
|
10
|
+
data.include ??= []
|
|
11
|
+
data.exclude ??= []
|
|
12
|
+
|
|
13
|
+
addInstrumentations(data)
|
|
14
|
+
addSecurityControls(data)
|
|
15
|
+
addExclusions(data)
|
|
16
|
+
|
|
17
|
+
return iitm.initialize(data)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function addInstrumentations (data) {
|
|
21
|
+
const instrumentations = Object.keys(hooks)
|
|
22
|
+
|
|
23
|
+
for (const moduleName of instrumentations) {
|
|
24
|
+
data.include.push(new RegExp(`node_modules/${moduleName}/(?!node_modules).+`), moduleName)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function addSecurityControls (data) {
|
|
29
|
+
const securityControls = (env('DD_IAST_SECURITY_CONTROLS_CONFIGURATION') || '')
|
|
30
|
+
.split(';')
|
|
31
|
+
.map(sc => sc.trim().split(':')[2])
|
|
32
|
+
.filter(Boolean)
|
|
33
|
+
.map(sc => sc.trim())
|
|
34
|
+
|
|
35
|
+
for (const subpath of securityControls) {
|
|
36
|
+
data.include.push(new RegExp(regexpEscape(subpath)))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function addExclusions (data) {
|
|
41
|
+
data.exclude.push(
|
|
42
|
+
/middle/,
|
|
43
|
+
/langsmith/,
|
|
44
|
+
/openai\/_shims/,
|
|
45
|
+
/openai\/resources\/chat\/completions\/messages/,
|
|
46
|
+
/openai\/agents-core\/dist\/shims/,
|
|
47
|
+
/@anthropic-ai\/sdk\/_shims/
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { initialize }
|
|
52
|
+
export { load, getFormat, resolve, getSource } from 'import-in-the-middle/hook.mjs'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.75.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -136,6 +136,7 @@
|
|
|
136
136
|
"@opentelemetry/resources": ">=1.0.0 <1.10.0",
|
|
137
137
|
"crypto-randomuuid": "^1.0.0",
|
|
138
138
|
"dc-polyfill": "^0.1.10",
|
|
139
|
+
"escape-string-regexp": "^5.0.0",
|
|
139
140
|
"ignore": "^7.0.5",
|
|
140
141
|
"import-in-the-middle": "^1.14.2",
|
|
141
142
|
"istanbul-lib-coverage": "^3.2.2",
|
|
@@ -158,25 +159,13 @@
|
|
|
158
159
|
"tlhunter-sorted-set": "^0.1.0",
|
|
159
160
|
"ttl-set": "^1.0.0"
|
|
160
161
|
},
|
|
161
|
-
"peerDependencies": {
|
|
162
|
-
"@openfeature/core": "^1.9.0",
|
|
163
|
-
"@openfeature/server-sdk": "~1.20.0"
|
|
164
|
-
},
|
|
165
|
-
"peerDependenciesMeta": {
|
|
166
|
-
"@openfeature/core": {
|
|
167
|
-
"optional": true
|
|
168
|
-
},
|
|
169
|
-
"@openfeature/server-sdk": {
|
|
170
|
-
"optional": true
|
|
171
|
-
}
|
|
172
|
-
},
|
|
173
162
|
"devDependencies": {
|
|
174
163
|
"@babel/helpers": "^7.27.6",
|
|
175
164
|
"@eslint/eslintrc": "^3.3.1",
|
|
176
165
|
"@eslint/js": "^9.29.0",
|
|
177
166
|
"@msgpack/msgpack": "^3.1.2",
|
|
178
|
-
"@openfeature/core": "^1.
|
|
179
|
-
"@openfeature/server-sdk": "
|
|
167
|
+
"@openfeature/core": "^1.9.0",
|
|
168
|
+
"@openfeature/server-sdk": "^1.20.0",
|
|
180
169
|
"@stylistic/eslint-plugin": "^5.0.0",
|
|
181
170
|
"@types/chai": "^4.3.16",
|
|
182
171
|
"@types/mocha": "^10.0.10",
|
|
@@ -214,7 +203,7 @@
|
|
|
214
203
|
"tap": "^16.3.10",
|
|
215
204
|
"tiktoken": "^1.0.21",
|
|
216
205
|
"typescript": "^5.9.2",
|
|
217
|
-
"workerpool": "^
|
|
206
|
+
"workerpool": "^10.0.0",
|
|
218
207
|
"yaml": "^2.8.0",
|
|
219
208
|
"yarn-deduplicate": "^6.0.2"
|
|
220
209
|
}
|
|
@@ -25,8 +25,6 @@ addHook({
|
|
|
25
25
|
name: 'cookie-parser',
|
|
26
26
|
versions: ['>=1.0.0']
|
|
27
27
|
}, cookieParser => {
|
|
28
|
-
// This prevents the non default export from entering the wrapping process
|
|
29
|
-
if (cookieParser.default) return cookieParser
|
|
30
28
|
return shimmer.wrapFunction(cookieParser, cookieParser => function () {
|
|
31
29
|
const cookieMiddleware = cookieParser.apply(this, arguments)
|
|
32
30
|
|
|
@@ -259,7 +259,7 @@ function wrapRun (pl, isLatestVersion, version) {
|
|
|
259
259
|
testStartCh.runStores(ctx, () => {})
|
|
260
260
|
const promises = {}
|
|
261
261
|
try {
|
|
262
|
-
this.eventBroadcaster.on('envelope',
|
|
262
|
+
this.eventBroadcaster.on('envelope', async (testCase) => {
|
|
263
263
|
// Only supported from >=8.0.0
|
|
264
264
|
if (testCase?.testCaseFinished) {
|
|
265
265
|
const { testCaseFinished: { willBeRetried } } = testCase
|
|
@@ -289,7 +289,7 @@ function wrapRun (pl, isLatestVersion, version) {
|
|
|
289
289
|
testStartCh.runStores(newCtx, () => {})
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
|
-
})
|
|
292
|
+
})
|
|
293
293
|
let promise
|
|
294
294
|
|
|
295
295
|
testFnCh.runStores(ctx, () => {
|
|
@@ -82,12 +82,7 @@ function createWrapQueryCallback (options) {
|
|
|
82
82
|
|
|
83
83
|
const cb = arguments[arguments.length - 1]
|
|
84
84
|
const ctx = { sql, conf: options }
|
|
85
|
-
|
|
86
|
-
if (typeof cb !== 'function') {
|
|
87
|
-
arguments.length += 1
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
arguments[arguments.length - 1] = shimmer.wrapFunction(cb, cb => function (err) {
|
|
85
|
+
const wrapper = (cb) => function (err) {
|
|
91
86
|
if (err) {
|
|
92
87
|
ctx.error = err
|
|
93
88
|
errorCh.publish(ctx)
|
|
@@ -96,7 +91,14 @@ function createWrapQueryCallback (options) {
|
|
|
96
91
|
return typeof cb === 'function'
|
|
97
92
|
? finishCh.runStores(ctx, cb, this, ...arguments)
|
|
98
93
|
: finishCh.publish(ctx)
|
|
99
|
-
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (typeof cb === 'function') {
|
|
97
|
+
arguments[arguments.length - 1] = shimmer.wrapFunction(cb, wrapper)
|
|
98
|
+
} else {
|
|
99
|
+
arguments.length += 1
|
|
100
|
+
arguments[arguments.length - 1] = wrapper()
|
|
101
|
+
}
|
|
100
102
|
|
|
101
103
|
return startCh.runStores(ctx, query, this, ...arguments)
|
|
102
104
|
}
|
|
@@ -15,6 +15,7 @@ const { DD_MAJOR } = require('../../../version')
|
|
|
15
15
|
|
|
16
16
|
const testStartCh = channel('ci:playwright:test:start')
|
|
17
17
|
const testFinishCh = channel('ci:playwright:test:finish')
|
|
18
|
+
const testSkipCh = channel('ci:playwright:test:skip')
|
|
18
19
|
|
|
19
20
|
const testSessionStartCh = channel('ci:playwright:session:start')
|
|
20
21
|
const testSessionFinishCh = channel('ci:playwright:session:finish')
|
|
@@ -37,6 +38,8 @@ const testSuiteToTestStatuses = new Map()
|
|
|
37
38
|
const testSuiteToErrors = new Map()
|
|
38
39
|
const testsToTestStatuses = new Map()
|
|
39
40
|
|
|
41
|
+
const RUM_FLUSH_WAIT_TIME = 1000
|
|
42
|
+
|
|
40
43
|
let applyRepeatEachIndex = null
|
|
41
44
|
|
|
42
45
|
let startedSuites = []
|
|
@@ -285,7 +288,12 @@ function getTestFullname (test) {
|
|
|
285
288
|
return names.join(' ')
|
|
286
289
|
}
|
|
287
290
|
|
|
288
|
-
function
|
|
291
|
+
function shouldFinishTestSuite (testSuiteAbsolutePath) {
|
|
292
|
+
const remainingTests = remainingTestsByFile[testSuiteAbsolutePath]
|
|
293
|
+
return !remainingTests.length || remainingTests.every(test => test.expectedStatus === 'skipped')
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function testBeginHandler (test, browserName, shouldCreateTestSpan) {
|
|
289
297
|
const {
|
|
290
298
|
_requireFile: testSuiteAbsolutePath,
|
|
291
299
|
location: {
|
|
@@ -297,6 +305,10 @@ function testBeginHandler (test, browserName, isMainProcess) {
|
|
|
297
305
|
if (_type === 'beforeAll' || _type === 'afterAll') {
|
|
298
306
|
return
|
|
299
307
|
}
|
|
308
|
+
// this means that a skipped test is being handled
|
|
309
|
+
if (!remainingTestsByFile[testSuiteAbsolutePath].length) {
|
|
310
|
+
return
|
|
311
|
+
}
|
|
300
312
|
|
|
301
313
|
const isNewTestSuite = !startedSuites.includes(testSuiteAbsolutePath)
|
|
302
314
|
|
|
@@ -313,7 +325,7 @@ function testBeginHandler (test, browserName, isMainProcess) {
|
|
|
313
325
|
}
|
|
314
326
|
|
|
315
327
|
// this handles tests that do not go through the worker process (because they're skipped)
|
|
316
|
-
if (
|
|
328
|
+
if (shouldCreateTestSpan) {
|
|
317
329
|
const testName = getTestFullname(test)
|
|
318
330
|
const testCtx = {
|
|
319
331
|
testName,
|
|
@@ -328,8 +340,20 @@ function testBeginHandler (test, browserName, isMainProcess) {
|
|
|
328
340
|
}
|
|
329
341
|
}
|
|
330
342
|
|
|
331
|
-
function testEndHandler (
|
|
332
|
-
|
|
343
|
+
function testEndHandler ({
|
|
344
|
+
test,
|
|
345
|
+
annotations,
|
|
346
|
+
testStatus,
|
|
347
|
+
error,
|
|
348
|
+
isTimeout,
|
|
349
|
+
shouldCreateTestSpan,
|
|
350
|
+
projects
|
|
351
|
+
}) {
|
|
352
|
+
const {
|
|
353
|
+
_requireFile: testSuiteAbsolutePath,
|
|
354
|
+
results,
|
|
355
|
+
_type,
|
|
356
|
+
} = test
|
|
333
357
|
|
|
334
358
|
let annotationTags
|
|
335
359
|
if (annotations.length) {
|
|
@@ -368,31 +392,34 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
|
|
|
368
392
|
}
|
|
369
393
|
|
|
370
394
|
// this handles tests that do not go through the worker process (because they're skipped)
|
|
371
|
-
if (
|
|
395
|
+
if (shouldCreateTestSpan) {
|
|
372
396
|
const testResult = results.at(-1)
|
|
373
397
|
const testCtx = testToCtx.get(test)
|
|
374
398
|
const isAtrRetry = testResult?.retry > 0 &&
|
|
375
399
|
isFlakyTestRetriesEnabled &&
|
|
376
400
|
!test._ddIsAttemptToFix &&
|
|
377
401
|
!test._ddIsEfdRetry
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
402
|
+
// if there is no testCtx, the skipped test will be created later
|
|
403
|
+
if (testCtx) {
|
|
404
|
+
testFinishCh.publish({
|
|
405
|
+
testStatus,
|
|
406
|
+
steps: testResult?.steps || [],
|
|
407
|
+
isRetry: testResult?.retry > 0,
|
|
408
|
+
error,
|
|
409
|
+
extraTags: annotationTags,
|
|
410
|
+
isNew: test._ddIsNew,
|
|
411
|
+
isAttemptToFix: test._ddIsAttemptToFix,
|
|
412
|
+
isAttemptToFixRetry: test._ddIsAttemptToFixRetry,
|
|
413
|
+
isQuarantined: test._ddIsQuarantined,
|
|
414
|
+
isEfdRetry: test._ddIsEfdRetry,
|
|
415
|
+
hasFailedAllRetries: test._ddHasFailedAllRetries,
|
|
416
|
+
hasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
|
|
417
|
+
hasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
|
|
418
|
+
isAtrRetry,
|
|
419
|
+
isModified: test._ddIsModified,
|
|
420
|
+
...testCtx.currentStore
|
|
421
|
+
})
|
|
422
|
+
}
|
|
396
423
|
}
|
|
397
424
|
|
|
398
425
|
if (testSuiteToTestStatuses.has(testSuiteAbsolutePath)) {
|
|
@@ -410,8 +437,25 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
|
|
|
410
437
|
.filter(currentTest => currentTest !== test)
|
|
411
438
|
}
|
|
412
439
|
|
|
413
|
-
|
|
414
|
-
|
|
440
|
+
if (shouldFinishTestSuite(testSuiteAbsolutePath)) {
|
|
441
|
+
const skippedTests = remainingTestsByFile[testSuiteAbsolutePath]
|
|
442
|
+
.filter(test => test.expectedStatus === 'skipped')
|
|
443
|
+
|
|
444
|
+
for (const test of skippedTests) {
|
|
445
|
+
const browserName = getBrowserNameFromProjects(projects, test)
|
|
446
|
+
testSkipCh.publish({
|
|
447
|
+
testName: getTestFullname(test),
|
|
448
|
+
testSuiteAbsolutePath,
|
|
449
|
+
testSourceLine: test.location.line,
|
|
450
|
+
browserName,
|
|
451
|
+
isNew: test._ddIsNew,
|
|
452
|
+
isDisabled: test._ddIsDisabled,
|
|
453
|
+
isModified: test._ddIsModified,
|
|
454
|
+
isQuarantined: test._ddIsQuarantined
|
|
455
|
+
})
|
|
456
|
+
}
|
|
457
|
+
remainingTestsByFile[testSuiteAbsolutePath] = []
|
|
458
|
+
|
|
415
459
|
const testStatuses = testSuiteToTestStatuses.get(testSuiteAbsolutePath)
|
|
416
460
|
let testSuiteStatus = 'pass'
|
|
417
461
|
if (testStatuses.includes('fail')) {
|
|
@@ -450,10 +494,13 @@ function dispatcherHook (dispatcherExport) {
|
|
|
450
494
|
shimmer.wrap(dispatcherExport.Dispatcher.prototype, '_createWorker', createWorker => function () {
|
|
451
495
|
const dispatcher = this
|
|
452
496
|
const worker = createWorker.apply(this, arguments)
|
|
497
|
+
const projects = getProjectsFromDispatcher(dispatcher)
|
|
498
|
+
|
|
499
|
+
// for older versions of playwright, `shouldCreateTestSpan` should always be true,
|
|
500
|
+
// since the `_runTest` function wrapper is not available for older versions
|
|
453
501
|
worker.process.on('message', ({ method, params }) => {
|
|
454
502
|
if (method === 'testBegin') {
|
|
455
503
|
const { test } = dispatcher._testById.get(params.testId)
|
|
456
|
-
const projects = getProjectsFromDispatcher(dispatcher)
|
|
457
504
|
const browser = getBrowserNameFromProjects(projects, test)
|
|
458
505
|
testBeginHandler(test, browser, true)
|
|
459
506
|
} else if (method === 'testEnd') {
|
|
@@ -464,12 +511,15 @@ function dispatcherHook (dispatcherExport) {
|
|
|
464
511
|
|
|
465
512
|
const isTimeout = testResult.status === 'timedOut'
|
|
466
513
|
testEndHandler(
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
514
|
+
{
|
|
515
|
+
test,
|
|
516
|
+
annotations: params.annotations,
|
|
517
|
+
testStatus: STATUS_TO_TEST_STATUS[testResult.status],
|
|
518
|
+
error: testResult.error,
|
|
519
|
+
isTimeout,
|
|
520
|
+
shouldCreateTestSpan: true,
|
|
521
|
+
projects
|
|
522
|
+
}
|
|
473
523
|
)
|
|
474
524
|
}
|
|
475
525
|
})
|
|
@@ -484,18 +534,30 @@ function dispatcherHookNew (dispatcherExport, runWrapper) {
|
|
|
484
534
|
shimmer.wrap(dispatcherExport.Dispatcher.prototype, '_createWorker', createWorker => function () {
|
|
485
535
|
const dispatcher = this
|
|
486
536
|
const worker = createWorker.apply(this, arguments)
|
|
537
|
+
const projects = getProjectsFromDispatcher(dispatcher)
|
|
487
538
|
|
|
488
539
|
worker.on('testBegin', ({ testId }) => {
|
|
489
540
|
const test = getTestByTestId(dispatcher, testId)
|
|
490
|
-
const projects = getProjectsFromDispatcher(dispatcher)
|
|
491
541
|
const browser = getBrowserNameFromProjects(projects, test)
|
|
492
|
-
|
|
542
|
+
const shouldCreateTestSpan = test.expectedStatus === 'skipped'
|
|
543
|
+
testBeginHandler(test, browser, shouldCreateTestSpan)
|
|
493
544
|
})
|
|
494
545
|
worker.on('testEnd', ({ testId, status, errors, annotations }) => {
|
|
495
546
|
const test = getTestByTestId(dispatcher, testId)
|
|
496
547
|
|
|
497
548
|
const isTimeout = status === 'timedOut'
|
|
498
|
-
|
|
549
|
+
const shouldCreateTestSpan = test.expectedStatus === 'skipped'
|
|
550
|
+
testEndHandler(
|
|
551
|
+
{
|
|
552
|
+
test,
|
|
553
|
+
annotations,
|
|
554
|
+
testStatus: STATUS_TO_TEST_STATUS[status],
|
|
555
|
+
error: errors && errors[0],
|
|
556
|
+
isTimeout,
|
|
557
|
+
shouldCreateTestSpan,
|
|
558
|
+
projects
|
|
559
|
+
}
|
|
560
|
+
)
|
|
499
561
|
const testResult = test.results.at(-1)
|
|
500
562
|
const isAtrRetry = testResult?.retry > 0 &&
|
|
501
563
|
isFlakyTestRetriesEnabled &&
|
|
@@ -625,6 +687,9 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
625
687
|
|
|
626
688
|
let runAllTestsReturn = await runAllTests.apply(this, arguments)
|
|
627
689
|
|
|
690
|
+
// Tests that have only skipped tests may reach this point
|
|
691
|
+
// Skipped tests may or may not go through `testBegin` or `testEnd`
|
|
692
|
+
// depending on the playwright configuration
|
|
628
693
|
Object.values(remainingTestsByFile).forEach(tests => {
|
|
629
694
|
// `tests` should normally be empty, but if it isn't,
|
|
630
695
|
// there were tests that did not go through `testBegin` or `testEnd`,
|
|
@@ -632,7 +697,15 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
|
|
|
632
697
|
tests.forEach(test => {
|
|
633
698
|
const browser = getBrowserNameFromProjects(projects, test)
|
|
634
699
|
testBeginHandler(test, browser, true)
|
|
635
|
-
testEndHandler(
|
|
700
|
+
testEndHandler({
|
|
701
|
+
test,
|
|
702
|
+
annotations: [],
|
|
703
|
+
testStatus: 'skip',
|
|
704
|
+
error: null,
|
|
705
|
+
isTimeout: false,
|
|
706
|
+
shouldCreateTestSpan: true,
|
|
707
|
+
projects
|
|
708
|
+
})
|
|
636
709
|
})
|
|
637
710
|
})
|
|
638
711
|
|
|
@@ -1007,6 +1080,9 @@ addHook({
|
|
|
1007
1080
|
const stepInfoByStepId = {}
|
|
1008
1081
|
|
|
1009
1082
|
shimmer.wrap(workerPackage.WorkerMain.prototype, '_runTest', _runTest => async function (test) {
|
|
1083
|
+
if (test.expectedStatus === 'skipped') {
|
|
1084
|
+
return _runTest.apply(this, arguments)
|
|
1085
|
+
}
|
|
1010
1086
|
steps = []
|
|
1011
1087
|
|
|
1012
1088
|
const {
|
|
@@ -1060,6 +1136,8 @@ addHook({
|
|
|
1060
1136
|
})
|
|
1061
1137
|
|
|
1062
1138
|
if (isRumActive) {
|
|
1139
|
+
// Give some time RUM to flush data, similar to what we do in selenium
|
|
1140
|
+
await new Promise(resolve => setTimeout(resolve, RUM_FLUSH_WAIT_TIME))
|
|
1063
1141
|
const url = page.url()
|
|
1064
1142
|
if (url) {
|
|
1065
1143
|
const domain = new URL(url).hostname
|
|
@@ -1067,9 +1145,10 @@ addHook({
|
|
|
1067
1145
|
name: 'datadog-ci-visibility-test-execution-id',
|
|
1068
1146
|
value: '',
|
|
1069
1147
|
domain,
|
|
1070
|
-
expires: 0,
|
|
1071
1148
|
path: '/'
|
|
1072
1149
|
}])
|
|
1150
|
+
} else {
|
|
1151
|
+
log.error('RUM is active but page.url() is not available')
|
|
1073
1152
|
}
|
|
1074
1153
|
}
|
|
1075
1154
|
}
|
|
@@ -153,6 +153,10 @@ function isCliApiPackage (vitestPackage) {
|
|
|
153
153
|
return vitestPackage.s?.name === 'startVitest'
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
function isTestPackage (testPackage) {
|
|
157
|
+
return testPackage.V?.name === 'VitestTestRunner'
|
|
158
|
+
}
|
|
159
|
+
|
|
156
160
|
function getSessionStatus (state) {
|
|
157
161
|
if (state.getCountOfFailedTests() > 0) {
|
|
158
162
|
return 'fail'
|
|
@@ -240,7 +244,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
240
244
|
if (isFlakyTestRetriesEnabled && !this.ctx.config.retry && flakyTestRetriesCount > 0) {
|
|
241
245
|
this.ctx.config.retry = flakyTestRetriesCount
|
|
242
246
|
try {
|
|
243
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
247
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
248
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
249
|
+
: this.ctx.getRootProject()
|
|
244
250
|
workspaceProject._provided._ddIsFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
|
|
245
251
|
} catch {
|
|
246
252
|
log.warn('Could not send library configuration to workers.')
|
|
@@ -272,7 +278,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
272
278
|
// TODO: use this to pass session and module IDs to the worker, instead of polluting process.env
|
|
273
279
|
// Note: setting this.ctx.config.provide directly does not work because it's cached
|
|
274
280
|
try {
|
|
275
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
281
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
282
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
283
|
+
: this.ctx.getRootProject()
|
|
276
284
|
workspaceProject._provided._ddIsKnownTestsEnabled = isKnownTestsEnabled
|
|
277
285
|
workspaceProject._provided._ddKnownTests = knownTests
|
|
278
286
|
workspaceProject._provided._ddIsEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
@@ -290,7 +298,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
290
298
|
|
|
291
299
|
if (isDiEnabled) {
|
|
292
300
|
try {
|
|
293
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
301
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
302
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
303
|
+
: this.ctx.getRootProject()
|
|
294
304
|
workspaceProject._provided._ddIsDiEnabled = isDiEnabled
|
|
295
305
|
} catch {
|
|
296
306
|
log.warn('Could not send Dynamic Instrumentation configuration to workers.')
|
|
@@ -305,7 +315,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
305
315
|
} else {
|
|
306
316
|
const testManagementTests = receivedTestManagementTests
|
|
307
317
|
try {
|
|
308
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
318
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
319
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
320
|
+
: this.ctx.getRootProject()
|
|
309
321
|
workspaceProject._provided._ddIsTestManagementTestsEnabled = isTestManagementTestsEnabled
|
|
310
322
|
workspaceProject._provided._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
|
|
311
323
|
workspaceProject._provided._ddTestManagementTests = testManagementTests
|
|
@@ -321,7 +333,9 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
321
333
|
log.error('Could not get modified tests.')
|
|
322
334
|
} else {
|
|
323
335
|
try {
|
|
324
|
-
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
336
|
+
const workspaceProject = this.ctx.getCoreWorkspaceProject
|
|
337
|
+
? this.ctx.getCoreWorkspaceProject()
|
|
338
|
+
: this.ctx.getRootProject()
|
|
325
339
|
workspaceProject._provided._ddIsImpactedTestsEnabled = isImpactedTestsEnabled
|
|
326
340
|
workspaceProject._provided._ddModifiedFiles = modifiedFiles
|
|
327
341
|
} catch {
|
|
@@ -443,13 +457,7 @@ function getStartVitestWrapper (cliApiPackage, frameworkVersion) {
|
|
|
443
457
|
return cliApiPackage
|
|
444
458
|
}
|
|
445
459
|
|
|
446
|
-
|
|
447
|
-
name: 'vitest',
|
|
448
|
-
versions: ['>=1.6.0'],
|
|
449
|
-
file: 'dist/runners.js'
|
|
450
|
-
}, (vitestPackage) => {
|
|
451
|
-
const { VitestTestRunner } = vitestPackage
|
|
452
|
-
|
|
460
|
+
function wrapVitestTestRunner (VitestTestRunner) {
|
|
453
461
|
// `onBeforeRunTask` is run before any repetition or attempt is run
|
|
454
462
|
// `onBeforeRunTask` is an async function
|
|
455
463
|
shimmer.wrap(VitestTestRunner.prototype, 'onBeforeRunTask', onBeforeRunTask => function (task) {
|
|
@@ -744,6 +752,30 @@ addHook({
|
|
|
744
752
|
|
|
745
753
|
return result
|
|
746
754
|
})
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
addHook({
|
|
758
|
+
name: 'vitest',
|
|
759
|
+
versions: ['>=4.0.0'],
|
|
760
|
+
filePattern: 'dist/chunks/test.*'
|
|
761
|
+
}, (testPackage) => {
|
|
762
|
+
if (!isTestPackage(testPackage)) {
|
|
763
|
+
return testPackage
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
wrapVitestTestRunner(testPackage.V)
|
|
767
|
+
|
|
768
|
+
return testPackage
|
|
769
|
+
})
|
|
770
|
+
|
|
771
|
+
addHook({
|
|
772
|
+
name: 'vitest',
|
|
773
|
+
versions: ['>=1.6.0 <4.0.0'],
|
|
774
|
+
file: 'dist/runners.js'
|
|
775
|
+
}, (vitestPackage) => {
|
|
776
|
+
const { VitestTestRunner } = vitestPackage
|
|
777
|
+
|
|
778
|
+
wrapVitestTestRunner(VitestTestRunner)
|
|
747
779
|
|
|
748
780
|
return vitestPackage
|
|
749
781
|
})
|