50.6 看板设计

一句话

看板不是图表的集合,而是一次决策的视觉化——先定「谁、在什么场景下看、看完要做什么决定」,再决定放哪六个图;判断看板好坏的标准不是「信息全」,而是看完的人能不能在 30 秒内做出正确的下一步动作。

先定场景,再定图

场景 谁看 停留时间 必须回答 图上限
值班首屏 on-call 30 秒 是不是我们的问题?影响多大?从几点开始? 6
服务详情 该服务 owner 2 分钟 哪一跳慢/错?哪个实例?和发布有关吗? 8–12
资源详情(USE) SRE 1 分钟 哪个资源饱和?多久会耗尽? 6
依赖详情 上下游团队 1 分钟 是依赖的问题还是我们的问题? 6
业务看板 产品 / 业务 1 分钟 用户还能不能下单/支付?掉了多少? 4–6
复盘看板 全员 5 分钟 长期趋势、容量、SLO 达成情况 10–15

第一件要放弃的幻想:一张大屏给所有人看。给老板看的(业务)、给 on-call 看的(症状)、给 owner 看的(内部步骤)是三种不同的问题,塞在一屏里必然谁都不满意。

首屏六格:把决策顺序画成布局

┌──────────────────┬──────────────────┬──────────────────┐
│ ① SLO / 预算剩余  │ ② 错误率 vs 阈值  │ ③ 最近变更        │
│ 99.93%  剩 62%   │ 0.07%  ▁▂▁█▁     │ 14:02 deploy v3.2│
├──────────────────┼──────────────────┼──────────────────┤
│ ④ 请求速率 RPS    │ ⑤ 延迟 P50/95/99 │ ⑥ 饱和度          │
│ 1.2k/s  ↑12%     │ 8 / 45 / 210ms   │ DB 连接池 82%    │
└──────────────────┴──────────────────┴──────────────────┘

布局不是审美,是决策顺序:

  • 左上 = 结论:SLO 与预算剩余,一眼看出「今天还能不能烧」。
  • 中上 = 与目标的差:错误率曲线 + 阈值线,判断「要不要动手」。
  • 右上 = 最近的变量:发布、配置变更、扩缩容。排障的第一猜想永远是「刚才改了什么」——业界经验是多数线上故障由变更引入(不同组织差异很大,但把它放在首屏几乎零成本)。
  • 下一行 = 四黄金指标:速率、延迟、饱和度,配合错误率构成完整的 RED + 饱和。

🔑 首屏的门槛:一个刚接手的人,只看这一屏,能判断「要不要升级、要不要回滚、要不要扩」。做不到就说明缺的不是图,是结论。

每个面板的规范

要素 要求 反例
标题 写结论或问句,不写指标名 rate(http_requests_total[5m])
单位 显式:ms、req/s、%、GB 裸数字,读者自己猜
时间范围 与决策匹配:首屏 1 h/6 h,复盘 30 d 全部用 30 d(尖刺被压平)
对比 上周同期、上一个发布点 只看当前值,判断不了「这是不是异常」
阈值线 把 SLO 线、容量线画在图上 让读者脑补红线在哪
颜色 只有越界才用红;正常不用绿 一片绿 = 没有绿;全彩 = 没有重点
图例 ≤ 5 条序列,命名带维度值 20 条线叠在一起,谁也看不清
下钻 每个面板都能点进 trace / 日志 / 实例 只能看,不能跳

图类型跟着问题走

问题 图 例子
随时间怎么变 折线(≤ 5 条) RPS、P99、错误率
分布怎么迁移 热图(histogram heatmap) 延迟分布随时间整体右移
现在是否越界 单值 + 阈值条 错误预算剩余 62%
由什么构成 堆叠面积(≤ 5 类) 5xx 按错误码构成
谁最差 表格 / 条形 TOP-N 最慢的 10 个路由
两个量是否相关 散点 延迟 vs 连接池占用

反例:用饼图看趋势、用双 Y 轴强行对齐两个量纲、3D 效果、超过 5 条线的折线。这些不是「不好看」,是「会读出错误结论」。

关联与下钻:看板的价值在跳转

你看到 下一步点哪 带什么参数
错误率尖刺 exemplar → 一条慢/错 trace trace_id
trace 里某个 DB span 慢 该 span 时间窗内的日志 trace_id + 时间范围
某个实例指标异常 主机/容器看板 host.name / pod
依赖错误率上升 依赖方的服务看板 service.name
延迟整体上移 「最近变更」面板 发布时间窗

🔑 一个看板如果只能「看」不能「跳」,它就是一张截图。排障真正的时间花在三个系统之间搬参数——把 trace_id、service.name、host.name 做成可点的链接,比多加十个图有用。

全栈监控三层:每层看什么

层 内容 主要数据 关键面板
基础层 CPU、内存、磁盘容量与 IO、网络吞吐与丢包 指标(USE) 饱和度、剩余可用时间
中间层 MySQL(连接、慢查询、复制延迟)、Redis(命中率、内存、evict)、Kafka(积压、ISR)、连接池 指标 + 日志 积压趋势、慢查询 TOP
应用层 入口吞吐/延迟/状态码、调用链、性能瓶颈、前端体验 指标 + 链路 + 日志 RED、trace 列表、错误聚类

四个验收问题

看板做完了,用这四个问题验收。答不上来,说明缺的不是面板,是关联维度:

