Skip to content

[Testing] Periodic metric-name drift detection for vLLM, SGLang, and TGI #669

Description

@Bslabe123

Part of the #621 testing work for the v0.7.0 tracker (#606). Builds on the replayed-/metrics e2e fixture landing with #382.

Problem

inference-perf hardcodes the Prometheus metric names it queries for every supported model server, and nothing tells us when an upstream server renames, removes, or re-namespaces one:

  • vllm_client.py: ~25 names under vllm: (vllm:num_requests_waiting, vllm:time_to_first_token_seconds, vllm:request_time_per_output_token_seconds, vllm:inter_token_latency_seconds, vllm:prompt_tokens, vllm:generation_tokens, vllm:kv_cache_usage_perc, ...)
  • sglang_client.py: 9 names under sglang:
  • tgi_client.py: 6 names under the tgi_ prefix

The failure is silent by construction. A stale name produces no error: the PromQL matches nothing, the query returns an empty result, and the affected field in summary_prometheus_metrics.json is absent or zero. A user reading the report cannot distinguish "the server did not report this" from "we asked for a name that no longer exists."

We already have one instance in flight: #382 updates sglang:cache_hit_rate to sglang:token_usage, a rename that was caught by hand rather than by CI.

Why it matters

This is the #564 family. Nothing fails, a number is just missing or wrong, and it stays that way until someone notices a blank column. The blast radius is every server-metrics section we publish, and the probability rises over time because all three servers version independently of us.

TGI is the sharpest case: it is the least active of the three upstreams and the one we exercise least, so a rename there could sit undetected for a full release cycle.

Proposed shape

A scheduled job whose output is a fixture-refresh PR, not a test failure:

  1. On a schedule (weekly is enough), start the latest release of each supported server: vLLM, SGLang, TGI.
  2. Scrape /metrics once and write the response to the checked-in fixture for that server, stamped with the server version it came from.
  3. If the fixture is unchanged, exit quietly. If it changed, open a PR with the new dump.

That PR then runs the normal merge-blocking e2e test, which replays the fixture through a real Prometheus and asserts the assembled report. A metric we no longer recognize shows up there as a report field going empty against the golden. So drift detection needs no new assertion machinery: it reuses the blocking test, and the failure lands on one attributable PR that someone owns instead of on every open PR at once.

Two things that keep this cheap:

  • No benchmark run is required. All three servers register their metric families at engine init, so a bare startup plus a single scrape is enough to see the names.
  • No new test to maintain. The job's only logic is start, scrape, diff, open PR.

Explicitly not merge-blocking

Deliberate. If latest upstream gated merges, a rename would turn every open PR red simultaneously, including the PR that fixes it. A moving external dependency cannot sit in the merge gate. Advisory and periodic is the correct contract here, and it is why this row does not gate a release even though it lives in the live tier.

Update (Aug 17): for vLLM this changed with #697: every release in e2e/vllm_releases.txt, including latest-x86_64, gates at merge. The "fixing PR is red too" premise does not hold once the table and declarations live in the tree. The scheduled, non-gating shape stays the plan for SGLang and TGI, which have no CPU tier.

Relationship to existing work

Known limit

This catches renames, removals, and re-namespacing, because those show up as a name appearing or disappearing from the dump. It does not catch a metric that keeps its name while changing units or semantics. Nothing short of value-level review catches that, and it is the same silent-wrongness family this issue is trying to shrink.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions