TT Lab
开始
学习 学习路径 课程

Grafana — 仪表盘是一个问题

没有单位的数字,由读的人自行臆测

在 TT Lab 中继续学习

一句话总结

没有写单位的数字,读的人会自己编出一个单位。而编出来的单位,往往偏向对那个人有利的一边。

为什么需要它

故障会议上,有人打开仪表板说:“延迟是 0.42。”会议室里一半人听成了 420 毫秒,另一半人听成了 0.42 毫秒。这两个数字相差一千倍,一个是事故,一个是自豪。对话又持续了大约 20 分钟,直到有人打开查询看了才结束。

这种错位并不是人粗心造成的。是因为界面只显示数字。Grafana 有给值加上单位的功能,但这个功能只有在我们告诉它这是什么的时候才会工作。如果什么也不说,Grafana 就原样画出数字,解读的责任留给看的人。

更糟的情况是写了单位,却写错了。没有单位时,人们至少还会怀疑一下。有了单位,就没有人怀疑了。如果给以秒为单位输出的查询加上毫秒单位,界面会自信地说“0.42 ms”,看到的人就会相信服务非常快。

工作原理

Grafana 的单位是显示规则,而不是转换规则。在面板的 fieldConfig.defaults.unit 中写下标识符后,Grafana 会用绑定在该标识符上的格式函数,把数字转换成字符串。值本身不会被改动。所以要让以秒为单位的值显示成毫秒,不是只改单位,而是必须在查询中乘以 1000。

标识符与界面上显示的名称不同。下拉框中写的是“Percent (0.0-1.0)”,但进入 JSON 的值是 percentunit。“bytes(IEC)”是 bytes,“bytes(SI)”是 decbytes。前者按 1024 相除并缩写为 GiB,后者按 1000 相除并缩写为 GB。同样的 4294967296,既可以显示为 4 GiB,也可以显示为 4.29 GB。哪一个正确,取决于生成这个数字的一方数的是什么。

比率也有两套。对 0 到 1 之间的值使用 percentunit,对 0 到 100 之间的值使用 percent。用 PromQL 得出的错误比率几乎总是前者,但面板上常常带着后者。这样,1.6% 的错误率在界面上就会显示成 0.016%。告警在响,而仪表板看起来风平浪静,这种状态就是这样产生的。

坐标轴是继单位之后第二种谎言的所在。Grafana 默认会根据数据自动设定 y 轴。如果每秒请求数在 34 到 75 之间浮动,轴也会设成 34 到 75,在这个范围内,线条会占满整个界面高度地起伏。实际上只相差两倍多一点,界面看起来却像悬崖。所以,对计数类面板,把最小值固定为 0 才是诚实的做法。标准选项文档中的 Min、Max 就是做这件事的位置。

相反,最大值不能随便固定。把最大值钉在 20 的请求数面板,即使流量涨到 75 的那天,也只会显示一条在 20 处被截平的天花板。事故总是发生在那条天花板之上,却不会留在界面上。如果只是不喜欢因波动小而显得线条扁平,就不要用硬性最大值,而是使用时间序列面板的 Soft min、Soft max。数据一旦超出该范围,轴会随之变宽,不会被截断。

有时也需要在一个面板中同时画出两个单位不同的东西。把延迟和错误比率叠在一起,问“变慢的时刻和失败增加的时刻是否相同”的面板就是这样。这时把整个面板的单位定为一个,只对其余序列通过覆盖(override)单独指定单位和轴的位置。时间序列面板文档写明,单位有两个以上时,第一个单位使用左轴,之后的单位使用右轴。如果不做覆盖直接叠在一起,两个序列就会共用一个轴,0.004 的比率在 0.3 的延迟旁边就会成为贴在底部的一条直线。

对数轴用于把大小相差悬殊的序列放进同一个界面。如果把每秒 42 次的处理器和每秒 6 次的处理器画在同一条线性轴上,较小一方的变化就看不见了。在对数轴上,相同的纵向距离表示相同的倍数,所以两者都能读出来。但也有所失。刻度之间的距离不再是数量的差值,所以无法用眼睛把面积相加;0 和负数根本画不出来;而且涨了两倍的事件和涨了十倍的事件看起来高度差相近。所以它不适合用来询问“增加了多少”的面板。

本实验有一件事无法判定——实际绘制出来的图像。这个 Pod 中的 Grafana 没有图像渲染器插件,无法把面板导出为图像。所以评分器只看仪表板 JSON 模型和查询结果。单位标识符是什么、轴的最小值是多少、查询实际给出什么值,这些都可以确认,但这样的组合在界面上是否可读,则无法确认。轴名称重叠被截断,或者图例盖住图表这类问题,需要自己用网页预览打开 3000 端口,用眼睛看。模型正确与界面可读是两回事。

在现场相遇的样子

有一个团队在内存使用量面板上用的是 SI 单位。容器限制是 4 GiB,界面却显示 4.29 GB,人们读成“还有余量”。当天夜里,那个 Pod 触及限制而死掉了。值从来没有错过,错的只是名称。

在另一个团队里,错误率面板连续几个月都用着 percent。即使实际错误率涨到 2% 的那天,界面显示的也是 0.02%。告警正常响了,但负责人看着仪表板,判断“告警好像响错了”而忽略了它。事故复盘时谈得最久的,不是告警规则,而是那一个单位字符。

下一项实验要做什么

启动真正的 Grafana,上传一个没有单位的面板,亲手写下这个数字可以被读成几种。接着给秒、比率、字节的面板填入 Grafana 的单位标识符,发出查询确认值的大小与单位是否匹配,并亲手确认要显示成毫秒需要乘以什么。区分必须把轴的最小值固定为 0 的地方,和不能固定最大值的地方,用覆盖把两个单位不同的序列放进同一个面板,使用对数轴之后写下失去了什么。最后拿到一个从生产环境取回的仪表板,把其中四个单位和轴的缺陷全部修正并提交——评分器会向 Grafana 询问修正后的仪表板,并实际发出面板的查询,看值与单位是否匹配。