Grafana连接Prometheus、Loki等数据源,将指标与日志转化为可视化仪表盘。通过变量模板、告警规则与通知渠道,构建从数据采集到告警触发的完整监控闭环。文章设计AI推理服务的Grafana监控面板,涵盖GPU利用率、请求延迟与Token吞吐量的可视化方案。
需要学习Grafana可视化,从原型到生产,工程化能力决定应用能否真正落地。本篇涵盖MLOps/LLMOps、模型部署、CI/CD、版本管理,帮助你实现AI工程化交付。
目录
可视化演示
展示Grafana监控仪表盘实时指标、告警规则评估流程与多数据源集成架构,切换模式查看AI推理服务监控核心机制。
本节配有交互动效(进入视口后自动加载,约 3KB)。
AI推理服务监控仪表盘 青色为GPU利用率曲线,橙色为延迟,绿色为吞吐量 SLI = 可用性 × 延迟达标率 Grafana连接Prometheus数据源,将GPU利用率、请求延迟P99和Token吞吐量可视化到面板上实时监控
Grafana架构与多数据源集成
Grafana 是一个开源的可观测性可视化平台,其核心设计理念是作为数据源的可视化前端,而非数据存储系统。Grafana 本身不存储任何指标数据,所有查询请求都会被代理转发到后端配置的数据源,由数据源引擎执行查询并返回结果。这一架构使得 Grafana 能够以统一的界面呈现来自不同存储系统的数据,极大地降低了运维团队在监控场景下的认知负担。
Grafana 通过插件机制支持多种数据源,包括但不限于 Prometheus、Loki、Tempo、Elasticsearch、InfluxDB、MySQL、PostgreSQL、CloudWatch 等。每个数据源以独立插件的形式注册到 Grafana 系统中,安装后即可在数据源配置页面添加。数据源插件提供专属的查询编辑器,例如 Prometheus 数据源的查询编辑器支持 PromQL 语法高亮和自动补全,Loki 数据源则提供 LogQL 的编辑支持。这种插件化的设计使得新增数据源支持无需修改 Grafana 核心代码,社区和第三方厂商可以独立开发和发布数据源插件。
数据源代理模式是 Grafana 架构中的一个关键设计。当用户在浏览器中发起查询时,请求首先发送到 Grafana 后端服务器,由后端代理转发到对应的数据源。这种代理模式带来了两个重要优势:一是避免了浏览器跨域问题,因为所有数据源请求都通过 Grafana 后端统一出口;二是支持跨数据源联合查询,即在一个面板中同时查询多个数据源并将结果叠加展示。例如,可以在同一个面板中叠加 Prometheus 的 CPU 指标和 Elasticsearch 的日志错误率,实现指标与日志的关联分析。
Grafana 分为开源版(OSS)和企业版(Enterprise/Cloud)两个版本,在数据源权限管理方面存在显著差异。开源版支持基础的数据源配置和查询功能,所有具有编辑权限的用户都可以访问所有已配置的数据源。企业版则提供了细粒度的 RBAC(基于角色的访问控制)权限管理,管理员可以为不同角色配置不同的数据源访问权限,例如只允许开发团队访问测试环境的 Prometheus 数据源,而生产环境的数据源仅对运维团队开放。此外,企业版还支持 SSO 单点登录集成,包括 SAML、OAuth、LDAP 等认证方式,满足企业级安全合规要求。
在实际的 AI 工程化场景中,Grafana 的多数据源集成能力尤为重要。一个典型的 AI 推理服务监控场景可能需要同时接入以下数据源:Prometheus 用于存储 GPU 利用率、推理延迟等实时指标;Loki 用于存储推理请求的日志;Tempo 用于存储分布式追踪数据;Elasticsearch 用于存储模型质量评估的结构化数据。通过 Grafana 的统一面板,团队可以在一个仪表盘上同时观察推理服务的性能指标、日志异常和追踪信息,快速定位问题根因。
Dashboard面板设计与变量模板
Dashboard 是 Grafana 中组织和展示面板的核心容器。一个 Dashboard 由多个 Panel(面板)组成,每个 Panel 绑定一个查询和数据源,以可视化图表的形式呈现查询结果。Dashboard 的 JSON 模型定义了面板的布局、查询配置、变量定义、时间范围等所有信息,这使得 Dashboard 可以像代码一样进行版本控制和团队协作管理。
变量模板是 Grafana Dashboard 中实现动态筛选和复用的核心机制。通过 $variable 语法,用户可以在面板查询中引用变量值,实现面板内容的动态切换。变量的值来源于数据源查询结果,需要手动定义变量查询语句。例如,定义一个名为 instance 的变量,其查询语句为 label_values(up, instance),则该变量会自动从 Prometheus 中获取所有 instance 标签值。用户在 Dashboard 顶部下拉框中选择不同的 instance 值时,所有引用了 $instance 变量的面板都会自动刷新,展示对应实例的数据。
Grafana 提供了丰富的面板类型以适应不同的可视化需求。Graph 面板是最常用的时序图面板,支持折线图、面积图、柱状图等多种展示方式,适用于展示指标随时间变化的趋势。Heatmap 面板用于展示数据分布,例如将 GPU 利用率按时间段和利用率区间进行热力图展示,可以直观发现利用率异常的时间段。Table 面板以表格形式展示数据,支持列排序和条件着色。Stat 面板用于展示单个关键数值,例如当前在线模型数量。Gauge 面板以仪表盘形式展示数值,适用于展示 CPU 使用率等有明确上下限的指标。
行(Row)和分组机制实现了面板的逻辑层次组织。Row 可以将面板按功能或主题分组,用户可以折叠和展开每个 Row,避免在单个屏幕上展示过多面板导致信息过载。例如,一个 AI 推理服务监控 Dashboard 可以按 GPU监控、推理性能、模型质量、资源消耗等维度创建不同的 Row,每个 Row 下包含相关的面板。这种分层设计使得运维人员可以快速定位到需要关注的监控维度。
变量模板的高级用法包括链式变量和自定义变量。链式变量是指一个变量的可选值依赖于另一个变量的选择,例如先选择 cluster 变量,再根据所选集群筛选该集群下的 node 变量。自定义变量允许用户手动定义一组可选值,不依赖数据源查询。此外,Grafana 还支持 interval 和 range 等内置变量,用于根据 Dashboard 的时间范围自动调整查询的采样间隔和时间窗口,确保在不同时间粒度下都能获得合适的查询性能。
# 使用 Grafana HTTP API 创建 Dashboard 并定义变量模板import jsonimport requests GRAFANA_URL = "http://localhost:3000"API_KEY = "your-api-key" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"} # 定义变量template_variables = [ { "name": "instance", "type": "query", "datasource": "Prometheus", "query": "label_values(up, instance)", "refresh": 1, "multi": True, "includeAll": True }, { "name": "model_version", "type": "custom", "current": {"text": "v2.1", "value": "v2.1"}, "options": [ {"text": "v1.0", "value": "v1.0", "selected": False}, {"text": "v2.0", "value": "v2.0", "selected": False}, {"text": "v2.1", "value": "v2.1", "selected": True} ] }] # 定义面板dashboard_json = { "dashboard": { "title": "AI Inference Service Monitor", "templating": {"list": template_variables}, "panels": [ { "id": 1, "title": "GPU Utilization - $instance", "type": "timeseries", "datasource": "Prometheus", "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}, "targets": [ { "expr": "nvidia_gpu_utilization{instance=~\"$instance\"}", "legendFormat": "{{gpu}} - {{instance}}" } ] }, { "id": 2, "title": "Token Throughput", "type": "timeseries", "datasource": "Prometheus", "gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}, "targets": [ { "expr": "rate(inference_tokens_total{model_version=\"$model_version\"}[5m])", "legendFormat": "{{model_version}}" } ] } ] }, "overwrite": True} # 发送创建请求resp = requests.post( f"{GRAFANA_URL}/api/dashboards/db", headers=headers, json=dashboard_json)print(f"Status: {resp.status_code}")print(f"Response: {resp.json()}")
AI推理服务监控面板设计
AI 推理服务的监控需要关注多个维度,包括 GPU 资源利用率、推理吞吐量、延迟分布和模型版本对比等。Grafana 的多样化面板类型为这些监控需求提供了合适的可视化方案。设计合理的监控面板可以帮助团队快速发现性能瓶颈、资源浪费和异常状况,是 AI 服务稳定运行的重要保障。
GPU 利用率面板使用 Heatmap(热力图)展示多卡利用率分布。在多 GPU 服务器上,每张 GPU 卡的利用率可能差异很大,简单的折线图难以直观展示这种分布特征。Heatmap 将时间作为 X 轴、GPU 卡编号作为 Y 轴、利用率作为颜色深浅,可以在一个面板中同时展示所有 GPU 卡的利用率随时间的变化。当某个 GPU 卡利用率持续偏低(颜色偏浅)时,说明可能存在负载不均衡的问题;当利用率持续满载(颜色偏深)时,则需要考虑扩容或优化批处理策略。
Token 吞吐量面板使用 Graph(时序图)展示每秒 Token 生成数(Tokens Per Second, TPS)的趋势。TPS 是衡量 AI 推理服务性能的核心指标之一,直接影响用户体验和服务成本。面板中通常同时展示输入 Token 速率和输出 Token 速率,通过对比可以分析模型在不同输入长度下的处理效率。当 TPS 出现突降时,可能表示 GPU 资源不足、批处理队列积压或模型加载异常。
推理延迟面板使用 Percentile(分位数)图展示 P50、P95、P99 延迟分位数。分位数图比简单的平均延迟图更有价值,因为它能揭示延迟分布的尾部特征。P50 表示 50% 的请求延迟低于该值,反映典型请求的延迟水平;P99 表示 99% 的请求延迟低于该值,反映最慢请求的延迟水平。当 P99 远大于 P50 时,说明延迟分布存在严重的长尾效应,可能由个别大请求、GPU 显存碎片化或垃圾回收等因素引起。
模型版本对比面板通过变量切换不同版本指标对比。在模型迭代频繁的 AI 团队中,对比不同版本的性能指标是常见需求。通过在 Dashboard 中定义 model_version 变量,并在面板查询中引用该变量,用户可以快速切换查看不同模型版本的性能数据。更高级的做法是在同一个面板中叠加多个版本的指标曲线,通过颜色区分不同版本,直观对比版本间的性能差异。这种对比分析为模型上线决策提供了数据支撑。
Grafana告警规则与通知渠道
Grafana Unified Alerting 是 Grafana 8.0 引入的统一告警管理系统,它将原先分散在各个数据源中的告警规则统一到一个管理界面中。在 Unified Alerting 架构下,告警规则由 Grafana 服务器统一评估和调度,支持跨数据源的告警规则管理。这意味着用户可以在同一个告警规则中引用 Prometheus 的指标数据和 Loki 的日志数据,实现更全面的异常检测。
告警规则通过 PromQL 或 LogQL 等数据源原生查询语言定义触发条件。一个告警规则包含查询表达式、触发条件、持续时间和严重级别等配置。例如,定义一个 GPU 温度告警规则:查询表达式为 nvidia_gpu_temperature_celsius > 85,触发条件为最后 5 分钟内持续超过阈值,严重级别设为 critical。Grafana 会按照配置的评估间隔(默认每分钟)执行查询,当触发条件满足时生成告警实例。需要注意的是,告警规则由各自数据源的引擎执行查询,不同数据源支持的查询语法和功能可能不同。
通知渠道(Notification Channel / Contact Point)支持多种告警通知方式,包括 Slack、邮件、Webhook、PagerDuty、OpsGenie、Microsoft Teams 等。每个通知渠道可以配置不同的消息模板,支持 Go Template 语法进行消息格式化。在实际部署中,通常会根据告警严重级别路由到不同的通知渠道:critical 级别的告警发送到 PagerDuty 并触发电话通知,warning 级别的告警发送到 Slack 频道,info 级别的告警仅记录到邮件。
告警抑制(Silence)和分组(Grouping)是减少告警噪音的重要机制。告警抑制允许用户在已知问题处理期间临时屏蔽特定告警,避免重复通知。告警分组将同一根因触发的多个告警合并为一条通知,例如当整个 Kubernetes 节点不可用时,该节点上所有 Pod 的告警会被合并为一条通知发送,而不是为每个 Pod 单独发送告警。这种分组机制有效避免了告警风暴,让运维人员能够集中精力处理根因问题。
在 AI 推理服务场景中,合理的告警规则设计需要考虑以下要素:GPU 利用率超过 95% 持续 10 分钟触发扩容建议告警;推理延迟 P99 超过 SLA 阈值触发性能降级告警;模型加载失败触发紧急告警;Token 吞吐量突降超过 50% 触发异常检测告警。同时需要配置合理的告警评估间隔和持续时间,避免因瞬时波动产生误报。
# 使用 Grafana HTTP API 创建告警规则import jsonimport requests GRAFANA_URL = "http://localhost:3000"API_KEY = "your-api-key" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"} # 定义告警规则alert_rule = { "name": "GPU Temperature Critical", "ruleGroup": "ai_inference_alerts", "evalOffset": "0s", "condition": "C", "data": [ { "refId": "A", "relativeTimeRange": {"from": 300, "to": 0}, "datasourceUid": "prometheus-ds-uid", "model": { "expr": "nvidia_gpu_temperature_celsius", "intervalMs": 1000, "maxDataPoints": 43200, "refId": "A" } }, { "refId": "B", "relativeTimeRange": {"from": 0, "to": 0}, "datasourceUid": "__expr__", "model": { "conditions": [{"evaluator": {"params": [85], "type": "gt"}}], "datasource": {"type": "__expr__", "uid": "__expr__"}, "expression": "A", "reducer": "last", "refId": "B", "type": "threshold" } }, { "refId": "C", "relativeTimeRange": {"from": 0, "to": 0}, "datasourceUid": "__expr__", "model": { "conditions": [], "datasource": {"type": "__expr__", "uid": "__expr__"}, "expression": "B", "refId": "C", "reducer": "last", "type": "threshold" } } ], "noDataState": "OK", "execErrState": "Error", "for": "5m", "annotations": { "summary": "GPU {{ $labels.gpu }} temperature is {{ $values.A }} C", "description": "GPU temperature exceeded 85C threshold for 5 minutes" }, "labels": {"severity": "critical", "team": "ai-infra"}} # 发送创建请求resp = requests.post( f"{GRAFANA_URL}/api/v1/provisioning/alert-rules", headers=headers, json=alert_rule)print(f"Status: {resp.status_code}")print(f"Response: {json.dumps(resp.json(), indent=2)}")
Loki日志集成与指标日志关联
Loki 是 Grafana Labs 开发的日志聚合系统,专为云原生和微服务架构设计。与 Prometheus 专注于指标数据不同,Loki 专注于日志数据的收集、存储和查询。Loki 的设计哲学与 Prometheus 类似,但有一个关键区别:Loki 不对日志内容建立全文索引,而是仅对日志的标签(labels)建立索引。这种设计大幅降低了存储成本和索引开销,同时保持了高效的日志查询能力。Loki 与 Prometheus 形成互补关系:Prometheus 告诉你发生了什么(指标异常),Loki 告诉你为什么发生(日志详情)。
LogQL(Log Query Language)是 Loki 的查询语言,语法设计与 PromQL 保持高度一致,降低了学习成本。LogQL 支持两种基本查询模式:日志查询和指标查询。日志查询用于过滤和展示原始日志行,例如 {app="inference-service"} |= “error“ 表示查询 app 标签为 inference-service 且包含 error 关键字的日志。指标查询则在日志查询基础上添加聚合函数,例如 rate({app=”inference-service”} |= "error" [5m]) 表示计算过去 5 分钟内错误日志的速率。这种从日志中提取指标的能力使得日志数据也可以用于告警和可视化。
Grafana 面板支持从指标图表下钻到关联日志详情,这是指标日志关联的核心交互模式。当用户在 Prometheus 指标面板中发现某个时间点的异常峰值时,可以通过点击该数据点,Grafana 会自动生成对应的 LogQL 查询,在 Loki 面板中展示该时间段的关联日志。这种下钻功能依赖于指标标签和日志标签的一致性:Prometheus 指标中的 instance、job、pod 等标签需要与 Loki 日志中的对应标签保持一致,Grafana 才能正确建立关联。
日志标签设计是 Loki 使用中的关键环节,需要与 Prometheus 指标标签保持一致以便于关联。推荐的标签包括:app(应用名称)、namespace(Kubernetes 命名空间)、pod(Pod 名称)、container(容器名称)、level(日志级别)、model_version(模型版本)等。需要注意的是,Loki 的标签设计应遵循低基数原则,即标签的可能取值数量不宜过多。例如,不应将 request_id 作为标签,因为它的取值数量会随请求量无限增长,导致索引膨胀。request_id 等高基数信息应保留在日志内容中,通过 |= 操作符进行过滤。
在 AI 推理服务场景中,指标日志关联的典型应用包括:当推理延迟 P99 出现异常峰值时,通过关联日志查看该时间段内是否有模型加载、GPU 显存回收或批处理队列清空等操作日志;当 GPU 利用率突降时,通过关联日志排查是否有 OOM 错误、CUDA 异常或驱动崩溃等错误日志。这种从宏观指标到微观日志的逐层排查方式,类似于破案时的证据链分析,通过指标发现异常线索,再通过日志追溯具体原因,形成完整的诊断路径。
# 使用 Grafana API 创建 Loki 数据源并配置指标日志关联import jsonimport requests GRAFANA_URL = "http://localhost:3000"API_KEY = "your-api-key" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"} # 1. 创建 Loki 数据源loki_datasource = { "name": "Loki", "type": "loki", "access": "proxy", "url": "http://loki:3100", "jsonData": { "maxLines": 1000, "derivedFields": [ { "name": "TraceID", "matcherRegex": "trace_id=(\\w+)", "datasourceUid": "tempo-ds-uid", "url": "" } ] }} resp = requests.post( f"{GRAFANA_URL}/api/datasources", headers=headers, json=loki_datasource)print(f"Loki datasource: {resp.status_code}") # 2. 配置 Prometheus 数据源的指标日志关联# 在 Prometheus 数据源的 jsonData 中配置 derivedFieldsprom_update = { "id": 1, "jsonData": { "httpMethod": "POST", "manageAlerts": True, "prometheusType": "Prometheus", "exemplarTraceIdDestinations": [ { "name": "traceID", "datasourceUid": "tempo-ds-uid" } ] }} resp = requests.put( f"{GRAFANA_URL}/api/datasources/1", headers=headers, json=prom_update)print(f"Prometheus update: {resp.status_code}") # 3. 定义 LogQL 查询示例logql_examples = { "error_rate": 'rate({app="inference-service"} |= "error" [5m])', "latency_log": '{app="inference-service"} | json | latency > 5000', "model_load_log": '{app="inference-service"} |= "model" |= "loaded"', "gpu_oom": '{app="inference-service"} |= "CUDA out of memory"'} print("\nLogQL Query Examples:")for name, query in logql_examples.items(): print(f" {name}: {query}")
Dashboard版本管理与团队协作
Dashboard 通过 JSON 模型定义其完整配置,包括面板布局、查询语句、变量定义、样式设置等所有信息。这个 JSON 模型可以像源代码一样进行版本控制,存储在 Git 仓库中,实现 Dashboard 的变更追踪、代码审查和回滚能力。每次对 Dashboard 的修改都会生成一个新的版本号,Grafana 内置了版本历史功能,可以查看任意两个版本之间的差异并回滚到历史版本。
Grafana Provisioning 是一种通过配置文件自动加载和同步 Dashboard 的机制,适用于 GitOps 工作流。通过配置 provisioning 目录下的 dashboard 配置文件,Grafana 会在启动时和定期扫描指定目录中的 JSON 文件,自动创建或更新 Dashboard。这种方式下,Dashboard 的修改需要通过更新 JSON 文件并重新部署来实现,而不是在 Grafana UI 中直接编辑。Provisioning 模式确保了 Dashboard 的可重复性和一致性,避免了手动修改导致的配置漂移。
文件夹和权限控制实现了团队间 Dashboard 的隔离管理。Grafana 中的 Dashboard 按文件夹组织,每个文件夹可以配置独立的权限规则。在大型组织中,不同团队(如 AI 推理团队、数据团队、平台团队)可以拥有各自的文件夹,团队成员只能查看和编辑自己团队的 Dashboard。企业版还支持更细粒度的权限控制,包括文件夹级别的查看、编辑、管理权限分配。
Dashboard 导出导入功能支持跨环境迁移和模板复用。Dashboard 可以导出为 JSON 文件,导入到另一个 Grafana 实例中。在导出时可以选择是否包含数据源配置,通常在跨环境迁移时需要重新配置数据源以匹配目标环境的配置。Dashboard 模板化是另一个重要实践,通过变量模板将 Dashboard 参数化,使得同一个 Dashboard 模板可以服务于不同的服务实例或环境,只需修改变量值即可适配不同的监控场景。
在 AI 工程化团队的实践中,推荐的 Dashboard 管理流程如下:开发人员在本地 Grafana 中创建和调试 Dashboard,完成后导出 JSON 文件提交到 Git 仓库;通过 CI/CD 流水线自动将 JSON 文件部署到测试环境的 Grafana Provisioning 目录;测试验证通过后,通过 CD 流水线部署到生产环境。这种流程确保了 Dashboard 变更的可追溯性和环境一致性,同时支持多人协作开发 Dashboard。
# Dashboard 版本管理与 Provisioning 配置示例import jsonimport os # 1. 生成 Provisioning 配置文件provisioning_config = { "apiVersion": 1, "providers": [ { "name": "AI Dashboards", "orgId": 1, "folder": "AI Monitoring", "folderUid": "ai-monitoring", "type": "file", "disableDeletion": True, "updateIntervalSeconds": 30, "allowUiUpdates": False, "options": { "path": "/var/lib/grafana/dashboards/ai", "foldersFromFilesStructure": True } } ]} # 保存 provisioning 配置print("=== Provisioning Configuration ===")print(json.dumps(provisioning_config, indent=2)) # 2. Dashboard JSON 模板(参数化)dashboard_template = { "uid": "ai-inference-overview", "title": "AI Inference Service - $environment", "tags": ["ai", "inference", "monitoring"], "timezone": "browser", "refresh": "30s", "time": {"from": "now-6h", "to": "now"}, "templating": { "list": [ { "name": "environment", "type": "custom", "current": {"text": "production", "value": "production"}, "options": [ {"text": "staging", "value": "staging", "selected": False}, {"text": "production", "value": "production", "selected": True} ] } ] }, "panels": [ { "id": 1, "title": "Request Rate", "type": "timeseries", "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}, "targets": [ { "expr": "sum(rate(http_requests_total{environment=\"$environment\"}[5m]))", "legendFormat": "requests/sec" } ] } ], "schemaVersion": 38, "version": 1} # 3. 模拟版本管理流程def save_dashboard_version(dashboard, version, output_dir="/tmp/dashboards"): """保存 Dashboard 版本到文件""" os.makedirs(output_dir, exist_ok=True) filename = f"{dashboard['uid']}_v{version}.json" filepath = os.path.join(output_dir, filename) with open(filepath, "w") as f: json.dump(dashboard, f, indent=2) print(f"Saved: {filepath}") return filepath # 保存初始版本path = save_dashboard_version(dashboard_template, version=1)print(f"\nDashboard saved to: {path}")print(f"UID: {dashboard_template['uid']}")print(f"Version: {dashboard_template['version']}")
AI服务可视化监控最佳实践
监控面板的分层设计是构建高效可观测性体系的核心原则。推荐采用三层结构:概览面板、详情面板和下钻面板。概览面板提供系统全局视图,通常包含关键 SLI(服务级别指标)的健康状态,使用 Stat 面板以红绿颜色直观展示各组件是否正常。详情面板提供单一维度的深入分析,例如某个服务的延迟分布或资源使用趋势。下钻面板提供问题诊断级别的信息,例如单个请求的追踪详情或特定时间段的日志分析。用户从概览面板出发,根据异常线索逐层深入到详情和下钻面板,形成系统化的排查路径。
色彩规范是监控面板视觉语言的重要组成部分。统一的色彩规范帮助团队成员快速理解面板含义:绿色表示正常状态,黄色表示警告状态(接近阈值但未超限),红色表示异常状态(已触发告警)。在 Stat 面板和 Table 面板中,可以配置 Threshold(阈值)规则实现自动着色。例如,GPU 利用率低于 80% 显示绿色,80% 到 95% 显示黄色,超过 95% 显示红色。除了红黄绿三色外,还应避免在面板中使用过多颜色,防止视觉疲劳和信息混淆。
面板密度的控制直接影响监控效率。概览面板建议每屏展示 8 到 12 个 Panel,这个数量范围既能提供足够的信息覆盖,又不会因为面板过多导致每个面板尺寸过小、信息难以辨认。在 1920x1080 分辨率的显示器上,通常采用 4 列或 6 列的面板布局,每个面板高度为 6 到 8 个网格单位。对于需要在大屏上展示的监控场景,可以进一步减少面板数量,增大单个面板尺寸,确保远距离也能清晰辨认面板状态。
定期评审是保持 Dashboard 有效性的关键实践。建议每月评审 Dashboard 的使用频率,通过 Grafana 的 Dashboard Analytics 功能查看每个 Dashboard 的访问次数和活跃用户数。对于连续 30 天无人查看的 Dashboard,应考虑归档或删除,避免维护成本浪费。同时,根据业务变化和团队反馈持续优化面板设计,例如添加新的关键指标面板、调整阈值配置、优化查询性能等。Dashboard 的质量直接影响团队的运维效率,需要像对待代码一样持续迭代和维护。
在 AI 服务的特定场景中,还需要关注以下最佳实践:首先,为模型推理服务配置独立的监控命名空间,将 GPU 监控、推理性能、模型质量等面板按 Row 分组;其次,使用 Annotations(注释)功能在时序图上标记模型发布、配置变更等事件,便于分析变更对性能的影响;最后,建立 Dashboard 模板库,将通用的监控面板(如 Kubernetes Pod 监控、GPU 监控、HTTP 请求监控)抽象为可复用的模板,新服务上线时只需修改变量即可快速生成监控面板。
AI 应用场景
AI推理服务多维监控仪表盘
解决的问题:AI推理服务团队构建Grafana仪表盘,包含GPU利用率热力图、Token吞吐量时序图和推理延迟P99分位数面板。通过多数据源集成,将Prometheus指标、Loki日志和Tempo追踪数据统一展示在一个Dashboard中,实现推理服务的全链路可观测性。团队使用变量模板在不同模型版本和GPU实例之间切换,快速定位性能瓶颈。
具体案例:AI推理服务团队构建Grafana仪表盘,包含GPU利用率热力图、Token吞吐量时序图和推理延迟P99分位数面板。通过多数据源集成,将Prometheus指标、Loki日志和Tempo追踪数据统一展示在一个Dashboard中,实现推理服务的全链路可观测性。团队使用变量模板在不同模型版本和GPU实例之间切换,快速定位性能瓶颈。
大模型质量趋势可视化追踪
解决的问题:大模型团队使用Grafana展示模型质量评估面板,将模型评估指标(如准确率、BLEU分数、困惑度等)随版本迭代的趋势可视化。通过变量模板切换不同评估数据集和模型架构,对比分析各版本的质量变化。结合告警规则,当模型质量指标低于基线阈值时自动通知模型团队。
具体案例:大模型团队使用Grafana展示模型质量评估面板,将模型评估指标(如准确率、BLEU分数、困惑度等)随版本迭代的趋势可视化。通过变量模板切换不同评估数据集和模型架构,对比分析各版本的质量变化。结合告警规则,当模型质量指标低于基线阈值时自动通知模型团队。
Python 演示
# Grafana Dashboard 面板配置生成器# 使用 Python 动态生成 AI 推理服务监控 Dashboard JSONimport json def create_panel(panel_id, title, panel_type, expr, grid_pos, legend=None, unit=None): """创建一个 Grafana 面板配置""" panel = { "id": panel_id, "title": title, "type": panel_type, "datasource": {"type": "prometheus", "uid": "prometheus"}, "gridPos": grid_pos, "targets": [{"expr": expr, "refId": "A"}] } if legend: panel["targets"][0]["legendFormat"] = legend if unit: panel["fieldConfig"] = { "defaults": {"unit": unit} } return panel # 定义面板列表panels = []row_y = 0 # Row 1: GPU 监控panels.append({"id": 100, "title": "GPU Monitoring", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": row_y}, "collapsed": False})row_y += 1panels.append(create_panel(1, "GPU Utilization", "timeseries", "avg(nvidia_gpu_utilization) by (gpu)", {"h": 8, "w": 12, "x": 0, "y": row_y}, legend="GPU {{gpu}}", unit="percent"))panels.append(create_panel(2, "GPU Memory", "timeseries", "nvidia_gpu_memory_used_bytes / nvidia_gpu_memory_total_bytes * 100", {"h": 8, "w": 12, "x": 12, "y": row_y}, legend="GPU {{gpu}}", unit="percent"))row_y += 8 # Row 2: 推理性能panels.append({"id": 101, "title": "Inference Performance", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": row_y}, "collapsed": False})row_y += 1panels.append(create_panel(3, "Token Throughput", "timeseries", "rate(inference_tokens_total[5m])", {"h": 8, "w": 8, "x": 0, "y": row_y}, legend="{{model_version}}", unit="short"))panels.append(create_panel(4, "P99 Latency", "timeseries", "histogram_quantile(0.99, rate(inference_latency_bucket[5m]))", {"h": 8, "w": 8, "x": 8, "y": row_y}, legend="P99", unit="ms"))panels.append(create_panel(5, "Error Rate", "stat", "sum(rate(inference_errors_total[5m])) / sum(rate(inference_requests_total[5m])) * 100", {"h": 8, "w": 8, "x": 16, "y": row_y}, unit="percent")) # 组装 Dashboard JSONdashboard = { "title": "AI Inference Service Monitor", "uid": "ai-inference-monitor", "tags": ["ai", "inference", "gpu"], "timezone": "browser", "refresh": "30s", "time": {"from": "now-6h", "to": "now"}, "panels": panels, "schemaVersion": 38, "version": 1} # 输出 JSONresult = json.dumps(dashboard, indent=2, ensure_ascii=False)print(f"Dashboard: {dashboard['title']}")print(f"Total panels: {len([p for p in panels if p['type'] != 'row'])}")print(f"Total rows: {len([p for p in panels if p['type'] == 'row'])}")print(f"JSON size: {len(result)} bytes")
定义 create_panel 函数,封装面板配置创建逻辑,接受面板ID、标题、类型、查询表达式、布局位置和可选的图例格式和单位参数panel 字典包含 Grafana 面板的核心配置:id 唯一标识、title 显示标题、type 面板类型、datasource 数据源引用、gridPos 网格布局和 targets 查询目标gridPos 使用 Grafana 网格系统,h 和 w 分别表示面板高度和宽度(单位为网格单位),x 和 y 表示面板左上角的坐标位置legendFormat 使用 {{label}} 语法引用 Prometheus 标签值,在图例中动态展示不同实例或维度的数据fieldConfig.defaults.unit 设置面板数值的显示单位,如 percent 表示百分比、ms 表示毫秒,Grafana 会自动进行单位换算和格式化使用 Row 类型面板实现面板的逻辑分组,Row 面板不展示数据,仅作为分组标题和折叠控制GPU 监控行包含 GPU 利用率和 GPU 显存使用率两个面板,分别展示计算资源和存储资源的使用情况推理性能行包含 Token 吞吐量、P99 延迟和错误率三个面板,覆盖推理服务的核心 SLI 指标histogram_quantile 函数用于从 Prometheus 直方图数据中计算分位数,0.99 参数表示计算 P99 分位数rate 函数计算时间序列在指定时间窗口内的每秒平均增长率,是 Prometheus 查询中最常用的函数之一dashboard 字典组装完整的 Dashboard 配置,包含标题、UID、标签、时区、自动刷新间隔、时间范围和面板列表schemaVersion 指定 Dashboard JSON 模型的版本号,不同 Grafana 版本使用不同的 schemaVersion最终输出的 JSON 可以直接通过 Grafana API 导入,或放入 Provisioning 目录自动加载
常见问答
Grafana 本身是否存储指标数据?它的数据获取机制是什么?
Grafana 的变量模板值是如何获取的?是否自动提取所有可用值?
Grafana Unified Alerting 中,告警规则的查询是在哪里执行的?
Loki 为什么不对日志内容建立全文索引?这种设计的优缺点是什么?
在 AI 推理服务监控中,为什么使用 P99 分位数而不是平均延迟?
常见误区
误区Grafana会自动存储所有查询的指标数据
正解Grafana 本身不存储指标数据,它是纯可视化前端。所有数据存储在外部数据源(如 Prometheus、InfluxDB 等)中,Grafana 仅负责查询和展示。如果数据源不可用,Grafana 无法展示任何数据。
误区Grafana变量模板会自动从查询结果中提取所有可用值
正解变量值来自数据源查询,需要手动定义变量查询语句。例如需要定义 label_values(up, instance) 这样的查询来获取 instance 变量的可选值。Grafana 不会自动推断或提取变量值。
误区Grafana告警规则可以直接在所有数据源上执行相同的查询逻辑
正解告警规则由各自数据源的引擎执行,不同数据源使用不同的查询语言。Prometheus 数据源使用 PromQL,Loki 数据源使用 LogQL,Elasticsearch 数据源使用其原生查询 DSL。不能在告警规则中跨数据源使用统一的查询逻辑。
参考来源
- official_docsGrafana Official DocumentationGrafana 官方文档,包含数据源配置、Dashboard 设计、告警规则、Provisioning 等全面的使用指南。
- official_docsLoki Official DocumentationLoki 官方文档,包含 LogQL 查询语言、标签设计、日志聚合架构等核心概念和使用指南。
- official_docsPrometheus Querying BasicsPrometheus 查询语言基础文档,包含 PromQL 语法、函数使用和最佳实践。
- official_docsGrafana Unified AlertingGrafana Unified Alerting 官方文档,包含告警规则配置、通知渠道、告警路由和抑制等详细内容。
- official_docsBuild Dashboards in GrafanaGrafana Dashboard 构建指南,包含面板配置、变量模板、布局设计和最佳实践。