How metrics reach Prometheus
Metrics reach Prometheus one of two ways. The OpenTelemetry Collector path is the recommended setup. Withobservability.enabled, each
engine pushes its metrics (and traces) to an OTel Collector, and Prometheus scrapes the Collector.
Enabling it also stops the engine serving /metrics directly. See Observability
for the full setup.
The engine-endpoint path is an alternative when you don’t run the collector. Each
engine pod serves /metrics directly, and the operator creates a metrics Service, plus a
ServiceMonitor (when serviceMonitor.enabled is set) so Prometheus auto-discovers it:
Verify metrics are flowing
First, find which path this engine uses. The check is whether the engine is pushing OTLP:- OTLP / collector path
- Engine-endpoint path
The engine pushes metrics to an OpenTelemetry Collector, so it exposes no scrapeable
lmcache_mp_* endpoint itself. Read them from the Collector’s Prometheus exporter and confirm
the pipeline in
Observability → Verify telemetry is flowing, or
just query Prometheus below.lmcache_mp_* lines (or a number from the query) confirms metrics are flowing. Empty
means no traffic has hit the engine yet; send some inference through vLLM first.
Pull every metric
See the complete set straight from Prometheus (works on either path):What to watch first
The signals to check first, in priority order.1. Lookup hit rate
How much of each requested prefix was served from cache instead of recomputed on the GPU.2. L1 activity
L1 is the host-DRAM tier. These counters show whether it’s serving reads (good) or just churning writes and evictions (undersized).- Reads rising on warm traffic → L1 is doing its job.
- Writes high, reads low → poor reuse, or the hot set doesn’t fit — see CPU offloading sizing.
- Evictions climbing fast → L1 is undersized for the working set.
3. L2 activity
Only relevant if you’ve configured external storage. These confirm data is landing in L2 and warm traffic is loading it back.4. Retrieved chunk volume
Slice by model and tenant
Many engine metrics carry labels you can group by:model_name— per-model hit rate and volumecache_salt— per-tenant isolationl2_name— which L2 backend
cache_salt coarse: one salt per tenant is fine, but one per request explodes your
time-series count and hurts cache reuse.
Complete metric reference
Most metrics carrymodel_name, cache_salt, and l2_name labels for
slicing. Counters (_total) need rate(...[5m]); gauges are
instantaneous; histograms expose _bucket / _sum / _count.
A metric only appears once it’s been recorded, so an idle engine shows only the always-on gauges;
the activity counters appear after traffic hits the cache.
Lookup & hit rate
L1 — CPU offloading (host DRAM)
L2 — external storage
Throughput
Histograms in GB/s: compute the live rate asrate(<name>_sum[5m]) / rate(<name>_count[5m]).
Prefetch & event bus (health)
Reuse gap
How long cached data lives before it’s reused, the input to sizing decisions.Lifecycle histograms
Per-tier block/chunk timing: how long cached data lives, sits idle, and waits between reuses. Newer engine builds expose more of these. All are histograms (_bucket / _sum / _count).
vLLM exports its own
vllm:* metrics on a separate port (TTFT, running/waiting requests, HBM KV
usage). Pair those with the cache-engine metrics above for the full request-to-cache picture.
When to go deeper
The catalog above is complete for operating the cache. For low-level internals (exact histogram-bucket boundaries, precise semantics, and cardinality notes), see the upstream multiprocess-engine reference: MP observability.Next steps
Operator UI
An interface that visualizes these metrics: fleet, hit rate, capacity, health.
Observability stack
Ship metrics and traces through an OpenTelemetry Collector to Prometheus and Tempo.
CPU offloading
Tune the L1 tier the L1 metrics above describe.

