feat(epp): add OpenTelemetry spans for the scheduler scoring path#1834
feat(epp): add OpenTelemetry spans for the scheduler scoring path#1834mvanhorn wants to merge 2 commits into
Conversation
| return weightedScorePerEndpoint | ||
| } | ||
|
|
||
| // runScorer invokes a single weighted scorer and records its latency metric. |
There was a problem hiding this comment.
Is there a need to have a span per plugin or we can live with a single span for scheduling?
Any reason to suspect that a scorer would take noticeable time to warrant creating such fine grained spans?
It would be good to have some rationale for the production of detailed OTel traces at the granularity of internal function calls.
|
This PR is marked as stale after 21d of inactivity. After an additional 14d of inactivity (7d to become rotten, then 7d more), it will be closed. To prevent this PR from being closed, add a comment or remove the |
|
Fair question — the rationale, and I'm happy to drop to a single span if it doesn't hold up. Why per-scorer rather than one On cost: I don't assume scorers are individually slow — the child spans are there for the tail, not the median. The hot path is guarded: If you'd rather keep the trace coarse, I'll collapse to the single |
Wrap the scorer chain in a parent llm_d.epp.scoring span and each scorer invocation in an llm_d.epp.scorer.<type> child span, so a request trace shows which scorers ran, how long they took, and aggregate score signals. Span attributes are request- and chain-level only (scorer type/name/weight, candidate count, score max/avg); no per-endpoint keys are emitted, keeping span cardinality bounded. Spans are no-ops when tracing is uninitialized. Signed-off-by: Matt Van Horn <mvanhorn@gmail.com>
The linked upstream guide URL 404s, which fails the Check Markdown Links workflow. The same material is covered by this document's own InferencePool & InferenceModel Design section. Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
0ea1f2b to
f06a935
Compare
What type of PR is this?
/kind feature
Summary
Adds fine-grained OpenTelemetry spans to the EPP scheduler scoring path so a single request trace shows which scorers ran, how long each took, and the aggregate score signals each produced.
SchedulerProfile.runScorerPluginsnow opens a parentllm_d.epp.scoringspan over the scorer chain, and each scorer invocation runs inside anllm_d.epp.scorer.<type>child span. The child spans nest under the parent, and the existing plugin-internal span (e.g.score_prefix_cache) nests under its scorer span. This mirrors the span-emission pattern already used by the precise-prefix-cache scorer.Attributes are request- and chain-level only:
llm_d.epp.scorer.count,llm_d.epp.scoring.candidate_endpoints, plusgen_ai.request.model/gen_ai.request.idwhen present.llm_d.epp.scorer.type,llm_d.epp.scorer.name,llm_d.epp.scorer.weight,llm_d.epp.scorer.candidate_endpoints, and aggregatellm_d.epp.scorer.score.max/.avg/endpoints_scoredderived from the returned score map.No per-pod / per-endpoint attribute keys are emitted, keeping span cardinality bounded.
Why this matters
Issue #1692 ("Add span for scheduler score") is the scoped sub-task of umbrella #1483, which asks for spans across the scheduling/scoring pipeline so operators can see scorer-level behavior inside a request trace instead of only the top-level
gateway.request/gateway.request_orchestrationspans. Today the scorer chain is invisible in traces: there is no way to tell which scorer dominated a routing decision or which one was slow.This package is allocation-sensitive (the surrounding code documents per-request allocation work in
runScorerPluginsandrunPickerPlugin), so the scoring path stays allocation-free when tracing is disabled: the parent span'sIsRecording()is checked once and all attribute and child-span construction is skipped on the default no-op path, with the tracer and span-kind option resolved once rather than per scorer.BenchmarkScheduleconfirms the disabled path holds at the prior baseline.Testing
llm_d.epp.scoringspan recorded with onellm_d.epp.scorer.<type>child per scorer, children nested under the parent, with correct weight, candidate-count, and aggregate max/avg attributes.Which issue(s) this PR fixes:
Fixes #1692
Release note: