Skip to content

feat(llm): nest OpenRouter Broadcast traces under the calling span - #829

Merged
JeremyFunk merged 1 commit into
mainfrom
feat/openrouter-broadcast-trace-link
Sep 10, 2026
Merged

JeremyFunk merged 1 commit into
mainfrom
feat/openrouter-broadcast-trace-link

Conversation

@JeremyFunk

@JeremyFunk JeremyFunk commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • OpenRouter Broadcast previously arrived as a separate openrouter trace per LLM call, linked to ours only by session_id (doubled session usage until fix(agent-sessions): count a model call's usage once — nested buckets, gateway mirrors, sub-steps #766's response-id dedupe).
  • Verified against prod (2026-09-10): the Broadcast OTLP exporter uses the request's trace.trace_id / trace.parent_span_id verbatim as W3C ids.
  • withUsageAccounting → withPerCallFields: the same HTTP-client body transform now also merges the current span's traceId/spanId into trace, keeping the per-layer trace_name. No span in scope → only usage is spliced.
  • Result: OpenRouter's LLM Generation + provider attempt N spans nest under Maple's chat span, so the waterfall shows provider fallbacks and deepestReporterSum nets the usage within one trace.

Test plan

  • Llm.test.ts: trace_id matches the enclosing span, parent_span_id is 16-hex, usage.include intact (21/21)
  • After deploy: one real chat, ServiceName='openrouter' rows share the chat span's TraceId; Agent Sessions totals not doubled

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Summary by CodeRabbit

  • Enhancements
    • OpenRouter requests now include usage accounting information.
    • Request traces now preserve existing trace details and include the current parent span context.
    • Requests remain unchanged if transformation fails.

OpenRouter's Broadcast exporter uses the request's trace.trace_id and
trace.parent_span_id verbatim as W3C ids (verified against prod on
2026-09-10). Stamp the current span's ids on every OpenRouter chat
request, in the same HTTP-client transform that adds usage accounting,
so the LLM Generation trace it emits (provider attempts, fallbacks,
router latency) lands inside Maple's own trace instead of arriving as a
twin trace that only shares a session id.
@coderabbitai

coderabbitai Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 37e683db-5e7a-4216-8962-ccc6cf231d1e

📥 Commits

Reviewing files that changed from the base of the PR and between e84ccc1 and 2b83ab2.

📒 Files selected for processing (2)
  • apps/api/src/platform/Llm.test.ts
  • apps/api/src/platform/Llm.ts

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

OpenRouter request transformation now injects usage reporting and current span identifiers. Existing trace fields remain intact. A live test verifies trace propagation, parent span ID format, and usage metadata.

Changes

OpenRouter per-call fields

Layer / File(s) Summary
Per-call request transformation
apps/api/src/platform/Llm.ts
The transformer adds usage: { include: true } and merges current trace and parent span identifiers into JSON object request bodies. It preserves unsupported requests and returns the original request when transformation fails.
Client wiring and trace validation
apps/api/src/platform/Llm.ts, apps/api/src/platform/Llm.test.ts
The OpenRouter client uses withPerCallFields. A live test verifies trace IDs, parent span IDs, and usage inclusion metadata.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Severity of issue fixed: Low

Sequence Diagram(s)

sequenceDiagram
  participant ChatSpan
  participant OpenRouterClient
  participant withPerCallFields
  participant OpenRouter
  ChatSpan->>OpenRouterClient: create request within chat span
  OpenRouterClient->>withPerCallFields: transform JSON request body
  withPerCallFields->>ChatSpan: read trace and parent span identifiers
  ChatSpan-->>withPerCallFields: return span identifiers
  withPerCallFields-->>OpenRouterClient: return request with usage and trace fields
  OpenRouterClient->>OpenRouter: send transformed request
Loading

Suggested reviewers: makisuo

Merge Risk: ⚪ Minimal · up to 2b83a

OpenRouter requests now nest under the calling chat trace while preserving usage metadata. The supplied validation covers the changed behavior, so the change is mergeable.

🚥 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 clearly and concisely describes the main change: nesting OpenRouter Broadcast traces under the calling span.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/openrouter-broadcast-trace-link

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.

@JeremyFunk
JeremyFunk merged commit c25dde0 into main Sep 10, 2026
28 checks passed
@JeremyFunk
JeremyFunk deleted the feat/openrouter-broadcast-trace-link branch September 10, 2026 20:11
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.

1 participant