面板是准确的,问题却不是同一个
一句话总结
面板画出错误数值的情况很少见。常见的是面板精确地展示了一个我们没有问过的问题的答案。
为什么需要它
故障结束后的复盘中,经常会出现这样一句话:“仪表板明明是正常的啊。”可是把同一时间段的原始数据重新量一遍,异常分明存在。查询是对的,数据也在。在这中间消失的,是面板选项。
假设有一个用大字显示一个数字的面板。人们会把它读成“当前值”。但这个面板实际计算的,可能是界面上所显示时间范围内的平均值。如果看的是六个小时,一次 20 分钟的突增,在平均值里几乎就消失了。面板是准确的,只是在回答一个没有人问过的问题——“过去六个小时的平均值是多少”。
缺失的点也一样。采集中断 30 分钟,那段时间里就没有点。如果把线直接连起来,图表会平滑地流过,看的人就会以为那 30 分钟里服务也运行良好。中断的是没有数据这个事实,而连线这个选择把这个事实抹掉了。
工作原理
Grafana 的面板大致有三层。查询获取时间序列,字段设置和转换对其加工,可视化选项决定绘制方式。被误读的面板,大多出在第二层和第三层。所以无论怎么盯着查询看,也看不出原因。
| 选项 | 决定什么 | 设置不当会怎样 |
|---|---|---|
计算值(reduceOptions.calcs) |
把一个时间序列压缩成一个数字的方法 | 设为平均值,突增就被掩盖 |
null 处理(spanNulls) |
是否连接缺失的点 | 连接的话,采集中断就被抹掉 |
堆叠(stacking.mode) |
是否把序列堆叠起来 | 堆叠的话,就无法读出单个值 |
| 序列数量 | 一个面板显示多少条 | 只问一个值的问题,却弹出四个框 |
先看计算值。时间序列有很多点,而只显示一个数字的面板必须从中选一个。选最后一个值是“当前”,选平均值是“该时间段的平均”,选最大值是“该时间段的最坏情况”。这三者是完全不同的问题,而面板标题并不区分它们。所以标题是“请求率”时,人们一定会读成“当前请求率”。如果这种读法与面板的计算不一致,界面就会悄悄地出错。
null 处理有三种。连接绘制、断开、用 0 填充。三者分别主张“那期间也有值”“那期间不知道”“那期间是 0”。像计数器的变化率那样,采集一旦中断就确实无法得知的值,应当断开绘制;像队列长度那样 0 有意义的值,则视情况而定。重要的是知道无论选哪一种,都是在做出一种主张,然后再去选择。
堆叠只有在想看总和时才是正确的。堆叠图最上面的那条线不是任何一个序列的值,而是全部的总和,但人眼会把最上面的线读成“最大的序列”。如果目的是比较各序列,就不应堆叠;如果想了解占比,就用 100% 堆叠这样明确表达比例的形式。
最后是标题和说明。Grafana 的面板有填写说明的位置(面板编辑文档),在那里写下问题句,两件事就一并解决了。读的人知道应该怎样读这个面板,半年后也能判断这个面板是否可以删除——只需要看那个问题是否还在问。
在现场相遇的样子
这是支付服务的状态仪表板上真实发生过的事。错误率面板全天都是绿色,客户咨询却不断进来。面板是 stat,计算值是平均值,默认时间范围是 24 小时。上午有 12 分钟错误率达到 30%,但按全天平均只有 0.25%。把计算值改成最后一个值、把时间范围缩短为一小时之后,同样的事故在下一周只用 3 分钟就引起了注意。
另一个是堆叠。按处理器划分的请求率面板被画成了堆叠,团队把最上面的线读成 /api/orders 的请求率,并据此做了容量规划。实际的 /api/orders 只有它的一半。并不是改了数字,而是仅仅关掉堆叠,误解就消失了。
本环境能判定与不能判定的内容
这个 Pod 中的 Grafana 是真正在运行的,但没有图像渲染器插件。所以无法检查面板在界面上是怎样绘制的。取而代之的是,依据仪表板 JSON 模型(计算值、null 处理、堆叠、标题、说明)以及用数据源实际执行其查询得到的值来判定。颜色实际看起来如何、线在哪里断开,最终还是要用眼睛看一次——实验中也建议用网页预览打开 3000 端口来确认。
下一项实验要做什么
原样上传一个包含六个缺陷的仪表板,然后逐一修正计算值、null 处理、堆叠、序列数量、标题和说明。每修正一处,都要用数字确认那个选择为什么是错的——在固定区间上亲自量出 last、mean、max,在某一时刻分别量出总和与单个值,看看堆叠隐藏了什么。最后,制作一个在下一个仪表板中也能抓出同样缺陷的检查器,并确认修正后的仪表板能通过这个检查器。