Add speculative-decoding (MTP) recording rules and Grafana dashboard - #3
Conversation
- prometheus-rules.yaml: new vllm-spec-decode group with five 1m-rate
recording rules (acceptance rate, mean accepted length, draft/accepted
token rates, per-position acceptance) following the existing
{job="vllm"} + 5s interval conventions
- grafana/dashboards/vllm-spec-decode.json: new provisioned
"vLLM Speculative Decoding" dashboard with five panels querying the
recorded metrics
- docs/METRICS.md: document the dashboard and recording rules; keep the
raw-counter PromQL as the equivalent reference
There was a problem hiding this comment.
Pull request overview
Adds speculative-decoding observability to the Prometheus/Grafana stack.
Changes:
- Adds five speculative-decoding recording rules.
- Adds a provisioned Grafana dashboard.
- Documents metrics, panels, and reload procedures.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
prometheus-rules.yaml |
Defines speculative-decoding metrics. |
grafana/dashboards/vllm-spec-decode.json |
Adds the visualization dashboard. |
docs/METRICS.md |
Documents setup and metric usage. |
Suppressed comments (2)
grafana/dashboards/vllm-spec-decode.json:104
- Like the acceptance-rate stat,
lastNotNullover a range keeps displaying the previous mean length after the recording rule stops emitting samples. Use an instant query so this panel shows No value once the one-minute draft rate reaches zero.
"range": true,
docs/METRICS.md:116
- This update also changes a bind-mounted Prometheus rule file, but Prometheus does not watch rule files and the Compose service does not enable the lifecycle reload endpoint. On an already-running stack,
compose up -dleaves the container unchanged, so restarting only Grafana produces a dashboard whose recording metrics do not exist. Document a Prometheus restart as part of applying rule changes.
If you add or replace dashboard files on disk, restart the Grafana container
for the file provider to reload them:
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| "editorMode": "code", | ||
| "expr": "vllm:spec_decode_acceptance_rate:rate1m", | ||
| "legendFormat": "Accepted", | ||
| "range": true, |
| "mode": "single", | ||
| "sort": "desc" | ||
| }, | ||
| "xTickLabel": "Position {{text}}" |
| The rules evaluate to no value while vLLM is idle, so the panels show **No | ||
| value** until requests are being generated; this avoids a misleading 100% | ||
| acceptance rate at idle. |
There was a problem hiding this comment.
Confirmed — the blanket wording was still incorrect after the instant-query fix: only the guarded ratio rules (acceptance rate, mean accepted length, per-position) evaluate to no value at idle; the two unguarded token-rate rules keep recording zero, so those panels show 0 rather than No value. Fixed in b66a553, which splits the documented behavior by rule type. Verified against live Prometheus data: during a 46-minute true-idle window (target up, counters flat) the draft/accepted token-rate rules recorded 0.0 while the ratio rules produced no samples.
|
Summary of the fixes in this round ( Recipe: MTP speculative decoding enabled (
Review comment: stale stat values at idle (
Review comment: per-position panel (
Both dashboards were validated end-to-end against the live Prometheus + Grafana stack: all |
Summary
Extends the existing Prometheus/Grafana metrics stack (added in #2) with speculative-decoding / MTP observability: new Prometheus recording rules plus a provisioned Grafana dashboard that shows draft acceptance and per-position MTP stats.
Changes
prometheus-rules.yamlNew
vllm-spec-decoderule group (5s interval, 1m rate window,{job="vllm"}filter — same conventions as the existingvllm-throughputgroup):vllm:spec_decode_acceptance_rate:rate1mvllm:spec_decode_mean_accepted_length:rate1mvllm:spec_decode_draft_tokens_per_second:rate1mvllm:spec_decode_accepted_tokens_per_second:rate1mvllm:spec_decode_acceptance_rate_by_pos:rate1mpositionlabel preserved)grafana/dashboards/vllm-spec-decode.json(new)Provisioned vLLM Speculative Decoding dashboard (uid
vllm-spec-decode, tagspec-decode), loaded into the vLLM folder by the existing file provider. Five panels, styled consistently withvllm-throughput.json(datasourceuid: prometheus, 5s refresh, 15m window):Position {{position}}legenddocs/METRICS.mdUsage
docker compose -f docker-compose.metrics.yaml up -d— Prometheus hot-reloads the changed rules file; verify the new group at:9090/rules.docker compose -f docker-compose.metrics.yaml restart grafana.Behavior notes
--num-speculative-tokensand compare the generation tokens/s rule.docs/METRICS.md(..._num_draft_tokens_total,..._num_drafts_total,..._num_accepted_tokens_per_pos_total). Builds exposing different vLLM spec-decode counter names would need the rule metrics adjusted.Testing
prometheus-rules.yamlvalidated (YAML parse); all five rules confirmed loaded without errors at:9090/rulesagainst the running stack.