Read queue and generation metrics from a local server
Sample a protected llama.cpp metrics endpoint during a repeatable workload and distinguish gauges, counters, and client latency.
On this page
Take an idle sample
Use the authenticated loopback server from the server authentication lab. It started with --metrics. Save this script next to compatible_chat.py, set LOCAL_MODEL_API_KEY in the client shell, and take one sample.
View sample_server_metrics.py
import argparse
import os
from time import sleep
from urllib.error import HTTPError
from urllib.request import ProxyHandler, Request, build_opener
from compatible_chat import NoRedirects, local_base
METRICS = {
"llamacpp:requests_processing": "active",
"llamacpp:requests_deferred": "waiting",
"llamacpp:tokens_predicted_total": "generated_total",
}
def read_metrics(base):
key = os.environ.get("LOCAL_MODEL_API_KEY")
headers = {"Authorization": f"Bearer {key}"} if key else {}
endpoint = base.removesuffix("/v1") + "/metrics"
opener = build_opener(ProxyHandler({}), NoRedirects())
with opener.open(Request(endpoint, headers=headers), timeout=5) as response:
body = response.read().decode("utf-8")
values = {}
for line in body.splitlines():
parts = line.split()
if len(parts) >= 2 and parts[0] in METRICS:
values[METRICS[parts[0]]] = float(parts[1])
if len(values) != len(METRICS):
raise ValueError("Expected llama.cpp metrics are missing. Check your server build.")
return values
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Sample metrics from your own local llama.cpp server.")
parser.add_argument("--base", type=local_base, default="http://127.0.0.1:8080/v1")
parser.add_argument("--samples", type=int, choices=range(1, 31), default=12)
args = parser.parse_args()
try:
for index in range(args.samples):
values = read_metrics(args.base)
print(f"{index + 1:02d} | active={values['active']:.0f} | waiting={values['waiting']:.0f} "
f"| generated_total={values['generated_total']:.0f}", flush=True)
if index + 1 < args.samples:
sleep(1)
except HTTPError as error:
raise SystemExit(f"Metrics returned HTTP {error.code}. Check --metrics and the local API key.") from None
except (OSError, ValueError) as error:
raise SystemExit(str(error)) from Nonepython sample_server_metrics.py --samples 1
The script reads active requests, deferred requests, and total generated tokens. Active and waiting counts are gauges. They describe the moment you sampled and can go up or down. The generated-token total is a counter for that server run.
Sample during a workload
In the first client terminal, start collecting samples. In another client terminal with the same key, run the workload from the concurrent requests lab.
python sample_server_metrics.py --samples 20
python measure_concurrency.py --base http://127.0.0.1:8080/v1 --model qwen-local --count 8
The generated-token total grows between the first and last samples. Active or waiting counts may stay at zero if requests finish between samples. If you need to see waiting work, try two clients with one server slot and repeat.
Read the counters and keep a baseline
Subtract the first counter value from the last for the tokens generated over that interval. Divide by the elapsed seconds for an average rate. A restart can reset the counter, so start a new measurement interval after restarting.
Record the server build, model, context per slot, client count, and output cap. Compare gauges with the client’s measured median reply time. A readiness check or a single gauge cannot tell you what a client waited for.
Check your understanding
Why might every waiting sample be zero while some requests still waited?
A queue can form and drain between observations. Use client timings and a repeatable workload to investigate.
Sources
Progress is saved in this browser.