Monitoring¶
Goal: collect the metrics and traces that the deployed serving stack emits, and read the metrics and traces correctly.
| Signal | Source | Collection and query |
|---|---|---|
| Metrics | modelserver (per role), llm-d Endpoint Picker (EPP), gateway | Monitoring custom resources (CRs) of the VictoriaMetrics Operator (default) or Prometheus Operator, and Grafana |
| Traces | EPP, routing sidecar, vLLM | OpenTelemetry (OTel) collector and a trace backend |
Metric collection targets¶
This section lists what the chart's monitoring CRs collect and how each target authenticates.
- The monitoring CRs collect modelserver metrics per role. The selector is the
llm-d.ai/role: decode|prefilllabel. The chart creates one VMPodScrape per role (PodMonitor with Prometheus Operator), so thejoblabel (<namespace>/<name>) differs by role. - EPP's
/metrics(port 9090) requires a bearer token. The modelserver's/metricshas no authentication. - The monitoring CRs collect gateway metrics as well. On the default Istio data plane, the monitoring CR collects the Envoy metrics (port 15090,
/stats/prometheus). With agentgateway, the same CR collects port 15020. - LMCache metrics are not a separate collection target. The modelserver exposes LMCache metrics on its own
/metrics.
With the default VictoriaMetrics Operator, enable monitoring with the following values. monitoring.scraper.serviceAccount.{name,namespace} names the ServiceAccount of VMAgent, the VictoriaMetrics agent that collects the metrics. If monitoring.scraper.serviceAccount is not set, the render fails.
The chart binds the permission to read EPP's /metrics to the VMAgent ServiceAccount. The chart does not create a bearer-token Secret. VMAgent authenticates with the projected token mounted in its Pod, and kubelet renews the projected token.
The chart's bundled examples/observability.yaml enables both metrics and tracing. Installing with examples/observability.yaml therefore also requires an OTel collector in the cluster. Fill in the <...> slots of examples/observability.yaml and pass the file with -f. To collect metrics only, remove the tracing and llm-d-router-gateway blocks from the file.
On a cluster that uses Prometheus Operator, set monitoring.backend=prometheus. The chart then creates PodMonitor and ServiceMonitor. The chart also creates the ServiceAccount and token Secret for EPP's /metrics, so monitoring.scraper.serviceAccount is not needed. monitoring.labels adds the label that your Prometheus selector requires (e.g. release: <prometheus-release>). This option is Unverified on the Target Configuration.
Prefix cache hit metrics¶
This stack has two cache tiers: tier 1 in high-bandwidth memory (HBM) and tier 2 in Rebellions Direct Storage (RDS). This section covers only the metrics that tell the two tiers apart. For the full metric list, see vLLM Production Metrics.
| What to check | Metric | How to read the metric |
|---|---|---|
| Tier 1 (HBM) reuse by Automatic Prefix Caching | vllm:prefix_cache_hits_total | Counts the prompt tokens reused from HBM, sub-block reuse included |
| Key-value (KV) cache fetched from outside HBM (P/D transfer and tier 2 reuse) | vllm:external_prefix_cache_hits_total | Counts the tokens whose KV a KV connector fetched. In the reference configuration, decode registers only NIXL as its KV connector, so the decode value of vllm:external_prefix_cache_hits_total is all P/D transfer. Read LMCache reuse from RDS in the prefill value of vllm:external_prefix_cache_hits_total |
| Prompt tokens by source | vllm:prompt_tokens_by_source_total | The source label splits into local_cache_hit (HBM prefix cache), external_kv_transfer (KV connector), and local_compute. The token counts of the three source values add up to the prompt token count |
| RDS reads and writes | lmcache_rbln_rds_io_total | Read reads and writes separately by the operation label (read, write). If lmcache_rbln_rds_io_total is absent, the RDS backend was not created |
Read the metric values as follows.
- Tier 1 hit rate: divide
vllm:prefix_cache_hits_totalbyvllm:prefix_cache_queries_total.vllm:prefix_cache_queries_totalis the number of prompt tokens looked up. - Summing DP ranks: a Pod that runs with DP exposes the vLLM counters of each rank on a different port. Decode uses one port per rank, starting at 8200. Add up the values of all ranks to get the Pod's value.
- LMCache values per worker: LMCache records its metrics separately for each PP worker (
worker_id). A sum over the workers is inflated by the PP degree, so read the value of one worker. lmcache:num_hit_tokens_total: exposed as 0 even when LMCache is not running. Use it for diagnosis only, not to judge reuse.
To see sub-block reuse alone, send a prompt shorter than --block-size twice. Then read the increase of the vllm:prompt_tokens_by_source_total value whose source is local_cache_hit.
Warning
Do not judge per-tier reuse from the response's prompt_tokens_details.cached_tokens. With --enable-prompt-tokens-details, which the chart sets, cached_tokens reports the reused tokens of the whole request. cached_tokens does not tell which tier or path supplied the reused tokens.
To see whether KV reached decode by P/D transfer, read the External prefix cache hit rate: <n>% line in the decode log. If the External prefix cache hit rate is above 0%, the KV came from outside the decode engine, which here is the P/D transfer. A shorter time to first token (TTFT) on a resent prompt does not prove cache reuse either. prefix-based-pd-decider sends a request already cached on decode to decode without prefill, so a shorter TTFT can come from skipping prefill.
NPU device metrics¶
The RBLN Metrics Exporter exposes NPU device-layer metrics (temperature and utilization). The RBLN Metrics Exporter is an SDK component, not part of the serving stack chart.
Per-stage engine instrumentation¶
With VLLM_RBLN_METRICS=True, each RBLN vLLM worker collects per-step latency split into the device, host, collective, and prepare stages. The engine prints a performance report when it shuts down (Configuration Guide).
The chart has no dedicated values key for VLLM_RBLN_METRICS. Set it with the following keys.
- The same value for prefill and decode:
modelserver.serveEnv - Different values for prefill and decode:
modelserver.extraServeEnv
Traces¶
The EPP, the routing sidecar, and vLLM send their spans to the same OTel collector. The processing of one request by the EPP, the routing sidecar, and vLLM, in that order, therefore appears as one trace. The chart default leaves tracing disabled (tracing.enabled: false).
To enable tracing, set tracing.enabled and, on the EPP subchart side, llm-d-router-gateway.router.tracing.enabled to the same value. The render fails if the two keys differ.
Set the OTel collector address in both of the following keys. With tracing enabled, the render fails if the two addresses differ. The chart compares the two addresses as strings, so write the same address in the same form in both keys.
| Key | Description |
|---|---|
tracing.collector.{name,namespace,port} | Sets the collector's Service name, namespace, and port. vLLM and the routing sidecar find the collector through tracing.collector. On agentgateway, the gateway layer uses tracing.collector as well |
llm-d-router-gateway.router.tracing.otelExporterEndpoint | Sets the collector address for the EPP subchart |
Note
tracing.enabled enables the vLLM, EPP, and routing-sidecar spans. On the default Istio data plane, configure gateway spans separately with the Istio Telemetry API. See Configure tracing with Telemetry API. When gateway.gatewayClassName is agentgateway and tracing is enabled, the chart emits an AgentgatewayPolicy for the gateway layer, and gateway.agentgateway.tracingPolicy carries the agentgateway-specific tracing settings (randomSampling and serviceName).