Inference serving metrics

GPU counters tell you a GPU is busy. They don’t tell you whether users are waiting. For that, gputop scrapes the Prometheus endpoints of LLM inference servers and shows serving metrics next to the GPUs that run them:

Metric Meaning
TTFT Time to first token: how long a request waits before output starts (queueing + prefill)
ITL Inter-token latency (time per output token): decode speed as the user sees it
E2E End-to-end request latency
Queue Time a request waited before it was scheduled
Running / waiting Requests in the batch / queued for admission
KV cache Fraction of KV-cache blocks in use. At 100%, new requests queue and running ones may be preempted
Prefix hit Fraction of prompt tokens served from the prefix cache
Throughput Completed requests/s, prompt tokens/s and generated tokens/s
Preemptions Requests evicted from the batch per second (vLLM)

These values have the application source: the server reports them and gputop only aggregates them.

Supported servers

Server Recognized command Metrics port TTFT ITL E2E Queue KV cache
vLLM vllm serve, vllm.entrypoints.* --port (8000) ✅ ✅ ✅ ✅ ✅
SGLang sglang.launch_server (needs --enable-metrics) --port (30000) ✅ ✅ ✅ ✅ ✅
Text Generation Inference text-generation-launcher / -router --prometheus-port (9000) — ✅ ✅ ✅ —
llama.cpp llama-server (needs --metrics) --port (8080) — — — — ✅

The engine is detected from the metric names, so a configured endpoint doesn’t need to say what it is. Values a server doesn’t export are shown as N/A. Metric names that changed between vLLM and SGLang versions (for example time_per_output_token_seconds → inter_token_latency_seconds) are both recognized.

Finding servers

Discovery (on by default). gputop recognizes the commands above among the processes using a GPU and derives the metrics URL from --port and --host. Processes started by the same server (tensor-parallel workers) are merged into one entry that lists all of their GPUs. Containerized servers are reached at their pod IP, which requires Kubernetes pod metadata (see kubernetes.md). A container without a known pod IP is skipped.

Configured endpoints, for servers on other hosts, behind a service, or on ports discovery can’t see:

inference:
  endpoints:
    - name: chat-api
      url: http://10.0.0.5:8000/metrics

A configured endpoint that can’t be scraped makes the inference collector unhealthy, so it shows up as an alert. A discovered server that can’t be scraped is only shown as down in the Inference tab, because it may simply not export metrics.

How values are computed

Servers export cumulative counters and histograms. gputop scrapes each server every refresh.normal interval (3s by default) and keeps the scrapes of the last inference.window (1 minute by default). Rates and latencies describe that window: they are the difference between the newest scrape and the oldest one in the window, the way PromQL’s rate() and histogram_quantile() work.

Where it shows up

Serving metrics are not written to the history store; the live charts cover the last 10 minutes.

Spotted something wrong? Edit this page on GitHub ↗