Skip to content

fix: check ai.operationId attribute for operation name transformation#891

Open
obs-gh-trevorColby wants to merge 2 commits intotraceloop:mainfrom
obs-gh-trevorColby:fix/operation-name-timing-bug
Open

fix: check ai.operationId attribute for operation name transformation#891
obs-gh-trevorColby wants to merge 2 commits intotraceloop:mainfrom
obs-gh-trevorColby:fix/operation-name-timing-bug

Conversation

@obs-gh-trevorColby
Copy link

@obs-gh-trevorColby obs-gh-trevorColby commented Feb 24, 2026

Summary

This PR fixes an issue where the gen_ai.operation.name attribute was not being set for AI SDK spans due to a timing bug in the span name transformation.

Problem

The transformOperationName function checks the span name to determine the gen_ai.operation.name attribute (e.g., "chat" for generateText operations). However, by the time this function runs in onSpanEnd, the span name has already been transformed by transformAiSdkSpanNames in onSpanStart.

Transformation timeline:

  1. onSpanStarttransformAiSdkSpanNames runs → span name changes from "ai.generateText" to "run.ai"
  2. onSpanEndtransformOperationName runs → checks span name for "generateText"never matches

Because the span name has already been transformed to "run.ai", the check for "generateText" fails and gen_ai.operation.name is never set.

Solution

This fix checks the ai.operationId attribute first, which is set by the Vercel AI SDK and contains the original operation ID (e.g., "ai.generateText"). This attribute is not transformed and reliably contains the original operation identifier.

Updated logic:

  1. Check ai.operationId attribute (set by Vercel AI SDK, contains original operation ID)
  2. Fall back to span name if ai.operationId is not available
  3. Use the resulting value to determine operation name

Example

Before (broken)

Span name: "run.ai" (already transformed)
ai.operationId: "ai.generateText"
gen_ai.operation.name: undefined  ❌

After (fixed)

Span name: "run.ai" (already transformed)
ai.operationId: "ai.generateText"
gen_ai.operation.name: "chat"  ✅

Backwards Compatibility

  • The function still checks the span name as a fallback if ai.operationId is not present
  • Tool call spans still work (they check both nameToCheck and spanName for .tool suffix)

Related Issue

Fixes #882


Pull Request opened by Augment Code with guidance from the PR author


Important

Fixes gen_ai.operation.name setting by checking ai.operationId before span name in transformOperationName function.

  • Behavior:
    • Fixes transformOperationName in ai-sdk-transformations.ts to check ai.operationId before span name for setting gen_ai.operation.name.
    • Ensures gen_ai.operation.name is set correctly even if span name is transformed.
  • Logic:
    • Checks ai.operationId first, falls back to span name if not available.
    • Handles cases for generateText, streamText, generateObject, streamObject, and tool calls.
  • Misc:
    • Updates comments and documentation in ai-sdk-transformations.ts for clarity.

This description was created by Ellipsis for e9ba33a. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • Improvements
    • Enhanced AI operation tracing with improved operation name derivation and type detection for better observability of chat and tool execution operations.

The transformOperationName function checks the span name to determine the
gen_ai.operation.name attribute. However, by the time this function runs
in onSpanEnd, the span name has already been transformed (e.g., from
"ai.generateText" to "run.ai") by transformAiSdkSpanNames in onSpanStart.

This means the check for 'generateText', 'streamText', etc. never matches,
and the gen_ai.operation.name attribute is never set to 'chat'.

This fix checks the ai.operationId attribute first, which is set by the
Vercel AI SDK and contains the original operation ID (e.g., "ai.generateText").
This allows the function to correctly identify the operation type.

Fixes traceloop#882
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Warning

Rate limit exceeded

@obs-gh-trevorColby has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 12 minutes and 14 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between e9ba33a and 526fb88.

📒 Files selected for processing (1)
  • packages/traceloop-sdk/src/lib/tracing/ai-sdk-transformations.ts
📝 Walkthrough

Walkthrough

Added transformOperationName helper function to derive gen_ai.operation.name by preferring ai.operationId attribute over the pre-transformed span name, enabling proper operation type detection for AI SDK transformations (chat vs. execute_tool).

Changes

Cohort / File(s) Summary
AI SDK Operation Name Derivation
packages/traceloop-sdk/src/lib/tracing/ai-sdk-transformations.ts
Introduced transformOperationName helper to resolve operation names from ai.operationId attribute as primary source, with fallback to span name. Detects operation types (chat, execute_tool) from operation identifiers including generateText, streamText, generateObject, streamObject, and tool execution patterns.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A helper hops in, quick and spry,
To catch the operationId on the fly,
Before the name transforms away,
Now gen_ai glows bright as day!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: checking ai.operationId attribute to fix operation name transformation, which is the core solution to the timing bug.
Linked Issues check ✅ Passed The code changes directly address issue #882 by implementing the suggested third approach: checking ai.operationId before span name to bypass the timing issue with span name transformation.
Out of Scope Changes check ✅ Passed All changes focus on the transformOperationName helper function to fix the gen_ai.operation.name attribute setting, with no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed everything up to e9ba33a in 13 seconds. Click for details.
  • Reviewed 53 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 0 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.

