-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
fix(core): Set op on ended Vercel AI spans #18553
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
base: develop
Are you sure you want to change the base?
Conversation
chargome
left a comment
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.
Hey @jam3gw, thanks for opening a PR!
The code will need some refinement and also some tests before we can merge this in.
We're happy to take this over if you want, please let us know.
| if (name && (span.op === 'default' || !span.op)) { | ||
| if ( | ||
| name === 'ai.generateText' || | ||
| name === 'ai.streamText' || | ||
| name === 'ai.generateObject' || | ||
| name === 'ai.streamObject' || | ||
| name === 'ai.embed' || | ||
| name === 'ai.embedMany' | ||
| ) { | ||
| span.op = 'gen_ai.invoke_agent'; | ||
| } else if (name === 'ai.generateText.doGenerate') { | ||
| span.op = 'gen_ai.generate_text'; | ||
| } else if (name === 'ai.streamText.doStream') { | ||
| span.op = 'gen_ai.stream_text'; | ||
| } else if (name === 'ai.generateObject.doGenerate') { | ||
| span.op = 'gen_ai.generate_object'; | ||
| } else if (name === 'ai.streamObject.doStream') { | ||
| span.op = 'gen_ai.stream_object'; | ||
| } else if (name === 'ai.embed.doEmbed') { | ||
| span.op = 'gen_ai.embed'; | ||
| } else if (name === 'ai.embedMany.doEmbed') { | ||
| span.op = 'gen_ai.embed_many'; | ||
| } | ||
| } |
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.
I think a cleaner approach would be to determine the name with a map here.
| name === 'ai.embed' || | ||
| name === 'ai.embedMany' | ||
| ) { | ||
| span.op = 'gen_ai.invoke_agent'; |
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.
We're generally using constants for these attributes, you'll find other occurrences in this file.
| ) { | ||
| span.op = 'gen_ai.invoke_agent'; | ||
| } else if (name === 'ai.generateText.doGenerate') { | ||
| span.op = 'gen_ai.generate_text'; |
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.
op should be updated like this:
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, YOUR_AI_ATTRIBUTE);
Summary
span.opfor Vercel AI spans during ended-span processing when it is missing or stilldefault.onVercelAiSpanStartreturns early (for example, AI SDK attributes required for op mapping are not present at span start).Context
Fixes #18448.
PR #18471 relaxed the spanStart guard to require only
ai.model.id, but this can still be insufficient if the attributes needed for op mapping aren't reliably present at span start. SinceprocessEndedVercelAiSpanalready normalizes AI attributes on ended spans, it's a good place to also ensurespan.opis set.FAQ
Q: Why aren't these spans getting a
gen_ai.*op at span start? Is the user setup wrong?A: Usually nothing is wrong with the user setup. The integration sets
span.opin thespanStarthook, but it gates that work on AI SDK attributes being present at span start (for exampleai.model.id). In practice, the AI SDK / OpenTelemetry instrumentation may attach some of those attributes after the span has started (for example once the provider response/usage is known). In that caseonVercelAiSpanStartcan return early and the span remainsop=default. The ended-span event processor already runs after those attributes exist (it renames them togen_ai.*), so setting the op there provides the needed fallback for the AI Agents UI.Test plan
ai.*spans no longer haveop=defaultand are classified asgen_ai.*(and appear in AI Agents).