Skip to content

feat(server): expose stage router stats - #344

Merged
nachiketb-nvidia merged 9 commits into
mainfrom
nachiketb/feat-stage-router-v1-stats
Aug 11, 2026
Merged

feat(server): expose stage router stats#344
nachiketb-nvidia merged 9 commits into
mainfrom
nachiketb/feat-stage-router-v1-stats

Conversation

@nachiketb-nvidia

@nachiketb-nvidia nachiketb-nvidia commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What

  • add algorithm_stats.stage_router to GET /v1/stats
  • group routing decisions by decision source and semantic target name
  • summarize stage-router score, confidence, and input dimensions with count and mean
  • reset the JSON projection through POST /v1/stats/reset

Why

The stage router already emits standard OpenTelemetry counters and histograms, but the server did not expose a readable stage-router summary comparable to the deprecated Python server. This makes those values available without adding a custom metrics API to libsy or changing the canonical /metrics output.

How

  • gather typed metric families from the server's Prometheus registry
  • project stage-router metrics in a private, algorithm-specific server module
  • retain a server-local baseline so /v1/stats/reset does not reset process-lifetime OpenTelemetry metrics
  • define histogram boundaries with the stage-router instruments in libsy, so every host receives the same OpenTelemetry advice without duplicating algorithm knowledge in the server

Future algorithm projections can be added under stats/algorithms/ without changing the accumulator, server, Algorithm, or Driver APIs.

JSON Shape

Before this MR, /v1/stats did not include an algorithm_stats field.

After stage-router traffic, the new fragment looks like this (existing top-level stats fields omitted):

{
  "algorithm_stats": {
    "stage_router": {
      "routing_decisions": {
        "dimensions": {
          "total": 3,
          "targets": {
            "model/capable": 1,
            "model/efficient": 2
          }
        }
      },
      "scoring": {
        "score": { "count": 2, "mean": 0.125 },
        "confidence": { "count": 1, "mean": 0.75 },
        "dimensions": {
          "severity": { "count": 0, "mean": 0.0 },
          "spinning": { "count": 0, "mean": 0.0 },
          "exploring": { "count": 0, "mean": 0.0 },
          "production_intensity": { "count": 0, "mean": 0.0 }
        }
      }
    }
  }
}

After POST /v1/stats/reset, process-lifetime OpenTelemetry metrics remain intact while the JSON projection starts from a new baseline:

{
  "algorithm_stats": {
    "stage_router": {
      "routing_decisions": {},
      "scoring": {
        "score": { "count": 0, "mean": 0.0 },
        "confidence": { "count": 0, "mean": 0.0 },
        "dimensions": {
          "severity": { "count": 0, "mean": 0.0 },
          "spinning": { "count": 0, "mean": 0.0 },
          "exploring": { "count": 0, "mean": 0.0 },
          "production_intensity": { "count": 0, "mean": 0.0 }
        }
      }
    }
  }
}

What To Review

  • the additive algorithm_stats.stage_router JSON shape
  • grouping by decision_source and semantic target_name
  • baseline behavior across /v1/stats/reset
  • stage-router ownership of its OpenTelemetry histogram boundaries
  • the private per-algorithm server projection boundary

Validation

  • cargo test -p switchyard-libsy algorithms::util::stage::tests
  • cargo test -p switchyard-server stage_router_projection_preserves_decisions_scores_and_reset_baseline
  • cargo clippy -p switchyard-libsy -p switchyard-server --all-targets -- -D warnings
  • cargo fmt --all --check
  • git diff --check

No Python or live-provider tests were needed; this is isolated to Rust algorithm telemetry and server stats projection.

Signed-off-by: nachiketb <nachiketb@nvidia.com>
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

🚀 View preview at
https://NVIDIA-NeMo.github.io/Switchyard/pr-preview/pr-344/

Built to branch gh-pages at 2026-08-11 17:17 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Signed-off-by: nachiketb <nachiketb@nvidia.com>
Signed-off-by: nachiketb <nachiketb@nvidia.com>
Signed-off-by: nachiketb <nachiketb@nvidia.com>
Signed-off-by: nachiketb <nachiketb@nvidia.com>
Signed-off-by: nachiketb <nachiketb@nvidia.com>
Signed-off-by: nachiketb <nachiketb@nvidia.com>
@nachiketb-nvidia
nachiketb-nvidia marked this pull request as ready for review August 10, 2026 23:48
@nachiketb-nvidia
nachiketb-nvidia requested a review from a team as a code owner August 10, 2026 23:48
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

The server now collects stage-router counters and histograms through the shared Prometheus registry. /v1/stats includes serialized algorithm statistics with reset-aware snapshots. Documentation and integration tests cover the new response data.

