vLLM Grafana 监控仪表盘实战:从 Prometheus 指标到性能与查询统计可视化
【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm
vLLM 仓库在examples/observability/dashboards/grafana/目录下提供了两套现成的 Grafana 仪表盘 JSON 配置,分别面向性能统计(延迟、吞吐)与查询统计(请求量、Token 分布)两类监控场景。本文以该目录下的 README 为主体,完整讲解前置条件、两种部署方式(手动导入与 Grafana Operator)、每个面板的 PromQL 查询含义,并溯源到 vLLM 中这些指标的注册实现,帮助你在生产环境中快速搭起一套可复制、可验证的 vLLM 可观测性方案。
目录结构与前提条件
Grafana 仪表盘所在目录结构如下:
examples/observability/dashboards/ ├── README.md # 仪表盘总览(Grafana 与 Perses 双平台) ├── grafana/ │ ├── README.md # Grafana 平台专属文档 │ ├── performance_statistics.json │ └── query_statistics.json └── perses/ # Perses 平台的等价 YAML 版本上层 总览文档 说明了两套平台(Grafana 与 Perses)提供等价的监控能力:Performance Statistics 跟踪延迟与吞吐,Query Statistics 监控请求量、查询性能与 KPI。Grafana 版采用原生 JSON 格式,兼容任意 Grafana 实例(云端、自托管、Docker),可直接通过 UI 或 API 导入,也可按需包裹进 Kubernetes Operator,无供应商锁定。
按 Grafana README 列出的 Requirements,使用这些仪表盘需要满足:
- Grafana 8.0+(仪表盘 JSON 的
schemaVersion为 40,实测导入时建议 10.x+ 以获得完整面板类型支持); - Grafana 中已配置 Prometheus 数据源:两个仪表盘都引用了名为
DS_PROMETHEUS的 Prometheus 类型数据源变量,导入后 Grafana 会弹出数据源选择框,务必选中你的 Prometheus 实例; - vLLM 部署已启用 Prometheus 指标:vLLM 的 OpenAI 兼容 API Server 默认在
/metrics端点暴露 Prometheus 格式指标(如vllm:e2e_request_latency_seconds_bucket、vllm:time_to_first_token_seconds等),这些正是仪表盘所有面板的数据来源。指标定义与暴露方式可参考仓库内的 Production Metrics 文档;
Prometheus 抓取侧通常配置为针对 vLLM 服务实例的scrape_configs,抓取:8000/metrics端点即可(对应vllm serve <model>的默认端口)。
两套仪表盘:性能统计与查询统计
performance_statistics.json:端到端延迟 / TTFT / ITL / TPS
performance_statistics.json(约 35 KB,标题 "Performance Statistics",默认时间范围now-12h)用于跟踪 vLLM 服务的核心性能指标,按四大区块组织面板:
| 区块(row 面板) | 面板 | 数据来源指标 |
|---|---|---|
| E2E latency over time | E2E Latency over Time(timeseries)、Avg / P50 / P90 / P99(stat) | vllm:e2e_request_latency_seconds(Histogram) |
| TTFT over time | TTFT Over Time(timeseries)、Avg / P50 / P90 / P99(stat) | vllm:time_to_first_token_seconds(Histogram) |
| ITL over time | Time Per Output Token Over Time(timeseries,含 Avg/P50/P90/P99 四条线)、四个分位数 stat | vllm:inter_token_latency_seconds(Histogram) |
| TPS (Tokens Per Second) | TPS Over Time(timeseries,三条曲线) | vllm:generation_tokens_total、vllm:prompt_tokens_total、vllm:iteration_tokens_total_count |
核心面板的代表性 PromQL 如下(均摘自 JSON 的targets[].expr字段):
平均 E2E 延迟曲线(sum/count 相除得到滑动平均值):
rate(vllm:e2e_request_latency_seconds_sum[$__interval]) / rate(vllm:e2e_request_latency_seconds_count[$__interval])P99 E2E 延迟(对 Histogram 桶做分位数插值):
histogram_quantile(0.99, sum by(le) (rate(vllm:e2e_request_latency_seconds_bucket[$__range])))TTFT 与 ITL 的分位数面板采用完全相同的histogram_quantile(..., sum by(le) (rate(..._bucket[...])))模式,仅把指标名换为vllm:time_to_first_token_seconds与vllm:inter_token_latency_seconds;ITL 的 timeseries 面板同时叠加 Avg(sum/count)与 P50/P90/P99 四条曲线,便于观察解码阶段逐 token 延迟的分布漂移。
TPS 面板用三条速率曲线刻画吞吐:
rate(vllm:generation_tokens_total[$__interval]) # 生成 token 速率 rate(vllm:prompt_tokens_total[$__interval]) # 提示 token 速率 rate(vllm:iteration_tokens_total_count[$__interval]) # 引擎每步迭代 token 计数速率其中 TPS 面板的纵轴单位为 tokens/s(unit: "short"量级下按 rate 计),是判断 prefill/decode 吞吐趋势的直接依据。
值得注意的细节:这些延迟 Histogram 面板的字段配置里设置了红色阈值(例如 E2E Latency 面板thresholds.steps中value: 80处由绿转红,单位s),意味着当 P99 端到端延迟超过约 80 秒时统计块会变红提示,属于对超长尾请求的告警式可视化。
在 vLLM 源码中,这三个核心 Histogram 均在 vllm/v1/metrics/loggers.py 中以 PrometheusHistogram类型注册:vllm:time_to_first_token_seconds(L797 附近)、vllm:inter_token_latency_seconds(L830 附近)、vllm:e2e_request_latency_seconds(L913 附近),并带有model_name等标签。也就是说,仪表盘与 vLLM V1 引擎的指标注册是严格对齐的——指标名一旦在引擎侧变更,导入的仪表盘会查询不到数据,升级 vLLM 后建议对照源码核对该文件。
query_statistics.json:请求量、Token 规模分布与按模型过滤
query_statistics.json(约 24 KB,标题 "Query Statistics_New4",默认时间范围now-12h)关注请求侧 KPI,同样分四大区块:
| 区块(row 面板) | 面板 | 数据来源指标 |
|---|---|---|
| Request Over Time | Successful Requests Over Time(timeseries,按model_name分线)、Requests Avg Rate、p50 / p90 / p99 Latency(stat) | vllm:request_success_total、vllm:e2e_request_latency_seconds_bucket |
| Size Distribution | Input Token Size Distribution(histogram)、Avg / p50 / p90 / p99(stat) | vllm:request_prompt_tokens_bucket、vllm:prompt_tokens_total |
| Input Token Over Time | Input Tokens Over Time(timeseries)、Input Tokens/Sec Avg | vllm:prompt_tokens_total |
| Output Token Over Time | Output Tokens Over Time(timeseries)、Output Tokens/Sec Avg | vllm:generation_tokens_total |
与性能仪表盘最关键的区别是:query 仪表盘的所有查询都带{model_name=~"$Deployment_id"}标签过滤,从而支持在多模型混部场景下按部署(即模型名)维度切分视图。代表性查询:
按模型分线的成功请求速率:
sum by (model_name) ( rate(vllm:request_success_total{model_name=~"$Deployment_id"}[$__rate_interval]) )按模型过滤的 p99 延迟:
histogram_quantile(0.99, sum by(le, model_name) (rate(vllm:e2e_request_latency_seconds_bucket{model_name=~"$Deployment_id"}[$__rate_interval])))输入 Token 平均大小(提示 token 速率 / 请求成功率,得到每请求平均输入长度):
sum(rate(vllm:prompt_tokens_total{model_name=~"$Deployment_id"}[$__rate_interval])) / sum(rate(vllm:request_success_total{model_name=~"$Deployment_id"}[$__rate_interval]))模板变量:导入后需要检查的配置
两个仪表盘的templating.variables中定义了 Grafana 变量,这是导入后必须确认的地方:
performance_statistics.json定义了 3 个变量:
DS_PROMETHEUS(datasource 类型,query 为prometheus):数据源选择,导入时由 Grafana 自动弹出确认框;Deployment_id(query 类型,多选 + 含 All 选项):取值为label_values(vllm:generation_tokens_total, model_name),即自动从 Prometheus 中发现所有上报过生成 token 的model_name标签值;agg_method(custom 类型):仅含一个占位选项 "avg : Average / 0.50 : P50 / 0.90 : P90 / 0.99 : P99 / 0.999 : Max (Approx)",从源码结构看这是一个预留的聚合方法变量,当前各面板的分位数是硬编码在查询里的,实际切换分位数需要直接编辑面板查询。
query_statistics.json定义了 5 个变量:
DS_PROMETHEUS:同上;Deployment_id:取值为label_values(vllm:request_success_total, model_name),多选含 All,这是请求类面板过滤下拉框的实际数据源;rush_hours/rush_hours_type/query0:均为隐藏变量(hide: 2),分别对应 "All hours / Rush hours"、"All / Static / Dynamic" 等选项,当前查询表达式中并未引用它们,从源码结构看属于模板遗留的隐藏变量,可按需忽略或清理。
一个实操提醒:Deployment_id变量的发现依赖 Prometheus 中已存在对应指标序列。如果 vLLM 刚启动、尚无成功请求,label_values(vllm:request_success_total, model_name)可能返回空,此时 query 仪表盘的模型下拉框会是空选项,等流量产生后会自动出现。
部署方式一:手动导入(官方推荐)
Grafana README 将 Manual Import 标注为 Recommended,步骤为:
- 打开 Grafana 实例;
- 点击侧边栏
+图标; - 选择 "Import";
- 将仪表盘 JSON 文件的内容粘贴进去,或直接上传 JSON 文件。
由于仓库提供的是完整 JSON 文件,通常直接上传 performance_statistics.json 或 query_statistics.json 即可。导入后在弹窗中把Prometheus数据源指向你的实例并保存。
如果希望在 CI/脚本化场景中批量导入,上层 总览文档 给出了 Grafana HTTP API 的用法:
cd examples/observability/dashboards curl -X POST http://grafana/api/dashboards/db \ -H "Content-Type: application/json" \ -d @grafana/performance_statistics.json该方式要求 Grafana 允许匿名或带凭据访问(生产环境请在请求头补充Authorization: Bearer <service_account_token>一类鉴权,并可将-d包裹进{"dashboard": ..., "overwrite": true}结构以覆盖式更新)。
部署方式二:Grafana Operator(Kubernetes)
若在 Kubernetes 中使用 Grafana Operator,可以按 README 提供的模式,把 JSON 配置包裹进GrafanaDashboard自定义资源:
# 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 }要点:
instanceSelector.matchLabels必须与集群中Grafana自定义资源的标签匹配,可用kubectl get grafana -o yaml查看;json字段需要填入performance_statistics.json的完整 JSON 内容(以{开始、}结束),并保证 YAML 块缩进正确;- 应用方式:
kubectl apply -f your-dashboard.yaml -n <namespace>对query_statistics.json可照同样模式再建一个GrafanaDashboard资源。注意 README 中的apiVersion: grafana.integreatly.org/v1beta1对应 Grafana Operator(Integreatly)的 API 组,不同 Operator 发行版(如 grafana-agent / grafana k8s sidecar 等)的 CRD 可能不同,使用前应先确认集群中安装的 Operator 及其 CRD 版本。
从指标定义到面板:与 vLLM 源码的对应关系
理解这套仪表盘的一个高效路径是把面板查询反向映射到 vLLM 的指标注册代码:
- 指标注册:
vllm:v1/metrics/loggers.py(即 vllm/v1/metrics/loggers.py)负责在 V1 引擎中创建并更新各请求级 Histogram 与 Counter。仪表盘用到的vllm:time_to_first_token_seconds、vllm:inter_token_latency_seconds、vllm:e2e_request_latency_seconds均在该文件注册(分别位于约 L797、L830、L913),Counter 类指标vllm:prompt_tokens_total、vllm:generation_tokens_total、vllm:request_success_total也随引擎日志逻辑更新; - 标签体系:引擎指标带有
model_name标签,这正是 query 仪表盘Deployment_id变量与sum by (model_name)分线查询能工作的原因; - 端点:指标通过 API Server 的
/metrics端点以 Prometheus 文本格式暴露,详见 Production Metrics 文档(其中还列出了/metrics的 curl 输出样例、通用指标表、Speculative Decoding 指标、NIXL KV Connector 指标以及--enable-mfu-metrics的 MFU 指标); - 兼容窗口:文档指出指标有弃用策略——版本
X.Y弃用的指标在X.Y+1隐藏(可用--show-hidden-metrics-for-version=X.Y恢复),在X.Y+2移除。因此跨大版本升级 vLLM 后,若仪表盘出现空面板,应优先核对指标名是否仍存在于loggers.py。
落地检查清单
结合上述内容,一条最小可运行的接入路径是:
- 用
vllm serve <model>(或对应部署方式)启动 vLLM,确认curl http://<host>:8000/metrics能看到vllm:e2e_request_latency_seconds_bucket等序列; - 在 Prometheus 中配置抓取该实例,确认
vllm:request_success_total{model_name="..."}有数据; - 在 Grafana 中配置 Prometheus 数据源,然后按 Manual Import 流程依次导入 performance_statistics.json 与 query_statistics.json,数据源选择你的 Prometheus;
- 发送若干测试请求后检查:性能仪表盘的 E2E/TTFT/ITL/TPS 曲线应出现,查询仪表盘的 "Successful Requests Over Time" 应按
model_name分线显示; - 如部署在 K8s,可改用 Grafana Operator 的
GrafanaDashboard资源方式实现 Dashboard-as-Code,JSON 内容与手动导入完全一致。
若还需要不依赖 Grafana 的方案,同一目录树下的 Perses 仪表盘 提供了等价的 YAML 版本(performance_statistics.yaml/query_statistics.yaml),可通过 Perses CLI(percli apply)导入,两者面板能力一致,可按团队栈任选。
【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考