fix: Calculate stats for streaming responses#64
Conversation
Fixed the /v1/routing/stats streaming zero-usage bug by adding a stream-wrapping helper in switchyard-components-v2 and wiring it into all four profiles. Mostly a port from v1 switchyard-components. Includes unit test that reproduces the bug against random routing profile. Closes: #55 Closes: #18 Assisted-by: Claude:Opus 4.7 High Signed-off-by: Graham King <grahamk@nvidia.com>
WalkthroughThe v2 components add shared buffered and streaming token-usage recording. LLM routing, passthrough, random routing, and stage routing use the helper, which wraps provider streams and records usage when available. Random routing adds coverage for delayed streaming usage events. ChangesStreaming usage recording
Estimated code review effort: 4 (Complex) | ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
crates/switchyard-components-v2/src/stats_recording.rs (1)
109-170: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing test coverage for
wrap_openai_responsesandwrap_anthropic.Only the
OpenAiStream/wrap_openai_chatpath is exercised (via the new test inrandom_routing.rs). This file has no#[cfg(test)]module, and the other two streaming variants —wrap_openai_responsesandwrap_anthropic(with its distinct accumulator-based commit logic) — are untested in the provided context, despite being core to the fix described by this PR.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/switchyard-components-v2/src/stats_recording.rs` around lines 109 - 170, Add a #[cfg(test)] module in stats_recording.rs covering both wrap_openai_responses and wrap_anthropic. Exercise representative usage-bearing stream events, consume the wrapped streams, and assert each path records usage once with the expected accumulated values, including Anthropic’s accumulator-based commit behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/switchyard-components-v2/src/stats_recording.rs`:
- Around line 76-170: Add concise doc comments to wrap_openai_chat,
wrap_openai_responses, and wrap_anthropic describing when usage is recorded,
that stream events are forwarded unchanged, and the differing single-shot versus
accumulator-driven commit behavior, including why only the OpenAI wrappers use a
committed guard.
- Around line 172-189: The record_usage function currently measures elapsed time
too late for streaming responses. Capture the backend elapsed latency
immediately after the backend call returns, pass that fixed value through the
stream wrappers, and update record_usage to use it when calculating
total_latency_ms and routing_overhead_ms instead of calling
profile_started_at.elapsed().
---
Nitpick comments:
In `@crates/switchyard-components-v2/src/stats_recording.rs`:
- Around line 109-170: Add a #[cfg(test)] module in stats_recording.rs covering
both wrap_openai_responses and wrap_anthropic. Exercise representative
usage-bearing stream events, consume the wrapped streams, and assert each path
records usage once with the expected accumulated values, including Anthropic’s
accumulator-based commit behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: f764206e-306c-4894-b56c-c737bbd5f106
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock,!Cargo.lock
📒 Files selected for processing (7)
crates/switchyard-components-v2/Cargo.tomlcrates/switchyard-components-v2/src/lib.rscrates/switchyard-components-v2/src/profiles/llm_routing.rscrates/switchyard-components-v2/src/profiles/passthrough.rscrates/switchyard-components-v2/src/profiles/random_routing.rscrates/switchyard-components-v2/src/profiles/stage_router.rscrates/switchyard-components-v2/src/stats_recording.rs
- Calculate latency when we get the first token, in streaming cases. Nice catch Code Rabbit! - Add doc comments to new functions. Signed-off-by: Graham King <grahamk@nvidia.com>
That's more precise, it include sub-millis. Codex is nit picking me. Signed-off-by: Graham King <grahamk@nvidia.com>
|
LGTM. Can we make sure to comment on / close #21 that this fix is going in so that PR can be closed? |
Fixed the /v1/routing/stats streaming zero-usage bug by adding a stream-wrapping helper in switchyard-components-v2 and wiring it into all four profiles. Mostly a port from v1 switchyard-components.
Includes unit test that reproduces the bug against random routing profile.
Closes: #55
Closes: #18
Assisted-by: Claude:Opus 4.7 High
Summary by CodeRabbit
New Features
Bug Fixes