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

Grafana — 仪表盘是一个问题

六个面板各自回答着不同的问题

在 TT Lab 中继续学习

目标

拿到一个带有缺陷的仪表板,修正其计算值、null 处理、堆叠、序列数量、标题和说明,并制作一个在下一个仪表板中也能抓出同样缺陷的检查器,让它通过。

为什么重要

仪表板悄悄出错的地方不是查询,而是面板选项。查询是对的,但只显示一个数字的面板展示的却是平均值,那么 20 分钟的突增就会消失在六个小时的平均值里。把缺失的点连起来绘制,采集中断这一事实本身就被抹掉;把序列堆叠起来,最上面的线就会被当作单个值来读。这三种情况都不是“错误的值”,而是“没有被问过的问题的准确答案”,所以看的人无法知道自己读错了。因此,要在说明中把每个面板回答什么问题定下来,并让检查器来守住这个约定。

步骤

  1. 用 lab-start-grafana 启动 Grafana,并把带有缺陷的仪表板 /opt/lab/gfd/gfd-misread/broken.json 不做修改、原样上传到 Grafana(uid 是文件中写的 gfd-misread,共 6 个面板)。用 curl 向 /api/dashboards/db 发送 POST 即可。
  2. 1 号面板(요청률,韩文,意为“请求率”)目前显示的是平均值。选一个已经过去的区间(1 小时以上,结束时间早于现在),在该区间上亲自量出 sum(rate(http_requests_total{job="shop-api"}[5m])) 的最后一个值、平均值和最大值,并在 /root/gfd-misread/02-calc.txt 中用 start=、end=、last=、mean=、max= 五行写下来(start、end 是 epoch 秒)。然后把 1 号面板的计算值改为 lastNotNull 并保存。
  3. 在 /root/gfd-misread/03-null.txt 中写 connected=、none=、zero= 三行。每一行都要用不少于 40 个字符说明该 null 处理选择向看的人主张了什么,并且三行必须互不相同。然后把 2 号面板(대기열,韩文,意为“队列”)的 spanNulls 改为 false 并保存。
  4. 3 号面板(핸들러별 요청률,韩文,意为“按处理器的请求率”)是把序列堆叠起来绘制的。选一个已经过去的时刻,分别量出那一刻的总和以及 /api/orders 这一个处理器的值,并在 /root/gfd-misread/04-stack.txt 中用 at=、total=、orders= 三行写下来(at 是 epoch 秒)。然后把 3 号面板的 stacking.mode 改为 none 并保存。
  5. 4 号面板(핸들러 지연,韩文,意为“处理器延迟”)的查询为每个处理器返回一个序列。数出序列的个数,写到 /root/gfd-misread/05-series.txt 的 before= 中,然后修改查询,让这个面板只回答“当前最慢处理器的 p95 是多少”这一个问题并保存,再把修改后查询的序列数写到 after= 中。
  6. 把六个面板的标题都改成能看出它在看什么(禁止使用 그래프(韩文,意为“图表”)这样的名称),并在说明中写下该面板所回答的问题句,以问号结尾(不少于 12 个字符,每个面板各不相同)。保存修改后的仪表板。
  7. 创建 /root/gfd-misread/lint.py。它接收仪表板 JSON 文件路径作为参数,把下面五条规则的违规每行输出一条(以 R1 到 R5 开头),只要有一处违规,就以退出码 1 结束。R1 stat 面板的计算值中含有平均值 · R2 spanNulls 为真 · R3 stacking.mode 为 normal · R4 说明不以问号结尾 · R5 标题为空,或者是 그래프、패널、차트(韩文,依次意为“图表”“面板”“图表”)。请在原始文件 /opt/lab/gfd/gfd-misread/broken.json 上运行,确认五条规则全部都能被抓出来。
  8. 把已经上传到 Grafana 的当前仪表板原样下载,保存到 /root/gfd-misread/fixed.json(只取 .dashboard 正文),运行检查器,确认违规为 0、退出码为 0。然后在 /root/gfd-misread/08-review.md 中用 R1= 到 R5= 五行,分别用不少于 30 个字符写明改了什么、为什么改。

参考

把修正之前的状态载入界面

用 lab-start-grafana 启动 Grafana,并把带有缺陷的仪表板 /opt/lab/gfd/gfd-misread/broken.json 不做修改、原样上传到 Grafana(uid 是文件中写的 gfd-misread,共 6 个面板)。用 curl 向 /api/dashboards/db 发送 POST 即可。

保存 API 把仪表板正文放在 dashboard 键中,并同时发送 overwrite。从文件构造这种形式,用 jq -n --slurpfile 比较方便。Grafana 启动需要几秒钟,请先看 /api/health 是否有响应。

只显示一个数字的面板,计算的是什么值

