大多数仪表盘不是「信息太少」,而是「信息太多且没有层级」:60 个面板铺满屏幕,颜色五花八门,双 Y 轴随意叠加,y 轴从 99 开始截断——结果是有数据但读不出结论,值班的人反而要一个个点开去猜。
仪表盘设计是一门可读性工程,它要回答的不是「数据能画出来吗」,而是「在 30 秒内,值班的人能否判断系统是否正常、异常在哪个维度、下一步该看什么」。本文按设计流程展开:先定信息层级与布局,再谈图表选型与坐标轴约定,然后是下钻路径与颜色语义,最后是查询成本与大屏生命周期维护。Grafana 的具体面板配置可参考 Grafana 可视化实践 。
1. 先定目标,再选图表
1.1 仪表盘的三种类型
类型一:总览盘(Overview / SLO 盘)
受众:值班、管理层
目标:30 秒判断"是否正常"
设计:少量大面板,突出 SLO 达成、错误预算、关键业务指标
数量:1 屏,不超过 12 个面板
类型二:诊断盘(Troubleshooting)
受众:排障工程师
目标:定位"问题在哪一层、哪个维度"
设计:分层展开,资源 → 服务 → 实例 → 依赖
数量:可多屏,用行(Row)折叠组织
类型三:分析盘(Exploratory)
受众:性能/容量工程师
目标:验证假设、看长期趋势
设计:多维度对比、可自由选变量
数量:不设限,但不作为值班入口
最常见的错误是把三种混在一个盘里:既想当值班入口,又想当排障工具,结果两边都不好用。正确做法是「总览盘提供跳转链接 → 诊断盘承接」。
1.2 指标先于图表
先想清楚要回答的问题,再选图:
问题 → 需要的表达 → 图表类型
"现在正常吗?" → 状态 / 阈值对比 → Stat / Gauge / 状态图
"趋势在恶化吗?" → 随时间变化 → 时间序列折线
"分布在哪个区间?" → 分布 → 直方图 / 热力图
"哪个维度最差?" → 排序对比 → 条形图 / 表格(Top-N)
"异常何时开始?" → 时间点定位 → 时间序列 + 注释(annotation)
"错误率有多少种?" → 分类占比 → 饼图(慎用)或表格
如果一个问题无法用上述任一表达回答,说明问题本身太模糊,先拆解它。图表选型的一般原则(编码效率、感知准确性)在 图表选型原理 中有系统论述。
2. 信息层级与布局
2.1 三层结构
第一层(屏幕顶部,占 1/4 高度):结论层
SLO 达成率、错误预算剩余、当前是否告警、关键业务指标
形式:大字号 Stat 面板 + 阈值配色
要求:不需要读图,看颜色和数字就能判断
第二层(屏幕中部,占 1/2 高度):趋势层
关键指标的时序折线(延迟、流量、错误、饱和度)
形式:时间序列,统一时间范围与对齐
要求:趋势一眼可见,异常点用注释标记
第三层(屏幕下部,占 1/4 高度):分解层
按维度分解:Top-N 慢接口、错误分类、实例列表
形式:表格 / 条形图 / 热力图
要求:从"哪里不对"到"哪个具体对象不对"
2.2 布局原则
原则一:重要信息放左上(阅读起点,符合 F 型视线)
原则二:同层信息大小一致,不同层用尺寸区分重要性
原则三:相关面板相邻(延迟与流量相邻,错误与重试相邻)
原则四:用行(Row)折叠次要内容,默认收起
原则五:面板数控制在 1 屏内可读(约 12~16 个)
原则六:留白——拥挤是误读的主要来源之一
反例:20 个同尺寸小面板平铺
问题:没有层级,视觉上等价,无法快速定位重点
改法:3 个大面板(结论层)+ 6 个中面板(趋势)+ 一行折叠表格(分解)
2.3 命名与单位标注
面板标题必须自解释:
❌ "Latency"
✅ "P99 延迟(按服务,含 SLO 阈值 200ms)"
单位必须显式标注:
❌ 数值 0.234
✅ 234 ms(用 Grafana 的 unit 配置,而非在标题里写)
单位在面板配置里设,避免每个查询手动换算
阈值必须可见:
SLO 阈值用 threshold 线或颜色区带标在图上
让"是否达标"变成视觉判断而非心算
3. 图表选型细则
3.1 时间序列的三种用法
| 用法 | 配置 | 适用 |
|---|---|---|
| 折线 | 默认,线性 y 轴 | 大多数趋势 |
| 堆叠面积 | stacking: normal | 总量分解(错误按类型) |
| 对数轴 | logBase: 10 | 跨越多个数量级的指标 |
折线图的使用要点:
系列数控制在 5~8 条以内,超过则用"按维度聚合 + Top-N"
多条线时统一单位,绝不混用不同量纲
时间范围统一(所有面板用同一个时间选择器)
关闭默认的"自动缩放"抖动:设 min=0(对延迟、错误率等非负指标)
什么时候用堆叠面积:
只在"各分量之和等于总量"且"关心构成比例"时使用
错误率按类型堆叠、流量按来源堆叠 ✅
不同服务的延迟堆叠 ❌(延迟不可相加)
3.2 热力图与直方图
热力图(Heatmap):
用途:分布随时间的变化,如延迟分布、GC 停顿分布
数据源:Prometheus 直方图桶 或 Loki 的日志分位数
配置要点:y 轴用桶边界(le),颜色映射用对数刻度(否则长尾淹没细节)
典型场景:P50 稳定但 P99 抖动 → 热力图能看出是哪个桶在变
直方图(Histogram):
用途:某个时刻的分布快照
与热力图区别:热力图是"分布 × 时间",直方图是"分布 × 单一时刻"
3.3 状态与表格
状态图(Stat / State timeline):
用途:实例健康、发布状态、多集群状态一览
配置:阈值配色(绿/黄/红),值映射(0=down, 1=up)
注意:颜色语义必须全站统一(绿=好、红=坏),不能反用
表格:
用途:Top-N 排序、多维度对比
配置要点:
- 默认按最关心的列降序(如按错误率)
- 数值列右对齐,单位统一
- 加阈值着色(超过 SLO 的行标红)
- 行数限制(Top 10),避免表格过长需要滚动
4. 避免误读:坐标轴、单位与颜色
4.1 双 Y 轴
结论:绝大多数情况下不要用双 Y 轴
原因:
两个不同量纲的序列叠加后,视觉上的"交叉点""同步上升"
完全取决于两个轴的缩放比例,是人为制造的伪相关
读者会本能地寻找因果关系,从而得出错误结论
替代方案:
方案一:拆成上下两个面板,共享 x 轴(推荐)
方案二:归一化到同一量纲(如都转成相对基线的百分比)
方案三:用相关性图(散点)显式表达两个指标的关系
唯一可接受的双轴场景:
两个序列有确定的换算关系(如字节数与字节/秒),
且换算关系在标题中明确标注
4.2 截断 Y 轴
问题:y 轴不从 0 开始时,小幅波动被放大成"剧烈震荡"
例:错误率从 0.1% 到 0.15%,y 轴设 [0.09, 0.16] 时看起来像雪崩
原则:
折线图对非负指标默认从 0 开始
确实需要看细节时,同时给出"全量视图"与"放大视图"两个面板
并在标题中标注 y 轴范围,避免读者误判幅度
例外:
温度、CPU 频率等有自然基线(非 0)的指标,可不从 0 开始
但需在标题中说明基线
4.3 颜色语义
三条规则:
规则一:颜色必须有语义且全站一致
绿=正常、黄=警告、红=严重,不得反用或混用
规则二:分类颜色不超过 7 种
超过则人眼无法区分;用 Top-N + "其他"聚合
规则三:色盲友好
避免红绿对立作为唯一区分手段(约 8% 男性红绿色盲)
用形状、线型、标签辅助区分
配色参考无障碍配色方案
反例:
用 20 种颜色区分 20 个服务 → 无人能读懂图例
改法:Top 5 + Other,或改为表格排序
可视化中的色彩、对比度与无障碍设计原则可参考 仪表盘设计 。
5. 变量与下钻
5.1 模板变量
模板变量把「一个大盘」变成「一套可复用的盘」:
常用变量:
$service 服务名(来自 label_values(up, service))
$instance 实例(依赖 $service 联动)
$env 环境(prod/staging)
$interval 采样间隔(1m/5m/1h,用于 rate 窗口)
配置要点:
变量之间设置依赖(instance 的取值依赖 service),避免无效组合
默认值选择"最有代表性的"(如 prod、所有服务聚合)
interval 变量要与 PromQL 的 rate 窗口绑定:
rate(http_requests_total[$interval])
避免在变量里放高基数维度(如 pod 名在千级规模下会拖慢大盘)
5.2 下钻路径
下钻的三级路径:
第一级:总览盘 —— 服务级 SLO 达成情况
↓ 点击服务名(Data link)
第二级:服务诊断盘 —— 该服务的 RED 指标 + 依赖
↓ 点击实例 / 点击异常时间段(带时间范围的链接)
第三级:实例/链路 —— 具体实例的资源指标 或 具体 trace
实现方式(Grafana):
Data links:面板值 → 带变量的 URL
/d/service-detail?var-service=${__field.labels.service}&from=${__from}&to=${__to}
关键:链接必须传递【时间范围】与【变量值】
否则下钻后要重新选时间和筛选,体验断裂
下钻设计要点:
时间范围必须传递(from/to),这是最容易漏的一环
下钻目标盘必须能自动适配传入变量(设好默认值兜底)
每一级都要有"返回上级"的路径
链路追踪的跳转用 trace_id,见 Exemplar 关联
5.3 从异常到根因的路径
理想路径(3 次点击内到根因):
1. 总览盘看到"支付服务 SLO 未达标"(红色)
2. 点击进入支付服务盘,看到"P99 延迟上升,错误集中在调用风控的接口"
3. 点击接口 → 打开该时间段的链路 → 看到风控调用超时
4. 从 span 跳到风控服务的日志 → 看到连接池耗尽
每一跳都要携带上下文(服务、时间、维度),
否则"下钻"变成"重新开始查",价值大打折扣
6. 告警与状态的可视化
6.1 状态要前置
原则:告警状态必须在总览盘最显眼处,而不是让人去告警列表里翻
做法:
顶部一行 Stat 面板显示"当前活跃告警数 / 最高严重级别"
用颜色区带标注 SLO 阈值,让"是否越线"成为视觉判断
在时间序列上用 annotation 标注发布、故障、配置变更事件
注释(Annotation)的价值:
把"指标突变"与"人为事件"对齐,是根因定位最快的手段
数据源:发布系统的 webhook、告警系统的历史、变更工单
6.2 阈值可视化
# Grafana 面板阈值配置(示意,JSON 片段)
fieldConfig:
defaults:
unit: ms
thresholds:
mode: absolute
steps:
- color: green
value: null
- color: yellow
value: 150 # 接近 SLO
- color: red
value: 200 # 超过 SLO 阈值
阈值设计要点:
阈值必须与 SLO 定义一致,不能各写一套
颜色区带要标在图上(而非只在 Stat 面板),趋势图也能看出越线时刻
多级阈值(警告/严重)用不同颜色,避免"要么全绿要么全红"
7. 查询成本与大屏维护
7.1 面板查询的成本
成本来源:
面板数 × 每面板查询数 × 刷新频率 × 查询扫描量
优化手段:
用 recording rule 预聚合高频大盘的查询
提高刷新间隔(值班盘 1m 足够,不要 5s)
限制时间范围(默认 6h 而非 30d)
避免在面板里用高基数聚合(如 group by pod)
用 $interval 变量让 rate 窗口随范围自适应,避免短窗口长范围导致数据点爆炸
量化示例:
20 个面板 × 2 条查询 × 每 5s 刷新 = 每秒 8 次查询
改为 1m 刷新后降到每秒 0.67 次,负载降 92%,可读性不变
7.2 大屏的生命周期
仪表盘会腐烂,必须定期治理:
指标改名/下线后,面板查询悄悄变成空图(不报错,只是没数据)
阈值随 SLO 调整而失效
服务下线后大盘仍挂着,成为"僵尸盘"
治理机制:
每月审查:活跃度(被访问次数)、空面板比例、查询耗时
空面板(连续 7 天无数据)自动标记待清理
大盘纳入 Git 管理(Grafana as Code / provisioning),变更走评审
大盘作为代码的实践可参考"可观测性即代码"
8. 评审清单
□ 每个盘有明确类型(总览/诊断/分析),不混用
□ 信息分三层:结论 / 趋势 / 分解,尺寸体现层级
□ 面板数 ≤ 16 且 1 屏内可读,次要内容折叠
□ 面板标题自解释,单位在配置里设而非标题里写
□ 时间序列系列数 ≤ 8,超出用 Top-N
□ 非负指标 y 轴从 0 开始,需放大时另开面板并标注范围
□ 不使用双 Y 轴(除非有明确换算关系且已标注)
□ 颜色语义全站统一,分类色 ≤ 7 种,色盲友好
□ SLO 阈值以颜色区带标在图上
□ 模板变量设依赖关系,interval 与 rate 窗口绑定
□ 下钻链接传递时间范围与变量值
□ 发布/变更事件以 annotation 标注在时间轴上
□ 刷新间隔与查询量匹配,高频查询用 recording rule
□ 大盘纳入 Git 管理,定期清理空面板与僵尸盘
关于该看哪些指标、每类服务该采什么,可参考 黄金信号与 RED/USE 方法论 ——仪表盘的可读性上限,取决于底层指标设计是否合理;指标设计混乱,再好的可视化也救不回来。
小结
仪表盘设计的核心,是把"数据"翻译成"判断"。落地时抓住四件事:信息层级——按「结论 / 趋势 / 分解」三层布局,重要信息放左上,面板数控制在一屏可读;图表选型——先明确要回答的问题,再选表达方式,时间序列、热力图、状态图、表格各有其位,不要用饼图表达一切;避免误读——不用双 Y 轴、非负指标 y 轴从 0 起、颜色语义全站统一且色盲友好,这三点能消除绝大多数误判;下钻路径——用模板变量与 Data links 把总览盘、诊断盘、链路串成 3 次点击可达根因的路径,且每一跳都必须携带时间范围与变量。最后,仪表盘会腐烂,把它纳入 Git 管理与定期评审,才能让它在半年后依然可信。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。