Workflow ID: wflow_RYsirwZNEWXy8dqr

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/traceloop-sdk/src/lib/tracing/ai-sdk-transformations.ts`:
- Around line 508-520: operationId (from AI_OPERATION_ID) may be non-string
which makes nameToCheck.includes(...) throw; guard and coerce before using
includes by ensuring operationId is a string (e.g., check typeof operationId ===
"string" or coerce with String(operationId)) and only set nameToCheck to
operationId when it's a string, otherwise fall back to spanName, then run the
existing includes checks on nameToCheck; update the logic around
AI_OPERATION_ID, operationId, nameToCheck and the includes checks to perform
this type guard.
- Around line 505-508: Add the AI_OPERATION_ID constant to the SpanAttributes
export in SemanticAttributes.ts (e.g., add AI_OPERATION_ID: "ai.operationId" to
the SpanAttributes object/type) and then update ai-sdk-transformations.ts to
import that constant instead of using the hardcoded string; replace the local
const AI_OPERATION_ID = "ai.operationId" with an import of AI_OPERATION_ID from
`@traceloop/ai-semantic-conventions` and use that imported symbol when reading
attributes[AI_OPERATION_ID] in the existing logic.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ddb1241 and e9ba33a.

📒 Files selected for processing (1)
  • packages/traceloop-sdk/src/lib/tracing/ai-sdk-transformations.ts

Comment on lines 505 to 508
// Check ai.operationId attribute first (set by Vercel AI SDK)
// This is more reliable since span name may have been transformed already
const AI_OPERATION_ID = "ai.operationId";
const operationId = attributes[AI_OPERATION_ID] as string | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, locate the ai-semantic-conventions package
find . -type d -name "ai-semantic-conventions" | head -5

Repository: traceloop/openllmetry-js

Length of output: 102


🏁 Script executed:

# List files in ai-semantic-conventions to understand its structure
git ls-files packages/ai-semantic-conventions/ | head -20

Repository: traceloop/openllmetry-js

Length of output: 451


🏁 Script executed:

# Search for operationId references in ai-semantic-conventions
rg -n "operationId" packages/ai-semantic-conventions/ -S

Repository: traceloop/openllmetry-js

Length of output: 50


🏁 Script executed:

# Check the current imports in the file being reviewed
head -30 packages/traceloop-sdk/src/lib/tracing/ai-sdk-transformations.ts

Repository: traceloop/openllmetry-js

Length of output: 994


🏁 Script executed:

# Check the SemanticAttributes.ts in ai-semantic-conventions to see what constants are defined
cat packages/ai-semantic-conventions/src/SemanticAttributes.ts | head -100

Repository: traceloop/openllmetry-js

Length of output: 4224


🏁 Script executed:

# Look for all references to operationId in the entire repository
rg -n "operationId" --type ts --type tsx -S

Repository: traceloop/openllmetry-js

Length of output: 95


🏁 Script executed:

# Check the specific lines (505-508) in the file being reviewed
sed -n '500,520p' packages/traceloop-sdk/src/lib/tracing/ai-sdk-transformations.ts

Repository: traceloop/openllmetry-js

Length of output: 805


🏁 Script executed:

# Search for all content in SemanticAttributes.ts
cat packages/ai-semantic-conventions/src/SemanticAttributes.ts

Repository: traceloop/openllmetry-js

Length of output: 4520


🏁 Script executed:

# Search for operationId in all TypeScript files
rg -n "operationId" -t ts

Repository: traceloop/openllmetry-js

Length of output: 851


🏁 Script executed:

# Check the imports in ai-semantic-conventions index.ts
cat packages/ai-semantic-conventions/src/index.ts

Repository: traceloop/openllmetry-js

Length of output: 845


Add ai.operationId constant to @traceloop/ai-semantic-conventions and import it here.

This file must import AI/LLM semantic attribute constants from @traceloop/ai-semantic-conventions rather than hardcoding strings. The "ai.operationId" attribute is currently hardcoded at line 507. Add this constant to SpanAttributes in packages/ai-semantic-conventions/src/SemanticAttributes.ts (e.g., AI_OPERATION_ID: "ai.operationId"), then import and use it here to comply with the guideline.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/traceloop-sdk/src/lib/tracing/ai-sdk-transformations.ts` around
lines 505 - 508, Add the AI_OPERATION_ID constant to the SpanAttributes export
in SemanticAttributes.ts (e.g., add AI_OPERATION_ID: "ai.operationId" to the
SpanAttributes object/type) and then update ai-sdk-transformations.ts to import
that constant instead of using the hardcoded string; replace the local const
AI_OPERATION_ID = "ai.operationId" with an import of AI_OPERATION_ID from
`@traceloop/ai-semantic-conventions` and use that imported symbol when reading
attributes[AI_OPERATION_ID] in the existing logic.

The ai.operationId attribute may be non-string in some cases, which would
cause nameToCheck.includes() to throw a runtime error.

This fix adds a proper type guard to ensure operationId is a string before
using it, falling back to spanName if it's not a string.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gen_ai.operation.name attribute not set for AI SDK spans due to span name transformation timing

2 participants