1 号面板(요청률,韩文,意为“请求率”)目前显示的是平均值。选一个已经过去的区间(1 小时以上,结束时间早于现在),在该区间上亲自量出 sum(rate(http_requests_total{job="shop-api"}[5m])) 的最后一个值、平均值和最大值,并在 /root/gfd-misread/02-calc.txt 中用 start=、end=、last=、mean=、max= 五行写下来(start、end 是 epoch 秒)。然后把 1 号面板的计算值改为 lastNotNull 并保存。

区间查询是 /api/v1/query_range,需要同时发送 start、end、step。通过数据源代理发出,走的就是与 Grafana 相同的路径。计算值位于仪表板 JSON 的 options.reduceOptions.calcs 中。之所以用固定区间来量,是为了以后重新量时能得到相同的值。

连接缺失的点也是一种主张

在 /root/gfd-misread/03-null.txt 中写 connected=、none=、zero= 三行。每一行都要用不少于 40 个字符说明该 null 处理选择向看的人主张了什么,并且三行必须互不相同。然后把 2 号面板(대기열,韩文,意为“队列”)的 spanNulls 改为 false 并保存。

如果把采集中断的区间连起来绘制,看起来就好像那段时间也有值。null 处理位于 fieldConfig.defaults.custom.spanNulls。也请想一想这三种选择分别在什么情况下是正确的——这不是只有一个正确答案的问题。

堆叠起来的最上面一条线不属于任何序列

3 号面板(핸들러별 요청률,韩文,意为“按处理器的请求率”)是把序列堆叠起来绘制的。选一个已经过去的时刻,分别量出那一刻的总和以及 /api/orders 这一个处理器的值,并在 /root/gfd-misread/04-stack.txt 中用 at=、total=、orders= 三行写下来(at 是 epoch 秒)。然后把 3 号面板的 stacking.mode 改为 none 并保存。

某一时刻的值,用 /api/v1/query 并附带 time= 即可。必须把时刻固定下来,以后重新量时才会得到相同的值。堆叠设置位于 fieldConfig.defaults.custom.stacking.mode。比较这两个数字,就能知道把最上面的线读成单个序列会错得多大。

只问一个值的面板却来了四个序列

4 号面板(핸들러 지연,韩文,意为“处理器延迟”)的查询为每个处理器返回一个序列。数出序列的个数,写到 /root/gfd-misread/05-series.txt 的 before= 中,然后修改查询,让这个面板只回答“当前最慢处理器的 p95 是多少”这一个问题并保存,再把修改后查询的序列数写到 after= 中。

用 promq "<쿼리>"(占位符为查询语句)发出查询,结果序列会每行一个地显示出来。有一个聚合运算符可以只保留多个序列中最大的那一个值。查询位于仪表板 JSON 的 targets[0].expr。

标题和说明就是该面板的问题

把六个面板的标题都改成能看出它在看什么(禁止使用 그래프(韩文,意为“图表”)这样的名称),并在说明中写下该面板所回答的问题句,以问号结尾(不少于 12 个字符,每个面板各不相同)。保存修改后的仪表板。

说明是仪表板 JSON 中每个面板都有的 description。在界面上,它显示为面板标题旁的信息标记。写成问题句之后,半年后就能判断这个面板是否可以删除——只需要看那个问题是否还在问。

在下一个仪表板中也抓出同样的缺陷

创建 /root/gfd-misread/lint.py。它接收仪表板 JSON 文件路径作为参数,把下面五条规则的违规每行输出一条(以 R1 到 R5 开头),只要有一处违规,就以退出码 1 结束。R1 stat 面板的计算值中含有平均值 · R2 spanNulls 为真 · R3 stacking.mode 为 normal · R4 说明不以问号结尾 · R5 标题为空,或者是 그래프、패널、차트(韩文,依次意为“图表”“面板”“图表”)。请在原始文件 /opt/lab/gfd/gfd-misread/broken.json 上运行,确认五条规则全部都能被抓出来。

只把规则写成文字,下一个仪表板还会以同样的状态诞生。请写成能运行的代码。别忘了折叠在行(row)里的面板也是面板。文件可能被 {"dashboard": ...} 包着,也可能就是仪表板正文。

修正后的仪表板自己通过自己的检查器

把已经上传到 Grafana 的当前仪表板原样下载,保存到 /root/gfd-misread/fixed.json(只取 .dashboard 正文),运行检查器,确认违规为 0、退出码为 0。然后在 /root/gfd-misread/08-review.md 中用 R1= 到 R5= 五行,分别用不少于 30 个字符写明改了什么、为什么改。

要让文件与界面不分道扬镳,修改之后必须重新下载。如果检查器没有以 0 结束,输出会告诉你还剩下哪个面板。留下记录是为了让下一个人不必重复同样的判断。