chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# Monitoring Dashboards
|
||||
|
||||
This directory contains monitoring dashboard configurations for vLLM, providing
|
||||
comprehensive observability for your vLLM deployments.
|
||||
|
||||
## Dashboard Platforms
|
||||
|
||||
We provide dashboards for two popular observability platforms:
|
||||
|
||||
- **[Grafana](https://grafana.com)**
|
||||
- **[Perses](https://perses.dev)**
|
||||
|
||||
## Dashboard Format Approach
|
||||
|
||||
All dashboards are provided in **native formats** that work across different
|
||||
deployment methods:
|
||||
|
||||
### Grafana (JSON)
|
||||
|
||||
- ✅ Works with any Grafana instance (cloud, self-hosted, Docker)
|
||||
- ✅ Direct import via Grafana UI or API
|
||||
- ✅ Can be wrapped in Kubernetes operators when needed
|
||||
- ✅ No vendor lock-in or deployment dependencies
|
||||
|
||||
### Perses (YAML)
|
||||
|
||||
- ✅ Works with standalone Perses instances
|
||||
- ✅ Compatible with Perses API and CLI
|
||||
- ✅ Supports Dashboard-as-Code workflows
|
||||
- ✅ Can be wrapped in Kubernetes operators when needed
|
||||
|
||||
## Dashboard Contents
|
||||
|
||||
Both platforms provide equivalent monitoring capabilities:
|
||||
|
||||
| Dashboard | Description |
|
||||
| --------- | ----------- |
|
||||
| **Performance Statistics** | Tracks latency, throughput, and performance metrics |
|
||||
| **Query Statistics** | Monitors request volume, query performance, and KPIs |
|
||||
|
||||
## Quick Start
|
||||
|
||||
First, navigate to this example's directory:
|
||||
|
||||
```bash
|
||||
cd examples/observability/dashboards
|
||||
```
|
||||
|
||||
### Grafana
|
||||
|
||||
Import the JSON directly into the Grafana UI, or use the API:
|
||||
|
||||
```bash
|
||||
curl -X POST http://grafana/api/dashboards/db \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @grafana/performance_statistics.json
|
||||
```
|
||||
|
||||
### Perses
|
||||
|
||||
Import via the Perses CLI:
|
||||
|
||||
```bash
|
||||
percli apply -f perses/performance_statistics.yaml
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Prometheus** metrics from your vLLM deployment
|
||||
- **Data source** configured in your monitoring platform
|
||||
- **vLLM metrics** enabled and accessible
|
||||
|
||||
## Platform-Specific Documentation
|
||||
|
||||
For detailed deployment instructions and platform-specific options, see:
|
||||
|
||||
- **[Grafana Documentation](grafana)** - JSON dashboards, operator usage, manual import
|
||||
- **[Perses Documentation](perses)** - YAML specs, CLI usage, operator wrapping
|
||||
|
||||
## Contributing
|
||||
|
||||
When adding new dashboards, please:
|
||||
|
||||
1. Provide native formats (JSON for Grafana, YAML specs for Perses)
|
||||
2. Update platform-specific README files
|
||||
3. Ensure dashboards work across deployment methods
|
||||
4. Test with the latest platform versions
|
||||
@@ -0,0 +1,59 @@
|
||||
# Grafana Dashboards for vLLM Monitoring
|
||||
|
||||
This directory contains Grafana dashboard configurations (as JSON) designed to monitor
|
||||
vLLM performance and metrics.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Grafana 8.0+
|
||||
- Prometheus data source configured in Grafana
|
||||
- vLLM deployment with Prometheus metrics enabled
|
||||
|
||||
## Dashboard Descriptions
|
||||
|
||||
- **performance_statistics.json**: Tracks performance metrics including latency and
|
||||
throughput for your vLLM service.
|
||||
- **query_statistics.json**: Tracks query performance, request volume, and key
|
||||
performance indicators for your vLLM service.
|
||||
|
||||
## Deployment Options
|
||||
|
||||
### Manual Import (Recommended)
|
||||
|
||||
The easiest way to use these dashboards is to manually import the JSON configurations
|
||||
directly into your Grafana instance:
|
||||
|
||||
1. Navigate to your Grafana instance
|
||||
2. Click the '+' icon in the sidebar
|
||||
3. Select 'Import'
|
||||
4. Copy and paste the JSON content from the dashboard files, or upload the JSON files
|
||||
directly
|
||||
|
||||
### Grafana Operator
|
||||
|
||||
If you're using the [Grafana Operator](https://github.com/grafana-operator/grafana-operator)
|
||||
in Kubernetes, you can wrap these JSON configurations in a `GrafanaDashboard` custom
|
||||
resource:
|
||||
|
||||
```yaml
|
||||
# Note: Adjust the instanceSelector to match your Grafana instance's labels
|
||||
# You can check with: kubectl get grafana -o yaml
|
||||
apiVersion: grafana.integreatly.org/v1beta1
|
||||
kind: GrafanaDashboard
|
||||
metadata:
|
||||
name: vllm-performance-dashboard
|
||||
spec:
|
||||
instanceSelector:
|
||||
matchLabels:
|
||||
dashboards: grafana # Adjust to match your Grafana instance labels
|
||||
folder: "vLLM Monitoring"
|
||||
json: |
|
||||
# Replace this comment with the complete JSON content from
|
||||
# performance_statistics.json - The JSON should start with { and end with }
|
||||
```
|
||||
|
||||
Then apply to your cluster:
|
||||
|
||||
```bash
|
||||
kubectl apply -f your-dashboard.yaml -n <namespace>
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,760 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "High-level overview of VLLM model deployment behavior and key performance indicators. Designed for Data Scientists and Product Managers to monitor request volume, token throughput, and latency",
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 47,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"collapsed": true,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
|
||||
"id": 20,
|
||||
"panels": [],
|
||||
"title": "Request Over Time",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "req/s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 10, "x": 0, "y": 1 },
|
||||
"id": 1,
|
||||
"options": {
|
||||
"legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "single", "sort": "none" }
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (model_name) (\n rate(vllm:request_success_total{model_name=~\"$Deployment_id\"}[$__rate_interval])\n)",
|
||||
"interval": "1",
|
||||
"legendFormat": "{{model_name}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Successful Requests Over Time",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "req/s"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 10, "y": 1 },
|
||||
"id": 2,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["mean"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "sum(rate(vllm:request_success_total{model_name=~\"$Deployment_id\"}[$__rate_interval]))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Requests Avg Rate",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "Calcultaions": { "index": 0, "text": "Last (not null)" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "ms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 17, "y": 1 },
|
||||
"id": 3,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.50, sum by(le, model_name) (rate(vllm:e2e_request_latency_seconds_bucket{model_name=~\"$Deployment_id\"}[$__rate_interval])))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "p50 Latency",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "Calculation": { "index": 0, "text": "Last (not null)" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "ms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 10, "y": 4 },
|
||||
"id": 4,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.90, sum by(le, model_name) (rate(vllm:e2e_request_latency_seconds_bucket{model_name=~\"$Deployment_id\"}[$__rate_interval])))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "p90 Latency",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "Calculation": { "index": 0, "text": "Last (not null)" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "ms"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 17, "y": 4 },
|
||||
"id": 5,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.99, sum by(le, model_name) (rate(vllm:e2e_request_latency_seconds_bucket{model_name=~\"$Deployment_id\"}[$__rate_interval])))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "p99 Latency",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 7 },
|
||||
"id": 19,
|
||||
"panels": [],
|
||||
"title": "Size Distribution",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"fillOpacity": 80,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"lineWidth": 1,
|
||||
"stacking": { "group": "A", "mode": "none" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 10, "x": 0, "y": 8 },
|
||||
"id": 6,
|
||||
"options": {
|
||||
"legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "single", "sort": "none" }
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (le, model_name) (rate(vllm:request_prompt_tokens_bucket{model_name=~\"$Deployment_id\"}[$__rate_interval]))",
|
||||
"legendFormat": "{{model_name}} le={{le}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Input Token Size Distribution",
|
||||
"type": "histogram"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "calculation ": { "index": 0, "text": "Last (not null)" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 10, "y": 8 },
|
||||
"id": 9,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.90, sum by(le, model_name) (rate(vllm:request_prompt_tokens_bucket{model_name=~\"$Deployment_id\"}[$__rate_interval])))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Input Token Size p90",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "Calculation": { "index": 0, "text": "Last (not null)" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 17, "y": 8 },
|
||||
"id": 8,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.50, sum by(le, model_name) (rate(vllm:request_prompt_tokens_bucket{model_name=~\"$Deployment_id\"}[$__rate_interval])))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Input Token Size p50",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "Calcultaion": { "index": 0, "text": "mean" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 10, "y": 11 },
|
||||
"id": 7,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "sum(rate(vllm:prompt_tokens_total{model_name=~\"$Deployment_id\"}[$__rate_interval]))\n/\nsum(rate(vllm:request_success_total{model_name=~\"$Deployment_id\"}[$__rate_interval]))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Input Token Size Avg",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "Calculation": { "index": 0, "text": "Last (not null)" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 17, "y": 11 },
|
||||
"id": 10,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.99, sum by(le, model_name) (rate(vllm:request_prompt_tokens_bucket{model_name=~\"$Deployment_id\"}[$__rate_interval])))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Input Token Size p99",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"collapsed": true,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 14 },
|
||||
"id": 18,
|
||||
"panels": [],
|
||||
"title": "Input Token Over Time",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 10, "x": 0, "y": 15 },
|
||||
"id": 11,
|
||||
"options": {
|
||||
"legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "single", "sort": "none" }
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (model_name) (rate(vllm:prompt_tokens_total{model_name=~\"$Deployment_id\"}[$__rate_interval]))",
|
||||
"legendFormat": "{{model_name}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Input Tokens Over Time",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "Calculation": { "index": 0, "text": "mean" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 10, "y": 15 },
|
||||
"id": 12,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "sum(rate(vllm:prompt_tokens_total{model_name=~\"$Deployment_id\"}[$__rate_interval]))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Input Tokens/Sec Avg",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": { "h": 1, "w": 24, "x": 0, "y": 21 },
|
||||
"id": 17,
|
||||
"panels": [],
|
||||
"title": "Output Token Over Time",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "palette-classic" },
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": { "legend": false, "tooltip": false, "viz": false },
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": { "type": "linear" },
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": { "group": "A", "mode": "none" },
|
||||
"thresholdsStyle": { "mode": "off" }
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 6, "w": 10, "x": 0, "y": 22 },
|
||||
"id": 13,
|
||||
"options": {
|
||||
"legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true },
|
||||
"tooltip": { "mode": "single", "sort": "none" }
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (model_name) (rate(vllm:generation_tokens_total{model_name=~\"$Deployment_id\"}[$__rate_interval]))",
|
||||
"legendFormat": "{{model_name}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Output Tokens Over Time",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": { "mode": "thresholds" },
|
||||
"mappings": [
|
||||
{ "options": { "Calculation": { "index": 0, "text": "mean" } }, "type": "value" }
|
||||
],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [{ "color": "green", "value": null }, { "color": "red", "value": 80 }]
|
||||
},
|
||||
"unit": "cps"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": { "h": 3, "w": 7, "x": 10, "y": 22 },
|
||||
"id": 14,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.3.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"expr": "sum(rate(vllm:generation_tokens_total{model_name=~\"$Deployment_id\"}[$__rate_interval]))",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Output Tokens/Sec Avg",
|
||||
"type": "stat"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"schemaVersion": 40,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": { "text": "Prometheus", "value": "4184fc20-68a7-483a-8d9b-7caa59c680dd" },
|
||||
"label": "datasource",
|
||||
"name": "DS_PROMETHEUS",
|
||||
"options": [],
|
||||
"query": "prometheus",
|
||||
"refresh": 1,
|
||||
"type": "datasource"
|
||||
},
|
||||
{
|
||||
"current": { "text": ["All"], "value": ["$__all"] },
|
||||
"definition": "label_values(vllm:request_success_total,model_name)",
|
||||
"includeAll": true,
|
||||
"label": "Deployment_ID",
|
||||
"multi": true,
|
||||
"name": "Deployment_id",
|
||||
"options": [],
|
||||
"query": {
|
||||
"qryType": 1,
|
||||
"query": "label_values(vllm:request_success_total,model_name)",
|
||||
"refId": "PrometheusVariableQueryEditor-VariableQuery"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"sort": 1,
|
||||
"type": "query"
|
||||
},
|
||||
{
|
||||
"current": { "text": "All hours", "value": "All hours" },
|
||||
"hide": 2,
|
||||
"label": "Rush Hours Only",
|
||||
"name": "rush_hours",
|
||||
"options": [
|
||||
{ "selected": true, "text": "false", "value": "All hours" },
|
||||
{ "selected": false, "text": "true", "value": "Rush hours" }
|
||||
],
|
||||
"query": "false : All hours, true : Rush hours",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"current": { "text": "All", "value": "All" },
|
||||
"hide": 2,
|
||||
"label": "Rush Hours Type",
|
||||
"name": "rush_hours_type",
|
||||
"options": [
|
||||
{ "selected": true, "text": "^All__.*$", "value": "All" },
|
||||
{ "selected": false, "text": "^Static__.*$", "value": "Static" },
|
||||
{ "selected": false, "text": "^Dynamic__.*$", "value": "Dynamic" }
|
||||
],
|
||||
"query": "^All__.*$ : All, ^Static__.*$ : Static, ^Dynamic__.*$ : Dynamic",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"current": { "text": "", "value": "" },
|
||||
"hide": 2,
|
||||
"name": "query0",
|
||||
"options": [],
|
||||
"query": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"type": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": { "from": "now-12h", "to": "now" },
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Query Statistics_New4",
|
||||
"uid": "query-statistics4",
|
||||
"version": 2,
|
||||
"weekStart": ""
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Perses Dashboards for vLLM Monitoring
|
||||
|
||||
This directory contains Perses dashboard configurations designed to monitor vLLM
|
||||
performance and metrics.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Perses instance (standalone or via operator)
|
||||
- Prometheus data source configured in Perses
|
||||
- vLLM deployment with Prometheus metrics enabled
|
||||
|
||||
## Dashboard Format
|
||||
|
||||
We provide dashboards in the **native Perses YAML format** that works across all
|
||||
deployment methods:
|
||||
|
||||
- **Files**: `*.yaml` (native Perses dashboard specifications)
|
||||
- **Format**: Pure dashboard specifications that work everywhere
|
||||
- **Usage**: Works with standalone Perses, API imports, CLI, and file provisioning
|
||||
- **Kubernetes**: Directly compatible with Perses Operator
|
||||
|
||||
## Dashboard Descriptions
|
||||
|
||||
- **performance_statistics.yaml**: Performance metrics with aggregated latency
|
||||
statistics
|
||||
- **query_statistics.yaml**: Query performance and deployment metrics
|
||||
|
||||
## Deployment Options
|
||||
|
||||
### Direct Import to Perses
|
||||
|
||||
Import the dashboard specifications via Perses API or CLI:
|
||||
|
||||
```bash
|
||||
percli apply -f performance_statistics.yaml
|
||||
```
|
||||
|
||||
### Perses Operator (Kubernetes)
|
||||
|
||||
The native YAML format works directly with the Perses Operator:
|
||||
|
||||
```bash
|
||||
kubectl apply -f performance_statistics.yaml -n <namespace>
|
||||
```
|
||||
|
||||
### File Provisioning
|
||||
|
||||
Place the YAML files in a Perses provisioning folder for automatic loading.
|
||||
@@ -0,0 +1,764 @@
|
||||
kind: PersesDashboard
|
||||
metadata:
|
||||
name: performance-statistics
|
||||
createdAt: 0001-01-01T00:00:00Z
|
||||
updatedAt: 0001-01-01T00:00:00Z
|
||||
version: 0
|
||||
project: ""
|
||||
spec:
|
||||
display:
|
||||
name: Performance Statistics
|
||||
|
||||
variables:
|
||||
- kind: ListVariable
|
||||
spec:
|
||||
display:
|
||||
name: Deployment_ID
|
||||
hidden: false
|
||||
name: Deployment_id
|
||||
allowAllValue: true
|
||||
allowMultiple: true
|
||||
defaultValue:
|
||||
- $__all
|
||||
sort: alphabetical-asc
|
||||
plugin:
|
||||
kind: PrometheusLabelValuesVariable
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
labelName: model_name
|
||||
matchers:
|
||||
# Any one vllm metric that always carries model_name
|
||||
- vllm:generation_tokens_total{}
|
||||
|
||||
panels:
|
||||
"1":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: E2E Latency over Time
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend:
|
||||
mode: table
|
||||
position: bottom
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
# avg latency by model = sum(rate(sum)) / sum(rate(count))
|
||||
query: >
|
||||
sum by (model_name) (rate(vllm:e2e_request_latency_seconds_sum{model_name=~"$Deployment_id"}[$__interval]))
|
||||
/
|
||||
sum by (model_name) (rate(vllm:e2e_request_latency_seconds_count{model_name=~"$Deployment_id"}[$__interval]))
|
||||
seriesNameFormat: '{{model_name}}'
|
||||
|
||||
"2":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: E2E Latency (Avg)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
(sum by (model_name) (increase(vllm:e2e_request_latency_seconds_sum{model_name=~"$Deployment_id"}[$__range])))
|
||||
/
|
||||
(sum by (model_name) (increase(vllm:e2e_request_latency_seconds_count{model_name=~"$Deployment_id"}[$__range])))
|
||||
|
||||
"3":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: E2E Latency (P50)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.50,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:e2e_request_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"4":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: E2E Latency (P90)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.90,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:e2e_request_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"5":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: E2E Latency (P99)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.99,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:e2e_request_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"6":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: TTFT over Time
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend:
|
||||
mode: table
|
||||
position: bottom
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
sum by (model_name) (rate(vllm:time_to_first_token_seconds_sum{model_name=~"$Deployment_id"}[$__interval]))
|
||||
/
|
||||
sum by (model_name) (rate(vllm:time_to_first_token_seconds_count{model_name=~"$Deployment_id"}[$__interval]))
|
||||
seriesNameFormat: '{{model_name}}'
|
||||
|
||||
"7":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: TTFT (Avg)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
(sum by (model_name) (increase(vllm:time_to_first_token_seconds_sum{model_name=~"$Deployment_id"}[$__range])))
|
||||
/
|
||||
(sum by (model_name) (increase(vllm:time_to_first_token_seconds_count{model_name=~"$Deployment_id"}[$__range])))
|
||||
|
||||
"8":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: TTFT (P50)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.50,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:time_to_first_token_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"9":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: TTFT (P90)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.90,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:time_to_first_token_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"10":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: TTFT (P99)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.99,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:time_to_first_token_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"11":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: ITL (Time per Output Token) over Time
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend:
|
||||
mode: table
|
||||
position: bottom
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
sum by (model_name) (rate(vllm:inter_token_latency_seconds_sum{model_name=~"$Deployment_id"}[$__interval]))
|
||||
/
|
||||
sum by (model_name) (rate(vllm:inter_token_latency_seconds_count{model_name=~"$Deployment_id"}[$__interval]))
|
||||
seriesNameFormat: '{{model_name}}'
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.50,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:inter_token_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
seriesNameFormat: '{{model_name}} p50'
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.90,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:inter_token_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
seriesNameFormat: '{{model_name}} p90'
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.99,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:inter_token_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
seriesNameFormat: '{{model_name}} p99'
|
||||
|
||||
"12":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: ITL (Avg)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
(sum by (model_name) (increase(vllm:inter_token_latency_seconds_sum{model_name=~"$Deployment_id"}[$__range])))
|
||||
/
|
||||
(sum by (model_name) (increase(vllm:inter_token_latency_seconds_count{model_name=~"$Deployment_id"}[$__range])))
|
||||
|
||||
"13":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: ITL (P50)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.50,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:inter_token_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"14":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: ITL (P90)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.90,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:inter_token_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"15":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: ITL (P99)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
histogram_quantile(
|
||||
0.99,
|
||||
sum by (le, model_name) (
|
||||
rate(vllm:inter_token_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__interval])
|
||||
)
|
||||
)
|
||||
|
||||
"16":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: TPS (Tokens/sec) over Time
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend:
|
||||
mode: table
|
||||
position: bottom
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
sum by (model_name) (rate(vllm:generation_tokens_total{model_name=~"$Deployment_id"}[$__interval]))
|
||||
seriesNameFormat: '{{model_name}} generation'
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
sum by (model_name) (rate(vllm:prompt_tokens_total{model_name=~"$Deployment_id"}[$__interval]))
|
||||
seriesNameFormat: '{{model_name}} prompt'
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
# overall iteration tokens/sec if exposed
|
||||
query: >
|
||||
rate(vllm:iteration_tokens_total_count[$__interval])
|
||||
seriesNameFormat: 'iteration overall'
|
||||
|
||||
"17":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: KV Cache Usage (avg %)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
# Multiply by 100 so we can read it as a percentage without setting a unit (avoids CUE unit conflicts)
|
||||
query: >
|
||||
100 * avg(vllm:kv_cache_usage_perc)
|
||||
|
||||
"18":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: Running Requests by Pod
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend:
|
||||
mode: table
|
||||
position: bottom
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
sum by (pod) (vllm:num_requests_running)
|
||||
seriesNameFormat: '{{pod}}'
|
||||
|
||||
"19":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: Waiting Requests by Pod
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend:
|
||||
mode: table
|
||||
position: bottom
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: >
|
||||
sum by (pod) (vllm:num_requests_waiting)
|
||||
seriesNameFormat: '{{pod}}'
|
||||
|
||||
"20":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: Running Requests (sum)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: sum(vllm:num_requests_running)
|
||||
|
||||
"21":
|
||||
kind: Panel
|
||||
spec:
|
||||
display:
|
||||
name: Waiting Requests (sum)
|
||||
plugin:
|
||||
kind: StatChart
|
||||
spec:
|
||||
calculation: last-number
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource:
|
||||
kind: PrometheusDatasource
|
||||
name: accelerators-thanos-querier-datasource
|
||||
query: sum(vllm:num_requests_waiting)
|
||||
|
||||
layouts:
|
||||
- kind: Grid
|
||||
spec:
|
||||
display:
|
||||
title: Overview
|
||||
items:
|
||||
- x: 0
|
||||
y: 0
|
||||
width: 6
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/17' } # KV cache %
|
||||
- x: 6
|
||||
y: 0
|
||||
width: 6
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/20' } # running sum
|
||||
- x: 12
|
||||
y: 0
|
||||
width: 6
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/21' } # waiting sum
|
||||
|
||||
- kind: Grid
|
||||
spec:
|
||||
display:
|
||||
title: E2E Latency
|
||||
items:
|
||||
- x: 0
|
||||
y: 1
|
||||
width: 10
|
||||
height: 6
|
||||
content: { $ref: '#/spec/panels/1' }
|
||||
- x: 10
|
||||
y: 1
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/2' }
|
||||
- x: 17
|
||||
y: 1
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/3' }
|
||||
- x: 10
|
||||
y: 4
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/4' }
|
||||
- x: 17
|
||||
y: 4
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/5' }
|
||||
|
||||
- kind: Grid
|
||||
spec:
|
||||
display:
|
||||
title: TTFT
|
||||
items:
|
||||
- x: 0
|
||||
y: 8
|
||||
width: 10
|
||||
height: 6
|
||||
content: { $ref: '#/spec/panels/6' }
|
||||
- x: 10
|
||||
y: 8
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/7' }
|
||||
- x: 17
|
||||
y: 8
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/8' }
|
||||
- x: 10
|
||||
y: 11
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/9' }
|
||||
- x: 17
|
||||
y: 11
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/10' }
|
||||
|
||||
- kind: Grid
|
||||
spec:
|
||||
display:
|
||||
title: ITL (Time per Output Token)
|
||||
items:
|
||||
- x: 0
|
||||
y: 15
|
||||
width: 10
|
||||
height: 6
|
||||
content: { $ref: '#/spec/panels/11' }
|
||||
- x: 10
|
||||
y: 15
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/12' }
|
||||
- x: 17
|
||||
y: 15
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/13' }
|
||||
- x: 10
|
||||
y: 18
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/14' }
|
||||
- x: 17
|
||||
y: 18
|
||||
width: 7
|
||||
height: 3
|
||||
content: { $ref: '#/spec/panels/15' }
|
||||
|
||||
- kind: Grid
|
||||
spec:
|
||||
display:
|
||||
title: TPS (Prompt / Generation / Iteration)
|
||||
items:
|
||||
- x: 0
|
||||
y: 22
|
||||
width: 14
|
||||
height: 6
|
||||
content: { $ref: '#/spec/panels/16' }
|
||||
|
||||
- kind: Grid
|
||||
spec:
|
||||
display:
|
||||
title: Per-Pod Request State
|
||||
items:
|
||||
- x: 0
|
||||
y: 28
|
||||
width: 12
|
||||
height: 6
|
||||
content: { $ref: '#/spec/panels/18' }
|
||||
- x: 12
|
||||
y: 28
|
||||
width: 12
|
||||
height: 6
|
||||
content: { $ref: '#/spec/panels/19' }
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
kind: PersesDashboard
|
||||
metadata:
|
||||
name: query-statistics
|
||||
createdAt: 0001-01-01T00:00:00Z
|
||||
updatedAt: 0001-01-01T00:00:00Z
|
||||
version: 0
|
||||
project: ""
|
||||
spec:
|
||||
display:
|
||||
name: Query Statistics_New
|
||||
|
||||
variables:
|
||||
- kind: ListVariable
|
||||
spec:
|
||||
name: NS
|
||||
display: { name: Namespace }
|
||||
allowMultiple: false
|
||||
defaultValue: llm-d
|
||||
plugin:
|
||||
kind: PrometheusLabelValuesVariable
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
labelName: namespace
|
||||
matchers:
|
||||
- up{service=~".*vllm.*"}
|
||||
|
||||
- kind: ListVariable
|
||||
spec:
|
||||
name: SVC
|
||||
display: { name: Service }
|
||||
allowMultiple: false
|
||||
defaultValue: vllm-qwen2-0-5b-sim
|
||||
plugin:
|
||||
kind: PrometheusLabelValuesVariable
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
labelName: service
|
||||
matchers:
|
||||
- up{namespace="$NS",service=~".*vllm.*"}
|
||||
|
||||
- kind: ListVariable
|
||||
spec:
|
||||
name: MODEL
|
||||
display: { name: Model (real vLLM) }
|
||||
allowAllValue: true
|
||||
allowMultiple: true
|
||||
defaultValue: ["$__all"]
|
||||
plugin:
|
||||
kind: PrometheusLabelValuesVariable
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
labelName: model_name
|
||||
matchers:
|
||||
- vllm:request_success_total{namespace="$NS",service="$SVC"}
|
||||
|
||||
panels:
|
||||
|
||||
# --- Core (works on Simulator & Real) ---
|
||||
core_running_now:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Running Requests (now) }
|
||||
plugin: { kind: StatChart, spec: { calculation: last-number } }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum(vllm:num_requests_running{namespace="$NS",service="$SVC"}) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
core_waiting_now:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Waiting Requests (now) }
|
||||
plugin: { kind: StatChart, spec: { calculation: last-number } }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum(vllm:num_requests_waiting{namespace="$NS",service="$SVC"}) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
core_kv_usage_now:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: KV Cache Usage (0–1) }
|
||||
plugin: { kind: StatChart, spec: { calculation: last-number } }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: avg(vllm:kv_cache_usage_perc{namespace="$NS",service="$SVC"}) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
core_running_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Running Over Time }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum by (service) (vllm:num_requests_running{namespace="$NS",service="$SVC"}) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
core_waiting_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Waiting Over Time }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum by (service) (vllm:num_requests_waiting{namespace="$NS",service="$SVC"}) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
core_targets_up:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Scrape Targets Up }
|
||||
plugin: { kind: StatChart, spec: { calculation: last-number } }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: count(up{namespace="$NS",service="$SVC"} == 1) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
# --- KV Cache as Percent (works on Simulator & Real) ---
|
||||
core_kv_usage_pct_now:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: KV Cache Usage (%) – now }
|
||||
plugin: { kind: StatChart, spec: { calculation: last-number } }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
# multiply by 100 to present percentage; omit format.unit to avoid schema conflicts
|
||||
query: (avg(vllm:kv_cache_usage_perc{namespace="$NS",service="$SVC"}) * 100) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
core_kv_usage_pct_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: KV Cache Usage (%) – over time }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: (avg by (service) (vllm:kv_cache_usage_perc{namespace="$NS",service="$SVC"}) * 100) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
# --- Per-Pod breakdowns (works on Simulator & Real) ---
|
||||
per_pod_running_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Running by Pod }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum by (pod) (vllm:num_requests_running{namespace="$NS",service="$SVC"}) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
per_pod_waiting_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Waiting by Pod }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum by (pod) (vllm:num_requests_waiting{namespace="$NS",service="$SVC"}) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
per_pod_kv_pct_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: KV Cache (%) by Pod }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
# if your exporter labels kv metric with pod (the sim does), this works; otherwise it will just return empty
|
||||
query: (avg by (pod) (vllm:kv_cache_usage_perc{namespace="$NS",service="$SVC"}) * 100) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
# --- Real vLLM only (zeros on simulator) ---
|
||||
real_req_rate_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Request Rate (real vLLM) }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum by (model_name) (rate(vllm:request_success_total{namespace="$NS",service="$SVC",model_name=~"$MODEL"}[$__interval])) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
real_p50:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: p50 Latency (real vLLM) }
|
||||
plugin: { kind: StatChart, spec: { calculation: last-number } }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: histogram_quantile(0.50, sum by (le, model_name) (rate(vllm:e2e_request_latency_seconds_bucket{namespace="$NS",service="$SVC",model_name=~"$MODEL"}[$__interval]))) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
real_p90:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: p90 Latency (real vLLM) }
|
||||
plugin: { kind: StatChart, spec: { calculation: last-number } }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: histogram_quantile(0.90, sum by (le, model_name) (rate(vllm:e2e_request_latency_seconds_bucket{namespace="$NS",service="$SVC",model_name=~"$MODEL"}[$__interval]))) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
real_p99:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: p99 Latency (real vLLM) }
|
||||
plugin: { kind: StatChart, spec: { calculation: last-number } }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: histogram_quantile(0.99, sum by (le, model_name) (rate(vllm:e2e_request_latency_seconds_bucket{namespace="$NS",service="$SVC",model_name=~"$MODEL"}[$__interval]))) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
real_input_tokens_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Input Tokens / sec (real vLLM) }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum by (model_name) (rate(vllm:prompt_tokens_total{namespace="$NS",service="$SVC",model_name=~"$MODEL"}[$__interval])) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
real_output_tokens_ts:
|
||||
kind: Panel
|
||||
spec:
|
||||
display: { name: Output Tokens / sec (real vLLM) }
|
||||
plugin:
|
||||
kind: TimeSeriesChart
|
||||
spec:
|
||||
legend: { mode: table, position: bottom }
|
||||
visual: { display: line, lineWidth: 1, areaOpacity: 0.3 }
|
||||
queries:
|
||||
- kind: TimeSeriesQuery
|
||||
spec:
|
||||
plugin:
|
||||
kind: PrometheusTimeSeriesQuery
|
||||
spec:
|
||||
datasource: { kind: PrometheusDatasource, name: accelerators-thanos-querier-datasource }
|
||||
query: sum by (model_name) (rate(vllm:generation_tokens_total{namespace="$NS",service="$SVC",model_name=~"$MODEL"}[$__interval])) or vector(0)
|
||||
minStep: "15s"
|
||||
|
||||
layouts:
|
||||
- kind: Grid
|
||||
spec:
|
||||
display: { title: Core (Sim & Real) }
|
||||
items:
|
||||
- { x: 0, y: 0, width: 6, height: 3, content: { $ref: '#/spec/panels/core_running_now' } }
|
||||
- { x: 6, y: 0, width: 6, height: 3, content: { $ref: '#/spec/panels/core_waiting_now' } }
|
||||
- { x: 12, y: 0, width: 6, height: 3, content: { $ref: '#/spec/panels/core_kv_usage_now' } }
|
||||
- { x: 18, y: 0, width: 6, height: 3, content: { $ref: '#/spec/panels/core_targets_up' } }
|
||||
- { x: 0, y: 3, width: 12, height: 6, content: { $ref: '#/spec/panels/core_running_ts' } }
|
||||
- { x: 12, y: 3, width: 12, height: 6, content: { $ref: '#/spec/panels/core_waiting_ts' } }
|
||||
|
||||
- kind: Grid
|
||||
spec:
|
||||
display: { title: KV Cache (%) }
|
||||
items:
|
||||
- { x: 0, y: 9, width: 6, height: 3, content: { $ref: '#/spec/panels/core_kv_usage_pct_now' } }
|
||||
- { x: 6, y: 9, width: 18, height: 6, content: { $ref: '#/spec/panels/core_kv_usage_pct_ts' } }
|
||||
|
||||
- kind: Grid
|
||||
spec:
|
||||
display: { title: Per-Pod breakdowns }
|
||||
items:
|
||||
- { x: 0, y: 15, width: 12, height: 6, content: { $ref: '#/spec/panels/per_pod_running_ts' } }
|
||||
- { x: 12, y: 15, width: 12, height: 6, content: { $ref: '#/spec/panels/per_pod_waiting_ts' } }
|
||||
- { x: 0, y: 21, width: 24, height: 6, content: { $ref: '#/spec/panels/per_pod_kv_pct_ts' } }
|
||||
|
||||
- kind: Grid
|
||||
spec:
|
||||
display: { title: Real vLLM only (shows 0 on simulator) }
|
||||
items:
|
||||
- { x: 0, y: 27, width: 12, height: 6, content: { $ref: '#/spec/panels/real_req_rate_ts' } }
|
||||
- { x: 12, y: 27, width: 4, height: 3, content: { $ref: '#/spec/panels/real_p50' } }
|
||||
- { x: 16, y: 27, width: 4, height: 3, content: { $ref: '#/spec/panels/real_p90' } }
|
||||
- { x: 20, y: 27, width: 4, height: 3, content: { $ref: '#/spec/panels/real_p99' } }
|
||||
- { x: 0, y: 33, width: 12, height: 6, content: { $ref: '#/spec/panels/real_input_tokens_ts' } }
|
||||
- { x: 12, y: 33, width: 12, height: 6, content: { $ref: '#/spec/panels/real_output_tokens_ts' } }
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
from vllm import LLM, SamplingParams
|
||||
from vllm.v1.metrics.reader import Counter, Gauge, Histogram, Vector
|
||||
|
||||
# Sample prompts.
|
||||
prompts = [
|
||||
"Hello, my name is",
|
||||
"The president of the United States is",
|
||||
"The capital of France is",
|
||||
"The future of AI is",
|
||||
]
|
||||
# Create a sampling params object.
|
||||
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
|
||||
|
||||
|
||||
def main():
|
||||
# Create an LLM.
|
||||
llm = LLM(model="facebook/opt-125m", disable_log_stats=False)
|
||||
|
||||
# Generate texts from the prompts.
|
||||
outputs = llm.generate(prompts, sampling_params)
|
||||
|
||||
# Print the outputs.
|
||||
print("-" * 50)
|
||||
for output in outputs:
|
||||
prompt = output.prompt
|
||||
generated_text = output.outputs[0].text
|
||||
print(f"Prompt: {prompt!r}\nGenerated text: {generated_text!r}")
|
||||
print("-" * 50)
|
||||
|
||||
# Dump all metrics
|
||||
for metric in llm.get_metrics():
|
||||
if isinstance(metric, Gauge):
|
||||
print(f"{metric.name} (gauge) = {metric.value}")
|
||||
elif isinstance(metric, Counter):
|
||||
print(f"{metric.name} (counter) = {metric.value}")
|
||||
elif isinstance(metric, Vector):
|
||||
print(f"{metric.name} (vector) = {metric.values}")
|
||||
elif isinstance(metric, Histogram):
|
||||
print(f"{metric.name} (histogram)")
|
||||
print(f" sum = {metric.sum}")
|
||||
print(f" count = {metric.count}")
|
||||
for bucket_le, value in metric.buckets.items():
|
||||
print(f" {bucket_le} = {value}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,86 @@
|
||||
# Setup OpenTelemetry POC
|
||||
|
||||
> **Note:** The core OpenTelemetry packages (`opentelemetry-sdk`, `opentelemetry-api`, `opentelemetry-exporter-otlp`, `opentelemetry-semantic-conventions-ai`) are bundled with vLLM. Manual installation is not required.
|
||||
|
||||
1. Start Jaeger in a docker container:
|
||||
|
||||
```bash
|
||||
# From: https://www.jaegertracing.io/docs/1.57/getting-started/
|
||||
docker run --rm --name jaeger \
|
||||
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
|
||||
-p 6831:6831/udp \
|
||||
-p 6832:6832/udp \
|
||||
-p 5778:5778 \
|
||||
-p 16686:16686 \
|
||||
-p 4317:4317 \
|
||||
-p 4318:4318 \
|
||||
-p 14250:14250 \
|
||||
-p 14268:14268 \
|
||||
-p 14269:14269 \
|
||||
-p 9411:9411 \
|
||||
jaegertracing/all-in-one:1.57
|
||||
```
|
||||
|
||||
1. In a new shell, export Jaeger IP:
|
||||
|
||||
```bash
|
||||
export JAEGER_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' jaeger)
|
||||
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=grpc://$JAEGER_IP:4317
|
||||
```
|
||||
|
||||
Then set vLLM's service name for OpenTelemetry, enable insecure connections to Jaeger and run vLLM:
|
||||
|
||||
```bash
|
||||
export OTEL_SERVICE_NAME="vllm-server"
|
||||
export OTEL_EXPORTER_OTLP_TRACES_INSECURE=true
|
||||
vllm serve facebook/opt-125m --otlp-traces-endpoint="$OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"
|
||||
```
|
||||
|
||||
1. In a new shell, send requests with trace context from a dummy client
|
||||
|
||||
```bash
|
||||
export JAEGER_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' jaeger)
|
||||
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=grpc://$JAEGER_IP:4317
|
||||
export OTEL_EXPORTER_OTLP_TRACES_INSECURE=true
|
||||
export OTEL_SERVICE_NAME="client-service"
|
||||
python dummy_client.py
|
||||
```
|
||||
|
||||
1. Open Jaeger webui: <http://localhost:16686/>
|
||||
|
||||
In the search pane, select `vllm-server` service and hit `Find Traces`. You should get a list of traces, one for each request.
|
||||

|
||||
|
||||
1. Clicking on a trace will show its spans and their tags. In this demo, each trace has 2 spans. One from the dummy client containing the prompt text and one from vLLM containing metadata about the request.
|
||||

|
||||
|
||||
## Exporter Protocol
|
||||
|
||||
OpenTelemetry supports either `grpc` or `http/protobuf` as the transport protocol for trace data in the exporter.
|
||||
By default, `grpc` is used. To set `http/protobuf` as the protocol, configure the `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` environment variable as follows:
|
||||
|
||||
```bash
|
||||
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
|
||||
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://$JAEGER_IP:4318/v1/traces
|
||||
vllm serve facebook/opt-125m --otlp-traces-endpoint="$OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"
|
||||
```
|
||||
|
||||
## Instrumentation of FastAPI
|
||||
|
||||
OpenTelemetry allows automatic instrumentation of FastAPI.
|
||||
|
||||
1. Install the instrumentation library
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-instrumentation-fastapi
|
||||
```
|
||||
|
||||
1. Run vLLM with `opentelemetry-instrument`
|
||||
|
||||
```bash
|
||||
opentelemetry-instrument vllm serve facebook/opt-125m
|
||||
```
|
||||
|
||||
1. Send a request to vLLM and find its trace in Jaeger. It should contain spans from FastAPI.
|
||||
|
||||

|
||||
@@ -0,0 +1,34 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
import requests
|
||||
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
||||
from opentelemetry.sdk.trace import TracerProvider
|
||||
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
|
||||
from opentelemetry.trace import SpanKind, set_tracer_provider
|
||||
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
|
||||
|
||||
trace_provider = TracerProvider()
|
||||
set_tracer_provider(trace_provider)
|
||||
|
||||
trace_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
|
||||
trace_provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
|
||||
|
||||
tracer = trace_provider.get_tracer("dummy-client")
|
||||
|
||||
url = "http://localhost:8000/v1/completions"
|
||||
with tracer.start_as_current_span("client-span", kind=SpanKind.CLIENT) as span:
|
||||
prompt = "San Francisco is a"
|
||||
span.set_attribute("prompt", prompt)
|
||||
headers = {}
|
||||
TraceContextTextMapPropagator().inject(headers)
|
||||
payload = {
|
||||
"model": "facebook/opt-125m",
|
||||
"prompt": prompt,
|
||||
"max_tokens": 10,
|
||||
"n": 3,
|
||||
"use_beam_search": "true",
|
||||
"temperature": 0.0,
|
||||
# "stream": True,
|
||||
}
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
@@ -0,0 +1,57 @@
|
||||
# Prometheus and Grafana
|
||||
|
||||
This is a simple example that shows you how to connect vLLM metric logging to the Prometheus/Grafana stack. For this example, we launch Prometheus and Grafana via Docker. You can checkout other methods through [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) websites.
|
||||
|
||||
Install:
|
||||
|
||||
- [`docker`](https://docs.docker.com/engine/install/)
|
||||
- [`docker compose`](https://docs.docker.com/compose/install/linux/#install-using-the-repository)
|
||||
|
||||
## Launch
|
||||
|
||||
Prometheus metric logging is enabled by default in the OpenAI-compatible server. Launch via the entrypoint:
|
||||
|
||||
```bash
|
||||
vllm serve mistralai/Mistral-7B-v0.1 \
|
||||
--max-model-len 2048
|
||||
```
|
||||
|
||||
Launch Prometheus and Grafana servers with `docker compose`:
|
||||
|
||||
```bash
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Submit some sample requests to the server:
|
||||
|
||||
```bash
|
||||
wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
|
||||
|
||||
vllm bench serve \
|
||||
--model mistralai/Mistral-7B-v0.1 \
|
||||
--tokenizer mistralai/Mistral-7B-v0.1 \
|
||||
--endpoint /v1/completions \
|
||||
--dataset-name sharegpt \
|
||||
--dataset-path ShareGPT_V3_unfiltered_cleaned_split.json \
|
||||
--request-rate 3.0
|
||||
```
|
||||
|
||||
Navigating to [`http://localhost:8000/metrics`](http://localhost:8000/metrics) will show the raw Prometheus metrics being exposed by vLLM.
|
||||
|
||||
## Grafana Dashboard
|
||||
|
||||
Navigate to [`http://localhost:3000`](http://localhost:3000). Log in with the default username (`admin`) and password (`admin`).
|
||||
|
||||
### Add Prometheus Data Source
|
||||
|
||||
Navigate to [`http://localhost:3000/connections/datasources/new`](http://localhost:3000/connections/datasources/new) and select Prometheus.
|
||||
|
||||
On Prometheus configuration page, we need to add the `Prometheus Server URL` in `Connection`. For this setup, Grafana and Prometheus are running in separate containers, but Docker creates DNS name for each container. You can just use `http://prometheus:9090`.
|
||||
|
||||
Click `Save & Test`. You should get a green check saying "Successfully queried the Prometheus API.".
|
||||
|
||||
### Import Dashboard
|
||||
|
||||
Navigate to [`http://localhost:3000/dashboard/import`](http://localhost:3000/dashboard/import), upload `grafana.json`, and select the `prometheus` datasource. You should see a screen that looks like the following:
|
||||
|
||||

|
||||
@@ -0,0 +1,19 @@
|
||||
# docker-compose.yaml
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway" # allow a direct connection from container to the local machine
|
||||
ports:
|
||||
- "9090:9090" # the default port used by Prometheus
|
||||
volumes:
|
||||
- ${PWD}/prometheus.yaml:/etc/prometheus/prometheus.yml # mount Prometheus config file
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
depends_on:
|
||||
- prometheus
|
||||
ports:
|
||||
- "3000:3000" # the default port used by Grafana
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
# prometheus.yaml
|
||||
global:
|
||||
scrape_interval: 5s
|
||||
evaluation_interval: 30s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: vllm
|
||||
static_configs:
|
||||
- targets:
|
||||
- 'host.docker.internal:8000'
|
||||
Reference in New Issue
Block a user