Algorithm statistics

Layer / File(s) Summary
Stage-router metric projection
crates/switchyard-server/src/stats/algorithms/stage_router.rs
Stage-router counters and histograms are aggregated into reset-aware decision, scoring, confidence, and dimension snapshots. Integration tests validate the projections and reset behavior.
Algorithm metric registration
crates/switchyard-server/src/stats/algorithms.rs, crates/switchyard-server/src/stats.rs, crates/switchyard-server/src/metrics.rs
The statistics module exposes stage-router histogram buckets. The meter provider registers routing and algorithm-specific histogram views.
Accumulator and server integration
crates/switchyard-server/src/stats/accumulator.rs, crates/switchyard-server/src/lib.rs, crates/switchyard-server/tests/server.rs
StatsAccumulator uses the shared registry and configured algorithms. Snapshots include algorithm_stats, and reset clears algorithm state with the other statistics.
Stats response documentation
crates/switchyard-server/README.md, docs/routing_algorithms/stage_router_routing.md
Documentation describes per-model usage, stage-router decision grouping, histograms, reset behavior, and process-lifetime metrics.

Estimated code review effort: 4 (Complex) | ~45 minutes

Poem

I’m a rabbit with metrics to chart,
Stage-router numbers now play their part.
Counters hop, histograms grow,
Resets mark the stats flow.
/v1/stats now shows the art!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: exposing stage-router statistics through the server.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
crates/switchyard-server/src/stats/algorithms.rs (1)

62-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the crate-visible bucket registry.

Add concise /// documentation for histogram_buckets. State that it returns explicit histogram boundaries for supported algorithm instruments. As per coding guidelines, add concise /// documentation for public Rust items.

🤖 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-server/src/stats/algorithms.rs` around lines 62 - 64, Add
concise Rust doc comments to the crate-visible histogram_buckets function,
stating that it returns explicit histogram boundaries for supported algorithm
instruments. Keep the existing delegation to stage_router::histogram_buckets
unchanged.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@crates/switchyard-server/src/stats/algorithms.rs`:
- Around line 62-64: Add concise Rust doc comments to the crate-visible
histogram_buckets function, stating that it returns explicit histogram
boundaries for supported algorithm instruments. Keep the existing delegation to
stage_router::histogram_buckets unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f755d8a6-976b-4264-807e-23788a1006ec

📥 Commits

Reviewing files that changed from the base of the PR and between fb3fc30 and d250577.

📒 Files selected for processing (9)
  • crates/switchyard-server/README.md
  • crates/switchyard-server/src/lib.rs
  • crates/switchyard-server/src/metrics.rs
  • crates/switchyard-server/src/stats.rs
  • crates/switchyard-server/src/stats/accumulator.rs
  • crates/switchyard-server/src/stats/algorithms.rs
  • crates/switchyard-server/src/stats/algorithms/stage_router.rs
  • crates/switchyard-server/tests/server.rs
  • docs/routing_algorithms/stage_router_routing.md

Comment thread crates/switchyard-server/src/stats/algorithms/stage_router.rs Outdated
@sabhatinas

Copy link
Copy Markdown
Contributor

can you add a JSON snapshot of how the stats look like before and after?

Signed-off-by: nachiketb <nachiketb@nvidia.com>
@sabhatinas

Copy link
Copy Markdown
Contributor

{
"algorithm_stats": {
"stage_router": {
"routing_decisions": {},
"scoring": {
"score": { "count": 0, "sum": 0.0, "avg": 0.0 },
"confidence": { "count": 0, "sum": 0.0, "avg": 0.0 },
"dimensions": {
"severity": { "count": 0, "sum": 0.0, "avg": 0.0 },
"spinning": { "count": 0, "sum": 0.0, "avg": 0.0 },
"exploring": { "count": 0, "sum": 0.0, "avg": 0.0 },
"production_intensity": { "count": 0, "sum": 0.0, "avg": 0.0 }
}
}
}
}
}

Nice! I dont think sum makes sense as much as the p50, p99 data points. can you remove sum and keep p50 and p99 along with mean + count?

@ayushag-nv ayushag-nv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Internal review come out clean

Signed-off-by: nachiketb <nachiketb@nvidia.com>
@nachiketb-nvidia
nachiketb-nvidia enabled auto-merge (squash) August 11, 2026 17:18
@nachiketb-nvidia
nachiketb-nvidia merged commit 6df31a9 into main Aug 11, 2026
21 checks passed
@nachiketb-nvidia
nachiketb-nvidia deleted the nachiketb/feat-stage-router-v1-stats branch August 11, 2026 17:23
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.

3 participants