Skip to content

Commit 19a148f

Browse files
JPeer264claude
andauthored
test(e2e): Port cloudflare-vercelai-v7 to span streaming (#23863)
Ports `cloudflare-vercelai-v7` to span streaming. The spec already asserted on streamed spans, so this only removes the static pin and a comment that described gen_ai extraction as a special case. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 3a9667e commit 19a148f

2 files changed

Lines changed: 40 additions & 28 deletions

File tree

dev-packages/e2e-tests/test-applications/cloudflare-vercelai-v7/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { MockLanguageModelV3 } from 'ai/test';
44

55
export default Sentry.withSentry(
66
(env: Env) => ({
7-
traceLifecycle: 'static',
87
dsn: env.E2E_TEST_DSN,
98
environment: 'qa',
109
tunnel: 'http://localhost:3031/',

dev-packages/e2e-tests/test-applications/cloudflare-vercelai-v7/tests/index.test.ts

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { expect, test } from '@playwright/test';
22
import { getSpanOp, waitForStreamedSpans } from '@sentry-internal/test-utils';
33

44
test('captures Vercel AI v7 spans with nodejs_compat using tracing channels', async ({ baseURL }) => {
5-
// gen_ai spans are extracted into a separate span v2 envelope item
65
const genAiSpansPromise = waitForStreamedSpans('cloudflare-vercelai-v7-compat', spans =>
76
spans.some(span => getSpanOp(span) === 'gen_ai.invoke_agent'),
87
);
@@ -13,30 +12,44 @@ test('captures Vercel AI v7 spans with nodejs_compat using tracing channels', as
1312

1413
const genAiSpans = await genAiSpansPromise;
1514

16-
expect(genAiSpans).toEqual(
17-
expect.arrayContaining([
18-
expect.objectContaining({
19-
name: 'invoke_agent',
20-
attributes: expect.objectContaining({
21-
'gen_ai.operation.name': { value: 'invoke_agent', type: 'string' },
22-
'gen_ai.usage.input_tokens': { value: 10, type: 'integer' },
23-
'gen_ai.usage.output_tokens': { value: 20, type: 'integer' },
24-
'gen_ai.usage.total_tokens': { value: 30, type: 'integer' },
25-
'sentry.op': { value: 'gen_ai.invoke_agent', type: 'string' },
26-
'sentry.origin': { value: 'auto.vercelai.channel', type: 'string' },
27-
}),
28-
}),
29-
expect.objectContaining({
30-
name: 'generate_content mock-model-id',
31-
attributes: expect.objectContaining({
32-
'gen_ai.operation.name': { value: 'generate_content', type: 'string' },
33-
'gen_ai.usage.input_tokens': { value: 10, type: 'integer' },
34-
'gen_ai.usage.output_tokens': { value: 20, type: 'integer' },
35-
'gen_ai.usage.total_tokens': { value: 30, type: 'integer' },
36-
'sentry.op': { value: 'gen_ai.generate_content', type: 'string' },
37-
'sentry.origin': { value: 'auto.vercelai.channel', type: 'string' },
38-
}),
39-
}),
40-
]),
41-
);
15+
const invokeAgentSpan = genAiSpans.find(span => getSpanOp(span) === 'gen_ai.invoke_agent');
16+
const generateContentSpan = genAiSpans.find(span => getSpanOp(span) === 'gen_ai.generate_content');
17+
18+
expect(invokeAgentSpan).toEqual({
19+
trace_id: expect.stringMatching(/^[a-f0-9]{32}$/),
20+
parent_span_id: expect.stringMatching(/^[a-f0-9]{16}$/),
21+
span_id: expect.stringMatching(/^[a-f0-9]{16}$/),
22+
name: 'invoke_agent',
23+
start_timestamp: expect.any(Number),
24+
end_timestamp: expect.any(Number),
25+
status: 'ok',
26+
is_segment: false,
27+
attributes: expect.objectContaining({
28+
'gen_ai.operation.name': { value: 'invoke_agent', type: 'string' },
29+
'gen_ai.usage.input_tokens': { value: 10, type: 'integer' },
30+
'gen_ai.usage.output_tokens': { value: 20, type: 'integer' },
31+
'gen_ai.usage.total_tokens': { value: 30, type: 'integer' },
32+
'sentry.op': { value: 'gen_ai.invoke_agent', type: 'string' },
33+
'sentry.origin': { value: 'auto.vercelai.channel', type: 'string' },
34+
}),
35+
});
36+
37+
expect(generateContentSpan).toEqual({
38+
trace_id: invokeAgentSpan!.trace_id,
39+
parent_span_id: invokeAgentSpan!.span_id,
40+
span_id: expect.stringMatching(/^[a-f0-9]{16}$/),
41+
name: 'generate_content mock-model-id',
42+
start_timestamp: expect.any(Number),
43+
end_timestamp: expect.any(Number),
44+
status: 'ok',
45+
is_segment: false,
46+
attributes: expect.objectContaining({
47+
'gen_ai.operation.name': { value: 'generate_content', type: 'string' },
48+
'gen_ai.usage.input_tokens': { value: 10, type: 'integer' },
49+
'gen_ai.usage.output_tokens': { value: 20, type: 'integer' },
50+
'gen_ai.usage.total_tokens': { value: 30, type: 'integer' },
51+
'sentry.op': { value: 'gen_ai.generate_content', type: 'string' },
52+
'sentry.origin': { value: 'auto.vercelai.channel', type: 'string' },
53+
}),
54+
});
4255
});

0 commit comments

Comments
 (0)