-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
test(e2e/node-eve): Assert a manual span nests under gen_ai.execute_tool #24330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,17 @@ | ||
| import * as Sentry from '@sentry/node'; | ||
| import { defineTool } from 'eve/tools'; | ||
| import { z } from 'zod'; | ||
|
|
||
| export default defineTool({ | ||
| description: 'Get the current weather for a city.', | ||
| inputSchema: z.object({ city: z.string().min(1) }), | ||
| async execute({ city }) { | ||
| return { city, condition: 'Sunny', temperatureC: 22 }; | ||
| // Manual instrumentation inside a tool call: eve runs `execute` while the | ||
| // SDK's `gen_ai.execute_tool` span is active, so this user span should nest | ||
| // under it. The e2e test asserts that parent/child link. | ||
| return Sentry.startSpan( | ||
| { name: 'resolve-weather', op: 'gen_ai.tool.manual', attributes: { 'weather.city': city } }, | ||
| () => ({ city, condition: 'Sunny', temperatureC: 22 }), | ||
| ); | ||
| }, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,7 +29,7 @@ test('captures Vercel AI agent spans (invoke_agent, generate_content, execute_to | |
| const traceSpansPromise = collectStreamedSpans( | ||
| APP, | ||
| spansOfTrace => | ||
| ['gen_ai.invoke_agent', 'gen_ai.generate_content', 'gen_ai.execute_tool'].every(op => | ||
| ['gen_ai.invoke_agent', 'gen_ai.generate_content', 'gen_ai.execute_tool', 'gen_ai.tool.manual'].every(op => | ||
| spansOfTrace.some(span => getSpanOp(span) === op), | ||
| ) && spansOfTrace.some(isAgentServerSpan), | ||
| ); | ||
|
|
@@ -66,6 +66,16 @@ test('captures Vercel AI agent spans (invoke_agent, generate_content, execute_to | |
| // The tool returns `{ city, condition: 'Sunny', temperatureC: 22 }`. | ||
| expect(executeTool?.attributes?.['gen_ai.tool.call.result']?.value).toContain('Sunny'); | ||
|
|
||
| // `get_weather` wraps its work in a manual `Sentry.startSpan`. Because eve runs | ||
| // the tool while the SDK's `execute_tool` span is active, that user span nests | ||
| // directly under it β this is the manual-instrumentation-inside-a-tool case. | ||
| const manualSpan = traceSpans.find(span => getSpanOp(span) === 'gen_ai.tool.manual'); | ||
| expect(manualSpan?.name).toBe('resolve-weather'); | ||
| expect(manualSpan?.attributes?.['weather.city']?.value).toBe('Paris'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The test assertion Suggested FixChange the assertion from Prompt for AI AgentDid we get this right? π / π to inform future reviews. |
||
| expect(manualSpan?.is_segment).toBe(false); | ||
| expect(manualSpan?.trace_id).toBe(executeTool?.trace_id); | ||
| expect(manualSpan?.parent_span_id).toBe(executeTool?.span_id); | ||
|
|
||
| // `agent/hooks/sentry.ts` sets the eve session id as the conversation id via | ||
| // `Sentry.eveConversationHook()`, so every gen_ai span in the turn is tagged with it β that is | ||
| // what links a multi-turn session (each turn is its own trace) into one Sentry conversation. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: The test may hang indefinitely if the
'gen_ai.tool.manual'span is not emitted, as the completion predicate incollectStreamedSpanswill never resolve.Severity: MEDIUM
Suggested Fix
Add a timeout to the
collectStreamedSpansutility or the specific test case. This will ensure the test fails quickly with a clear error message if the required spans are not received within a reasonable time, rather than hanging.Prompt for AI Agent
Did we get this right? π / π to inform future reviews.