Skip to content

Commit 5acd010

Browse files
new exporter
1 parent db66b0a commit 5acd010

File tree

11 files changed

+132
-26
lines changed

11 files changed

+132
-26
lines changed

ci/init.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ const isCucumberWorker = !!process.env.CUCUMBER_WORKER_ID
88
const isMochaWorker = !!process.env.MOCHA_WORKER_ID
99

1010
const isPlaywrightWorker = !!process.env.DD_PLAYWRIGHT_WORKER
11+
// we can't use VITEST_WORKER_ID because it's set _after_ the worker is initialized
12+
// maybe we can intercept tinypool to inject it to be sure
13+
const isVitestWorker = !!process.env.TINYPOOL_WORKER_ID
1114

1215
const packageManagers = [
1316
'npm',
1417
'yarn',
1518
'pnpm'
1619
]
1720

21+
console.log('init', isVitestWorker)
22+
1823
const isPackageManager = () => {
1924
return packageManagers.some(packageManager => process.argv[1]?.includes(`bin/${packageManager}`))
2025
}
@@ -75,6 +80,13 @@ if (isPlaywrightWorker) {
7580
}
7681
}
7782

83+
if (isVitestWorker) {
84+
console.log('initializing as vites tworker')
85+
options.experimental = {
86+
exporter: 'vitest_worker'
87+
}
88+
}
89+
7890
if (shouldInit) {
7991
tracer.init(options)
8092
tracer.use('fs', false)

ext/exporters.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ declare const exporters: {
66
JEST_WORKER: 'jest_worker',
77
CUCUMBER_WORKER: 'cucumber_worker',
88
MOCHA_WORKER: 'mocha_worker',
9-
PLAYWRIGHT_WORKER: 'playwright_worker'
9+
PLAYWRIGHT_WORKER: 'playwright_worker',
10+
VITEST_WORKER: 'vitest_worker'
1011
}
1112

1213
export = exporters

ext/exporters.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ module.exports = {
77
JEST_WORKER: 'jest_worker',
88
CUCUMBER_WORKER: 'cucumber_worker',
99
MOCHA_WORKER: 'mocha_worker',
10-
PLAYWRIGHT_WORKER: 'playwright_worker'
10+
PLAYWRIGHT_WORKER: 'playwright_worker',
11+
VITEST_WORKER: 'vitest_worker'
1112
}

packages/datadog-instrumentations/src/helpers/hooks.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,6 @@ module.exports = {
132132
vm: () => require('../vm'),
133133
when: () => require('../when'),
134134
winston: () => require('../winston'),
135-
workerpool: () => require('../mocha')
135+
workerpool: () => require('../mocha'),
136+
tinypool: { esmFirst: true, fn: () => require('../vitest') }
136137
}

packages/datadog-instrumentations/src/vitest.js

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
const v8 = require('node:v8')
2+
13
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
24
const shimmer = require('../../datadog-shimmer')
35
const log = require('../../dd-trace/src/log')
4-
56
// test hooks
67
const testStartCh = channel('ci:vitest:test:start')
78
const testFinishTimeCh = channel('ci:vitest:test:finish-time')
@@ -26,6 +27,8 @@ const knownTestsCh = channel('ci:vitest:known-tests')
2627
const isEarlyFlakeDetectionFaultyCh = channel('ci:vitest:is-early-flake-detection-faulty')
2728
const testManagementTestsCh = channel('ci:vitest:test-management-tests')
2829

30+
const workerReporterCh = channel('ci:vitest:worker-report:trace')
31+
2932
const taskToCtx = new WeakMap()
3033
const taskToStatuses = new WeakMap()
3134
const newTasks = new WeakSet()
@@ -61,6 +64,8 @@ function getProvidedContext () {
6164
_ddIsFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled
6265
} = globalThis.__vitest_worker__.providedContext
6366

67+
// console.log('globalThis.__vitest_worker__', globalThis.__vitest_worker__)
68+
6469
return {
6570
isDiEnabled: _ddIsDiEnabled,
6671
isEarlyFlakeDetectionEnabled: _ddIsEarlyFlakeDetectionEnabled,
@@ -187,6 +192,11 @@ function getSortWrapper (sort) {
187192
let knownTests = {}
188193
let testManagementTests = {}
189194

195+
// console.log('this.ctx.vitest', this.ctx.vitest)
196+
// console.log('this.ctx.rpc', this.ctx.rpc)
197+
console.log('__vitest_worker__', global.__vitest_worker__)
198+
// console.log('this.ctx.getCoreWorkspaceProject()', this.ctx.getCoreWorkspaceProject())
199+
// console.log('this.ctx', this)
190200
try {
191201
const { err, libraryConfig } = await getChannelPromise(libraryConfigurationCh)
192202
if (!err) {
@@ -262,24 +272,25 @@ function getSortWrapper (sort) {
262272
log.warn('Could not send Dynamic Instrumentation configuration to workers.')
263273
}
264274
}
265-
266-
if (isTestManagementTestsEnabled) {
267-
const { err, testManagementTests: receivedTestManagementTests } = await getChannelPromise(testManagementTestsCh)
268-
if (!err) {
269-
testManagementTests = receivedTestManagementTests
270-
try {
271-
const workspaceProject = this.ctx.getCoreWorkspaceProject()
272-
workspaceProject._provided._ddIsTestManagementTestsEnabled = isTestManagementTestsEnabled
273-
workspaceProject._provided._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
274-
workspaceProject._provided._ddTestManagementTests = testManagementTests
275-
} catch {
276-
log.warn('Could not send test management tests to workers so Test Management will not work.')
277-
}
278-
} else {
279-
isTestManagementTestsEnabled = false
280-
log.error('Could not get test management tests.')
281-
}
282-
}
275+
debugger
276+
277+
// if (isTestManagementTestsEnabled) {
278+
// const { err, testManagementTests: receivedTestManagementTests } = await getChannelPromise(testManagementTestsCh)
279+
// if (!err) {
280+
// testManagementTests = receivedTestManagementTests
281+
// try {
282+
// const workspaceProject = this.ctx.getCoreWorkspaceProject()
283+
// workspaceProject._provided._ddIsTestManagementTestsEnabled = isTestManagementTestsEnabled
284+
// workspaceProject._provided._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
285+
// workspaceProject._provided._ddTestManagementTests = testManagementTests
286+
// } catch {
287+
// log.warn('Could not send test management tests to workers so Test Management will not work.')
288+
// }
289+
// } else {
290+
// isTestManagementTestsEnabled = false
291+
// log.error('Could not get test management tests.')
292+
// }
293+
// }
283294

284295
let testCodeCoverageLinesTotal
285296

@@ -344,6 +355,47 @@ function getCreateCliWrapper (vitestPackage, frameworkVersion) {
344355
return vitestPackage
345356
}
346357

358+
359+
// UNUSED RIGHT NOW, but we can use it to bind the async resource to the test fn
360+
// getFn is what's used to get the test fn to run it with vitest:
361+
// https://github.com/vitest-dev/vitest/blob/0cbad1b0d0d56f1ec60f8496678d1435f8bb8977/packages/runner/src/run.ts#L315-L321
362+
let getFn = null
363+
364+
// run in workers only
365+
addHook({
366+
name: '@vitest/runner',
367+
versions: ['>=1.6.0'],
368+
file: 'dist/index.js'
369+
}, (suitePackage) => {
370+
getFn = suitePackage.getFn
371+
372+
return suitePackage
373+
})
374+
375+
addHook({
376+
name: 'tinypool',
377+
versions: ['>=1.0.0'],
378+
file: 'dist/index.js'
379+
}, (TinyPool) => {
380+
debugger
381+
// we can pass handle here to the worker, and then use it to send messages to the main process
382+
shimmer.wrap(TinyPool.prototype, 'run', run => function (_, { channel }) {
383+
const res = run.apply(this, arguments)
384+
385+
this.threads.forEach(thread => {
386+
thread.process.on('message', (message) => {
387+
if (message.__tinypool_worker_message__ && message.data) {
388+
workerReporterCh.publish(message.data)
389+
}
390+
})
391+
})
392+
393+
return res
394+
})
395+
396+
return TinyPool
397+
})
398+
347399
addHook({
348400
name: 'vitest',
349401
versions: ['>=1.6.0'],
@@ -354,6 +406,7 @@ addHook({
354406
// `onBeforeRunTask` is run before any repetition or attempt is run
355407
// `onBeforeRunTask` is an async function
356408
shimmer.wrap(VitestTestRunner.prototype, 'onBeforeRunTask', onBeforeRunTask => function (task) {
409+
// console.log('on before run task', process.env)
357410
const testName = getTestName(task)
358411

359412
const {
@@ -420,6 +473,7 @@ addHook({
420473
// `onAfterRunTask` is run after all repetitions or attempts are run
421474
// `onAfterRunTask` is an async function
422475
shimmer.wrap(VitestTestRunner.prototype, 'onAfterRunTask', onAfterRunTask => function (task) {
476+
// console.log('task', task)
423477
const { isEarlyFlakeDetectionEnabled, isTestManagementTestsEnabled } = getProvidedContext()
424478

425479
if (isTestManagementTestsEnabled) {
@@ -819,6 +873,7 @@ addHook({
819873

820874
testSuiteFinishCh.publish({ status: testSuiteResult.state, onFinish, ...testSuiteCtx.currentStore })
821875

876+
// console.log('test usite finish!')
822877
// TODO: fix too frequent flushes
823878
await onFinishPromise
824879

packages/datadog-plugin-vitest/src/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const {
3535
TELEMETRY_TEST_SESSION
3636
} = require('../../dd-trace/src/ci-visibility/telemetry')
3737
const { DD_MAJOR } = require('../../../version')
38+
const id = require('../../dd-trace/src/id')
3839

3940
// Milliseconds that we subtract from the error test duration
4041
// so that they do not overlap with the following test
@@ -386,6 +387,22 @@ class VitestPlugin extends CiPlugin {
386387
})
387388
this.tracer._exporter.flush(onFinish)
388389
})
390+
391+
this.addSub('ci:vitest:worker-report:trace', (traces) => {
392+
// it has no test session or test module id so there are hanging
393+
const formattedTraces = JSON.parse(traces).map(trace => {
394+
return trace.map(span => ({
395+
...span,
396+
span_id: id(span.span_id),
397+
trace_id: id(span.trace_id),
398+
parent_id: id(span.parent_id)
399+
}))
400+
})
401+
402+
formattedTraces.forEach(trace => {
403+
this.tracer._exporter.export(trace)
404+
})
405+
})
389406
}
390407

391408
getTestProperties (testManagementTests, testSuite, testName) {

packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const {
77
CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
88
MOCHA_WORKER_TRACE_PAYLOAD_CODE,
99
JEST_WORKER_LOGS_PAYLOAD_CODE,
10-
PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE
10+
PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE,
11+
VITEST_WORKER_TRACE_PAYLOAD_CODE
1112
} = require('../../../plugins/util/test')
1213

1314
function getInterprocessTraceCode () {
@@ -23,6 +24,9 @@ function getInterprocessTraceCode () {
2324
if (process.env.DD_PLAYWRIGHT_WORKER) {
2425
return PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE
2526
}
27+
if (process.env.VITEST_WORKER_ID) {
28+
return VITEST_WORKER_TRACE_PAYLOAD_CODE
29+
}
2630
return null
2731
}
2832

packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,19 @@ class Writer {
3434
// See cucumber code:
3535
// https://github.com/cucumber/cucumber-js/blob/5ce371870b677fe3d1a14915dc535688946f734c/src/runtime/parallel/run_worker.ts#L13
3636
if (process.send) { // it only works if process.send is available
37-
process.send([this._interprocessCode, data], () => {
38-
onDone()
39-
})
37+
if (process.env.TINYPOOL_WORKER_ID) {
38+
// in vitest we have to trick the main process into thinking these are messages from
39+
// tinypool so they are not rejected
40+
process.send({ __tinypool_worker_message__: true, data }, () => {
41+
onDone()
42+
})
43+
} else {
44+
process.send([this._interprocessCode, data], () => {
45+
onDone()
46+
})
47+
}
4048
}
49+
// onDone()
4150
}
4251
}
4352

packages/dd-trace/src/exporter.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module.exports = name => {
2121
case exporters.CUCUMBER_WORKER:
2222
case exporters.MOCHA_WORKER:
2323
case exporters.PLAYWRIGHT_WORKER:
24+
case exporters.VITEST_WORKER:
2425
return require('./ci-visibility/exporters/test-worker')
2526
default:
2627
return inAWSLambda && !usingLambdaExtension ? require('./exporters/log') : require('./exporters/agent')

packages/dd-trace/src/plugins/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ module.exports = {
6969
get 'mocha-each' () { return require('../../../datadog-plugin-mocha/src') },
7070
get vitest () { return require('../../../datadog-plugin-vitest/src') },
7171
get workerpool () { return require('../../../datadog-plugin-mocha/src') },
72+
get tinypool () { return require('../../../datadog-plugin-vitest/src') },
7273
get moleculer () { return require('../../../datadog-plugin-moleculer/src') },
7374
get mongodb () { return require('../../../datadog-plugin-mongodb-core/src') },
7475
get 'mongodb-core' () { return require('../../../datadog-plugin-mongodb-core/src') },

0 commit comments

Comments
 (0)