Metrics Collection¶
Comprehensive guide to how metrics are collected, stored, and visualized in the vLLM CPU Performance Evaluation framework.
Overview¶
The framework collects three types of metrics:
- Client-Side Metrics - GuideLLM benchmark results (always collected)
- Server-Side Metrics - vLLM server performance (automatically collected when available)
- System Metrics - CPU, memory, container stats (collected for managed mode)
Key Point: All metrics are collected automatically. Grafana/Prometheus are optional for real-time visualization only.
Deployment Modes:
- Managed Mode (default): vLLM runs in container on DUT → full metrics
- External Mode: vLLM runs externally (cloud/K8s) → client metrics + server metrics if /metrics exposed
Metrics Collection Flow¶
During benchmark execution¶
| Step | Action | Output file |
|---|---|---|
| 1 | vLLM server starts on DUT | — |
| 2 | Metrics collector starts (background) | Scrapes http://DUT:8000/metrics every 10s |
| 3 | GuideLLM benchmark runs | benchmarks.json |
| 4 | Metrics collector stops | vllm-metrics.json |
| 5 | System metrics collected | system-metrics.log |
Result files¶
Saved to results/llm/<model>/<test-id>/<config>/:
| File | Source |
|---|---|
benchmarks.json |
Client-side (GuideLLM) |
vllm-metrics.json |
Server-side (vLLM) |
system-metrics.log |
System resources |
test-metadata.json |
Test configuration |
vllm-server.log |
Server logs |
Post-test analysis¶
| Tool | Views |
|---|---|
| Streamlit Dashboard | Client Metrics, Server Metrics, Unified Analysis |
Optional: real-time monitoring (during test)¶
| Tool | Views | Requires |
|---|---|---|
Grafana (http://localhost:3000) |
vLLM Performance Statistics, vLLM Query Statistics | Grafana + Prometheus + SSH tunnel |
1. Client-Side Metrics (GuideLLM)¶
Client Metrics: What is Collected¶
End-user experience metrics from the benchmark client:
- Throughput: Total tokens/sec, request rate
- Latency: TTFT, ITL, E2E latency (mean, P50, P95, P99)
- Success Rate: Request completion percentage
- Request Distribution: Prompt tokens, output tokens
Client Metrics: Collection Method¶
Automatic - GuideLLM saves results after benchmark completes.
Client Metrics: Output File¶
benchmarks.json
Client Metrics: Example Structure¶
{
"benchmarks": [
{
"request_rate": 16,
"concurrency": null,
"completed_request_rate": 15.8,
"total_num_completed_requests": 158,
"total_num_errored_requests": 2,
"total_time": 10.01,
"completed_requests_per_min": 948.05,
"request_latency": {
"mean": 0.634,
"min": 0.121,
"max": 1.823,
"std": 0.234,
"p25": 0.456,
"p50": 0.589,
"p75": 0.721,
"p90": 0.892,
"p95": 1.012,
"p99": 1.456
},
"time_to_first_token": { ... },
"inter_token_latency": { ... }
}
]
}
2. Server-Side Metrics (vLLM)¶
Server Metrics: What is Collected¶
Internal vLLM server performance metrics:
- Queue State: Requests running, waiting
- Cache Utilization: KV cache usage percentage
- Token Processing: Prompt tokens, generation tokens (cumulative)
- Request Counters: Success, failures, preemptions
- Latency Histograms: TTFT, ITL, E2E (with percentile buckets)
- Processing Time: Prefill time, decode time, queue time
Server Metrics: Collection Method¶
Direct Collection (Default - No Grafana Required)
vllm_metrics_collectorrole starts before benchmark- Python script runs in background
- Scrapes
http://DUT:8000/metricsevery 10 seconds - Saves time-series data to JSON file
- Stops after benchmark completes
Implementation:
# Automatically integrated in llm-benchmark-auto.yml
pre_tasks:
- name: Start vLLM metrics collection
include_role:
name: vllm_metrics_collector
vars:
vllm_url: "http://{{ bench_config.vllm_host }}:8000"
metrics_collection_interval: 10
metrics_collection_duration: 720 # 12 minutes
post_tasks:
- name: Stop vLLM metrics collection
include_role:
name: vllm_metrics_collector
tasks_from: stop
Server Metrics: Output File¶
vllm-metrics.json
Server Metrics: Example Structure¶
{
"collection_info": {
"source": "direct",
"vllm_url": "http://ec2-13-59-253-249.us-east-2.compute.amazonaws.com:8000",
"interval_seconds": 10,
"start_time": "2026-03-31T13:59:11",
"end_time": "2026-03-31T14:05:23",
"test_run_id": "20260331-135911",
"total_samples": 38,
"duration_seconds": 372
},
"samples": [
{
"timestamp": "2026-03-31T13:59:21",
"elapsed_seconds": 10.0,
"metrics": {
"vllm:num_requests_running": [
{
"labels": {
"engine": "0",
"model_name": "meta-llama/Llama-3.2-1B-Instruct"
},
"value": 3.0
}
],
"vllm:kv_cache_usage_perc": [
{
"labels": {...},
"value": 45.2
}
],
...
}
}
]
}
Configuration Options¶
# Skip metrics collection entirely
ansible-playbook llm-benchmark-auto.yml \
-e "skip_metrics_collection=true"
# Adjust collection interval (default: 10s)
ansible-playbook llm-benchmark-auto.yml \
-e "metrics_collection_interval=5"
External Endpoint Metrics Collection¶
When testing external vLLM endpoints (cloud, K8s, production):
Automatic Detection:
1. Playbook checks if ${VLLM_ENDPOINT_URL}/metrics is accessible
2. If YES (HTTP 200): Server metrics collection enabled
3. If NO (HTTP 404/403/timeout): Server metrics collection skipped
Example - Metrics Available:
export VLLM_ENDPOINT_MODE=external
export VLLM_ENDPOINT_URL=http://your-endpoint:8000
# Test endpoint
curl http://your-endpoint:8000/metrics
# → Returns Prometheus metrics (vllm:*, etc.)
# Run test (cores not needed - external endpoint manages its own CPUs)
ansible-playbook llm-benchmark-concurrent-load.yml \
-e "base_workload=chat"
# Result: vllm-metrics.json created ✅
Example - Metrics Not Available:
export VLLM_ENDPOINT_MODE=external
export VLLM_ENDPOINT_URL=http://production-lb.company.com:8000
# Test endpoint
curl http://production-lb.company.com:8000/metrics
# → 403 Forbidden (metrics not publicly exposed)
# Run test (cores not needed - external endpoint manages its own CPUs)
ansible-playbook llm-benchmark-concurrent-load.yml \
-e "base_workload=chat"
# Result: Only benchmarks.json created (client metrics) ⚠️
What You Get:
| Endpoint Type | Client Metrics | Server Metrics | System Metrics |
|---|---|---|---|
| Managed (DUT container) | ✅ Always | ✅ Always | ✅ Always |
External + /metrics public |
✅ Always | ✅ Auto-collected | ❌ Not applicable |
External + /metrics private |
✅ Always | ❌ Skipped | ❌ Not applicable |
Why /metrics might not be available:
- Security policies (production endpoints)
- Load balancer configuration (metrics endpoint not forwarded)
- Firewall rules (port blocked)
- Authentication required (bearer token not configured)
Note: Client metrics (GuideLLM) are always sufficient for performance evaluation. Server metrics provide additional debugging insight but are not required.
3. System Metrics¶
System Metrics: What is Collected¶
Infrastructure-level metrics:
- CPU Info: Model, cores, NUMA topology
- Memory: Total, used, free
- Container Stats: CPU%, Memory, I/O
System Metrics: Collection Method¶
Automatic - results_collector role runs after benchmark.
System Metrics: Output File¶
system-metrics.log
Example Content¶
=== CPU Info ===
Architecture: x86_64
CPU(s): 32
Model name: Intel(R) Xeon(R) 6975P-C
Threads per core: 2
Cores per socket: 16
NUMA node(s): 1
=== Memory Usage ===
total used free shared buff/cache available
Mem: 125Gi 23Gi 89Gi 1.2Gi 13Gi 100Gi
=== Container Stats ===
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET IO BLOCK IO
1f8fbcd2e8f0 vllm-server 524% 12.3GiB / 125GiB 9.84% 45.2MB / 0B 0B / 0B
Two Independent Systems¶
System 1: Metrics Collection & Analysis (Always Active)¶
vLLM Server :8000/metrics
│
▼
Direct Collector (Python)
│
▼
vllm-metrics.json ←───┐
│ │
▼ │
Streamlit Dashboard ───┘
(Reads JSON files)
No Grafana/Prometheus needed!
System 2: Real-Time Monitoring (Optional)¶
vLLM Server :8000/metrics
│
▼ (via SSH tunnel)
Prometheus (TSDB)
│
▼
Grafana Dashboards
(Live visualization)
Completely separate - only for watching tests in real-time!
Optional: Real-Time Monitoring with Grafana¶
While metrics are automatically collected (System 1), you can optionally run Grafana (System 2) for live visualization during tests.
Setup¶
# 1. Start Grafana stack
cd automation/test-execution/ansible
ansible-playbook start-grafana.yml
# 2. Open Grafana
open <http://localhost:3000>
# Username: admin
# Password: admin
# 3. Run benchmark (metrics visible in real-time)
ansible-playbook llm-benchmark-auto.yml \
-e "test_model=meta-llama/Llama-3.2-1B-Instruct" \
-e "workload_type=chat" \
-e "requested_cores=16"
Architecture¶
The DUT exposes metrics at http://DUT:8000/metrics. Two collection paths
are available:
| Path | Component | Purpose |
|---|---|---|
| Always active | Direct collector | Scrapes /metrics, saves to vllm-metrics.json |
| Optional | SSH tunnel → Prometheus → Grafana | Real-time visualization during test |
Flow: DUT /metrics → direct collector (JSON file) and/or SSH tunnel →
Prometheus (TSDB) → Grafana dashboards.
Key points:
- Direct collector and Prometheus both scrape the same /metrics endpoint (read-only, no conflict)
- Grafana is purely for live monitoring - not required for metrics collection
- After test completes, both paths produce the same data
- Use whichever visualization tool fits your workflow
When to Use Grafana¶
✅ Use Grafana when: - Running long tests (>5 minutes) and want to monitor progress - Debugging performance issues in real-time - Need to verify server is handling load correctly - Team collaboration - share dashboard URL for live view
❌ Skip Grafana when: - Running quick tests (<2 minutes) - Only care about final results - Don't want to manage extra services - Post-test analysis is sufficient
Analysis & Visualization¶
Streamlit Dashboard (Post-Test Analysis)¶
Note: Streamlit reads JSON files directly. No Grafana/Prometheus required.
Location: automation/test-execution/dashboard-examples/vllm_dashboard/
Launch:
cd automation/test-execution/dashboard-examples
./setup.sh
cd vllm_dashboard
./launch-dashboard.sh
Access: http://localhost:8501
What it reads:
- benchmarks.json (GuideLLM results - always created)
- vllm-metrics.json (vLLM server metrics - automatically collected)
- No database, no Prometheus, no Grafana needed!
Features: - 📊 Client Metrics - GuideLLM analysis (multi-percentile overlay for throughput, latency, success rate) - 🖥️ Server Metrics - vLLM internals (time-series for queue, cache, tokens) - 📈 Platform Comparison - Side-by-side performance with % differences - 💾 CSV Export - For external analysis - 🔄 Correlation - Switch between dashboards to correlate client & server behavior
Grafana Dashboards (Real-Time)¶
Location: http://localhost:3000 (when running)
Dashboards: - vLLM Performance Statistics - Queue depth, cache, token rates - vLLM Query Statistics - Request processing, latencies
See: Grafana README
Metrics Storage¶
Directory Structure¶
Example path:
results/llm/meta-llama__Llama-3.2-1B-Instruct/chat-20260331-135911/16cores-numa0-tp1/
| File | Description |
|---|---|
benchmarks.json |
GuideLLM results |
vllm-metrics.json |
vLLM server metrics |
system-metrics.log |
System resources |
test-metadata.json |
Test configuration |
vllm-server.log |
Server logs |
File Sizes¶
Typical file sizes for a 10-minute benchmark:
benchmarks.json: 50-200 KB (depends on rate sweep points)vllm-metrics.json: 500 KB - 2 MB (60 samples × ~30 metrics)system-metrics.log: 5-10 KBtest-metadata.json: 1-2 KBvllm-server.log: 1-10 MB (depends on log level)
Troubleshooting¶
vllm-metrics.json not created¶
Check metrics collector logs:
tail -f results/llm/*/metrics-collector.log
Common issues:
1. Port 8000 blocked - Check firewall/security groups
2. vLLM server not started - Verify server is running
3. Wrong hostname - Check bench_config.vllm_host in inventory
Test manually:
curl http://$DUT_HOSTNAME:8000/metrics
Empty metrics file¶
Issue: File created but no samples
Fix:
- Collector duration too short - increase metrics_collection_duration
- vLLM server not exposing metrics - check vLLM version supports /metrics
Grafana shows no data¶
Issue: Grafana dashboards empty
Fix:
1. Check SSH tunnel: ps aux | grep "ssh.*8000:localhost:8000"
2. Check Prometheus targets: http://localhost:9090/targets
3. Verify vLLM accessible: curl http://localhost:8000/metrics
Note: Direct collection (vllm-metrics.json) works independently of Grafana
Best Practices¶
For Production Benchmarking¶
- ✅ Always collect all metrics (default behavior)
- ✅ Use meaningful test IDs - include date/config in test_run_id
- ✅ Save test metadata - captures full configuration
- ✅ Archive results - back up results directory regularly
For Development/Debugging¶
- ✅ Use Grafana for long tests - live monitoring helps debug issues
- ✅ Check system-metrics.log - verify resource availability
- ✅ Compare vllm-metrics.json across runs - identify regressions
- ❌ Don't delete metrics files - small size, high value for analysis
For Performance Analysis¶
- ✅ Use Streamlit dashboard - comprehensive post-test analysis
- ✅ Compare multiple test runs - identify optimal configurations
- ✅ Correlate client & server metrics - root cause bottlenecks
- ✅ Export to CSV - for detailed statistical analysis