问题 需要什么才能答
一台机器挂了,会影响哪些对外 API? service.name ↔ host.name ↔ 路由 的关联表/拓扑
一个 API 变慢,是 GC、资源不足,还是依赖慢? 同一时间窗内的 GC/饱和度指标 + trace 的 span 拆分
一条 SQL 变慢,会影响哪个对外 API? 从 DB 实例反查到调用方服务,再到入口路由
MQ 积压了,会影响哪些 API? 消费组 → 服务 → 路由的依赖图

TOP-N 三视图

排障时最有用的三个排名,缺一不可:

视图 排序依据 回答
按调用量 请求数降序 哪些接口承载主要流量(先保它们)
按最耗时 P99 或总耗时降序 哪里最慢(优化收益最大)
按热点 单实例/单 key 的集中度 是否有个别实例或热点 key 在拖后腿

图和告警同源:recording rules

groups:
  - name: route-recording
    interval: 30s
    rules:
      - record: route:http_requests:rate5m
        expr: sum by (route) (rate(http_requests_total[5m]))
      - record: route:http_errors:ratio5m
        expr: |
          sum by (route) (rate(http_requests_total{code=~"5.."}[5m]))
          /
          sum by (route) (rate(http_requests_total[5m]))

面板与告警都查 route:http_errors:ratio5m,就不会出现“图上 5m、告警 1h”的口径漂移;改口径只改一处。recording rules 用 promtool check rules 校验;告警规则的单测见 50.5 告警。

告警响了之后谁接、怎么升级,见 56.3 on-call (值班 / 升级路径 / runbook)。

promtool check rules /etc/prometheus/rules/*.yml
# 面板/告警引用了不存在的 recording rule → 直接搜出来
grep -R "route:http_errors:ratio5m" dashboards/ rules/

一条纪律:看板上的每个数字,要么来自 recording rule,要么来自一条能在告警里复用的查询;否则同一个指标迟早出现两种口径。

看板的生命周期

  • 看板即代码:JSON 进 Git,改动走 PR。手改 UI 的看板三个月后没人知道某个图为什么在那。
  • 每块面板有 owner:写在标题或描述里;没有 owner 的面板默认「可删」。
  • 季度清理:30 天无人访问的看板归档(Grafana 有 usage stats)。看板数量本身就是一种技术债。
  • 告警与看板同源:告警里的 PromQL 就是看板里的查询;否则会出现「图上正常、告警在响」这种最伤信任的情况。
  • 新服务上线即带看板:模板化(同样的 RED + USE 布局),而不是等出事再手工搭。

反模式

反模式 后果
把所有指标都堆上去(200 个图) 首屏失去焦点,排障变成「找图」
用平均值做主图 长尾不可见,用户投诉与看板长期矛盾
没有变更标注 排障时要挨个问「刚才谁发布了」
各面板时间范围不一致 无法目视关联,A 图 1 h、B 图 30 d
每个服务手工一套看板 新服务上线没有看板,故障时靠猜
看板无 owner、无清理 半年后没人敢删,也没人看得懂
红绿滥用、彩虹配色 一片红等于没有红
看板与告警用两份查询 「图上正常、告警在响」,团队开始不信监控
把看板当告警(人盯屏) 没人盯的时段就是盲区(50.5 告警)

自检

Q1 为什么首屏必须有「最近变更」面板?

▸ 答案:排障的第一个假设应该是「刚才改了什么」,因为变更(发布、配置、扩缩容、开关)是最常见的故障触发器,而且它给出的动作(回滚)往往最快见效。把发布时间点画在指标图上,能让「指标从 14:02 开始变坏」与「14:02 有一次发布」在视觉上直接对齐,省掉最耗时的一轮「挨个问人」。

Q2 一个看板放 200 个图,问题出在哪?

▸ 答案:看板服务的是一次决策,200 个图意味着没有决策目标,读者要在里面「找」而不是「看」。具体代价:① 首屏失去焦点,异常信号被淹没;② 加载慢、查询贵;③ 没人维护,图例与指标名半年后过期;④ 无法判断哪块该删。正确做法是按场景拆成多个看板(首屏 6 图、服务详情 8–12 图),用下钻连接。

Q3 「一台机器挂了,会影响哪些对外 API」——这个问题需要什么数据才能回答?

▸ 答案:需要三层关联:主机/容器 → 运行在其上的服务实例(host.name/pod ↔ service.name)→ 服务对外暴露的路由(service.name ↔ route)。只有指标没有关联维度时,这个问题无法回答——你能看到「这台机器 CPU 掉了」,但说不出影响面。所以看板的前提是统一的资源命名(见 50.1 三支柱与成本模型),而不是更多的图。

Q4 为什么看板与告警必须用同一条查询?

▸ 答案:否则会出现「图上一切正常,告警在响」或者反过来。原因通常是两份查询的过滤条件、窗口、聚合方式不同(图上是 sum by (route),告警是 sum 全局;图上用 5 m,告警用 1 h)。这种不一致会直接摧毁团队对监控的信任,进而导致「告警响了先关掉」——比没有告警更糟。

Q5 延迟分布为什么用热图而不是 P99 折线?

▸ 答案:P99 折线只给一条分位线,会掩盖「分布形状的变化」:双峰(缓存命中/未命中)、整体右移、或者长尾变厚,在单条线上看起来可能一样。热图(时间 × 延迟桶 × 计数)能直接看到分布怎么迁移,判断是「整体变慢」还是「一小撮请求变慢」。代价是读图门槛更高,所以热图放在服务详情页,首屏仍用 P50/P95/P99 三条线。

关联