Repository navigation
Conversation
AlgorithmStats::new creates the stage-router baseline only when a route's
algorithm name is literally "stage_router". A composite route is a stage
route under another name: CompositeRouter is
build_stage_route(config.stage)?.with_name(COMPOSITE)
and its StageClassifier records switchyard.stage_router.routing_decisions
and the scoring histograms on every turn regardless of the route name. With
no baseline the snapshot field stays None and serde skips it, so an operator
running a composite route gets algorithm_stats: {} from /v1/stats while
/metrics carries the counters, and loses the decision-source breakdown the
stage-router docs promise.
Key the baseline on either name. The wider fix is for libsy to say which
algorithms a route composes, so the next wrapper does not reintroduce this;
this keeps the change inside the server, next to the two names already
hardcoded there.
Signed-off-by: Dmitry Voropaev <dy.voropaev@gmail.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review. WalkthroughComposite routes now include stage-router metrics in stats snapshots. A new test checks that a composite route reports three recorded routing decisions for ChangesComposite Route Stats
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to Composite routes now have the metric baseline needed to report their stage-router decisions in 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
A rabbit counts the routes in spring, Comment |
AlgorithmStats::newcreates the stage-router baseline only when some route's algorithm name is exactly"stage_router":A composite route is a stage route under another name.
CompositeRouter::newends withand
CompositeRouter::name()returns"composite", while theStageClassifierinside it callsrecord_score_metricsandrecord_routing_decisionon every turn, with no dependence on the route name. So the counters reach/metricsand the JSON block does not: with no baseline the snapshot field staysNoneand#[serde(skip_serializing_if = "Option::is_none")]drops it, andGET /v1/statsanswers"algorithm_stats":{}.What the operator loses is the whole decision-source breakdown the stage-router documentation promises (
docs/routing_algorithms/stage_router_routing.md:154, "/v1/stats reports decision counts by source and selected target, plus aggregate" scoring) for one of the documented strategies.subagentsandautoare unaffected: the former delegatesname()to its parent and the latter builds a realStageRouter.The change keys the baseline on either name, next to the two names already hardcoded in that file.
Worth saying out loud: this is the narrow fix, not the structural one. The structural one is for libsy to say which algorithms a route composes, something like an
Algorithm::composed_names()defaulting to[self.name()]and overridden byCompositeRouter, so that the next wrapper aroundbuild_stage_routedoes not reintroduce the gap. That touches a trait in another crate and is yours to want or not; say so and I will send it that way instead.Tested:
a_composite_route_reports_its_stage_router_stats, next to the existing projection test, drivingStatsAccumulator::new(registry, ["composite"])and the same instruments the existing test uses. It fails onmainat theunwrap_or_elsewith "stage-router stats missing for a composite route".cargo test --workspace926 passed, 0 failed.cargo fmt --all --checkandcargo clippy -p switchyard-server --all-targets -- -D warningsclean on toolchain 1.99.Not run: a live composite deployment. The test records the instruments directly rather than routing a turn through a composite route, because the recording path goes through the process-global OTel meter provider and that would make the test order-dependent. The half that is read rather than run is "a composite route records these instruments", which follows from
CompositeRouter::newbuilding the route withbuild_stage_routeandStageClassifier::scorerecording unconditionally.Summary by CodeRabbit