Skip to content

Commit 69ef616

Browse files
committed
cleanup
1 parent 0a62374 commit 69ef616

1 file changed

Lines changed: 57 additions & 73 deletions

File tree

  • dev-packages/node-integration-tests/suites/tracing/vercelai/v6_v7

dev-packages/node-integration-tests/suites/tracing/vercelai/v6_v7/test.ts

Lines changed: 57 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -530,45 +530,37 @@ describe.each(matrix)('Vercel AI integration (version %s)', (version, vercelAiVe
530530
// A single model instance shared by two concurrent `streamText` calls carries only one
531531
// captured-parent slot, so both model calls must still land under their own `invoke_agent` — not
532532
// collapse onto whichever operation resolved the shared model last.
533-
// `ai` v7 publishes the top-level `streamText`/`step` channel events through a code path that
534-
// loads `node:diagnostics_channel` via `process.getBuiltinModule()`, which was only added in
535-
// Node 20.16 / 22.3 and never backported to Node 18. On Node 18 that lookup returns undefined,
536-
// so the `streamText` event is never published and no `invoke_agent` span is created. The
537-
// non-streaming ops load the channel via dynamic `import()` and are unaffected.
538-
test.skipIf(version === '7' && nodeVersion === 18)(
539-
'parents concurrent streamText calls that share one model instance correctly',
540-
async () => {
541-
await createRunner()
542-
.expect({ transaction: { transaction: 'main' } })
543-
.expect({
544-
span: container => {
545-
const invokeAgents = container.items.filter(
546-
span => span.attributes?.['sentry.op']?.value === 'gen_ai.invoke_agent',
547-
);
548-
const generateContents = container.items.filter(
549-
span => span.attributes?.['sentry.op']?.value === 'gen_ai.generate_content',
550-
);
551-
552-
// Two concurrent operations -> two invoke_agent + two generate_content spans.
553-
expect(invokeAgents).toHaveLength(2);
554-
expect(generateContents).toHaveLength(2);
555-
556-
const agentSpanIds = new Set(invokeAgents.map(span => span.span_id));
557-
558-
// Each model call lands under an invoke_agent span...
559-
for (const span of generateContents) {
560-
expect(agentSpanIds.has(span.parent_span_id!)).toBe(true);
561-
}
562-
// ...a distinct one each (no cross-attribution despite the shared model instance)...
563-
expect(new Set(generateContents.map(span => span.parent_span_id)).size).toBe(2);
564-
// ...and both operations sit under the same `main` parent.
565-
expect(new Set(invokeAgents.map(span => span.parent_span_id)).size).toBe(1);
566-
},
567-
})
568-
.start()
569-
.completed();
570-
},
571-
);
533+
test('parents concurrent streamText calls that share one model instance correctly', async () => {
534+
await createRunner()
535+
.expect({ transaction: { transaction: 'main' } })
536+
.expect({
537+
span: container => {
538+
const invokeAgents = container.items.filter(
539+
span => span.attributes?.['sentry.op']?.value === 'gen_ai.invoke_agent',
540+
);
541+
const generateContents = container.items.filter(
542+
span => span.attributes?.['sentry.op']?.value === 'gen_ai.generate_content',
543+
);
544+
545+
// Two concurrent operations -> two invoke_agent + two generate_content spans.
546+
expect(invokeAgents).toHaveLength(2);
547+
expect(generateContents).toHaveLength(2);
548+
549+
const agentSpanIds = new Set(invokeAgents.map(span => span.span_id));
550+
551+
// Each model call lands under an invoke_agent span...
552+
for (const span of generateContents) {
553+
expect(agentSpanIds.has(span.parent_span_id!)).toBe(true);
554+
}
555+
// ...a distinct one each (no cross-attribution despite the shared model instance)...
556+
expect(new Set(generateContents.map(span => span.parent_span_id)).size).toBe(2);
557+
// ...and both operations sit under the same `main` parent.
558+
expect(new Set(invokeAgents.map(span => span.parent_span_id)).size).toBe(1);
559+
},
560+
})
561+
.start()
562+
.completed();
563+
});
572564
},
573565
{
574566
additionalDependencies: {
@@ -582,40 +574,32 @@ describe.each(matrix)('Vercel AI integration (version %s)', (version, vercelAiVe
582574
'scenario-stream-text.mjs',
583575
'instrument.mjs',
584576
(createRunner, test) => {
585-
// `ai` v7 publishes the top-level `streamText`/`step` channel events through a code path that
586-
// loads `node:diagnostics_channel` via `process.getBuiltinModule()`, which was only added in
587-
// Node 20.16 / 22.3 and never backported to Node 18. On Node 18 that lookup returns undefined,
588-
// so the `streamText` event is never published and no `invoke_agent` span is created. The
589-
// non-streaming ops load the channel via dynamic `import()` and are unaffected.
590-
test.skipIf(version === '7' && nodeVersion === 18)(
591-
'creates streamText spans with the model call parented to invoke_agent',
592-
async () => {
593-
await createRunner()
594-
.expect({ transaction: { transaction: 'main' } })
595-
.expect({
596-
span: container => {
597-
// Every emitted gen_ai span carries the version-appropriate origin.
598-
container.items
599-
.filter(s => String(s.attributes?.['sentry.op']?.value ?? '').startsWith('gen_ai.'))
600-
.forEach(s => expect(s.attributes?.['sentry.origin']?.value).toBe(expectedOrigin));
601-
const invokeAgent = container.items.find(
602-
span => span.attributes?.['sentry.op']?.value === 'gen_ai.invoke_agent',
603-
)!;
604-
expect(invokeAgent).toBeDefined();
605-
expect(invokeAgent.attributes?.['vercel.ai.operationId']?.value).toBe('ai.streamText');
606-
607-
const generateContent = container.items.find(
608-
span => span.attributes?.['sentry.op']?.value === 'gen_ai.generate_content',
609-
)!;
610-
expect(generateContent).toBeDefined();
611-
expect(generateContent.parent_span_id).toBe(invokeAgent.span_id);
612-
expect(generateContent.attributes?.['vercel.ai.operationId']?.value).toBe('ai.streamText.doStream');
613-
},
614-
})
615-
.start()
616-
.completed();
617-
},
618-
);
577+
test('creates streamText spans with the model call parented to invoke_agent', async () => {
578+
await createRunner()
579+
.expect({ transaction: { transaction: 'main' } })
580+
.expect({
581+
span: container => {
582+
// Every emitted gen_ai span carries the version-appropriate origin.
583+
container.items
584+
.filter(s => String(s.attributes?.['sentry.op']?.value ?? '').startsWith('gen_ai.'))
585+
.forEach(s => expect(s.attributes?.['sentry.origin']?.value).toBe(expectedOrigin));
586+
const invokeAgent = container.items.find(
587+
span => span.attributes?.['sentry.op']?.value === 'gen_ai.invoke_agent',
588+
)!;
589+
expect(invokeAgent).toBeDefined();
590+
expect(invokeAgent.attributes?.['vercel.ai.operationId']?.value).toBe('ai.streamText');
591+
592+
const generateContent = container.items.find(
593+
span => span.attributes?.['sentry.op']?.value === 'gen_ai.generate_content',
594+
)!;
595+
expect(generateContent).toBeDefined();
596+
expect(generateContent.parent_span_id).toBe(invokeAgent.span_id);
597+
expect(generateContent.attributes?.['vercel.ai.operationId']?.value).toBe('ai.streamText.doStream');
598+
},
599+
})
600+
.start()
601+
.completed();
602+
});
619603
},
620604
{
621605
additionalDependencies: {

0 commit comments

Comments
 (0)