一个接口的 QPS 从 800 冲到 3000,同时 P99 延迟从 60ms 爬到 400ms。这两条曲线塞进同一张 Grafana 图里,共用一个 Y 轴,结果是 QPS 把延迟压成贴着零轴的一条直线,什么都看不出来;反过来以延迟为准,QPS 又直接顶出画布。这就是双 Y 轴要解决的问题:让量纲相差一个甚至几个数量级的指标,在同一个时间窗口里还能互相参照。Grafana 里把第二条 Y 轴挂上去,熟练的人两分钟搞定,但它背后牵扯到面板类型、字段覆盖 Overrides、单位层级、坐标轴缩放、面板拷贝这几件事,任何一环理解错,图就会悄悄骗你——注意是悄悄,因为它照样能画出来,只是画得不对,而且能骗过不看细节的同事。下面这些是我在 8.x 到 11.x 几个版本上反复配、反复改之后整理出来的东西,包含完整操作路径,也包含几个我实打实被坑过的位置。
1. 先判断这张图到底该不该用双 Y 轴
1.1 量纲差一个数量级,才是双轴的正当理由
我见过太多人被"双 Y 轴"这个功能本身吸引,什么指标都想往上挂。判断标准其实很朴素:两个指标的数量级差多少。QPS 是千级、延迟是百毫秒级,差了十来倍甚至上百倍,共轴必然有一方被压扁,这时候双轴是对的。CPU 使用率是 0 到 100 的百分比、内存用量是几十 GB 的字节数,同样共轴没法看,双轴也合理。反过来,如果两个指标量纲完全一致——比如两个服务的响应时间,一个是 80ms,一个是 120ms——硬拆成双轴就是给自己找麻烦。共轴画出来的两条线谁高谁低一目了然,双轴之后两条线各自占满画布高度,看起来都"很剧烈",你反而失去了对比能力。
还有一个容易被忽略的角度:你在这张图上到底要看什么。如果目的是"看趋势是否同步",比如流量涨的时候延迟是不是跟着涨,那双轴很合适,因为你需要的是形状的同步性,不是绝对数值。但如果目的是"看某一刻的精确值",比如容量规划要读内存峰值,那双轴就有点危险,因为右轴的刻度和你肉眼判断的位置之间隔了一层换算。
1.2 三种我建议直接放弃双轴的情况
第一种,右轴上挂了三个以上的指标。我踩过这个坑,当时想把 GC 次数、线程数、连接数全挂到右轴,结果三条线颜色接近、数值范围差十倍,右轴刻度被最大的那条撑开,另外两条贴底。这种图对老板汇报还行,对自己排查问题毫无价值,正确做法是拆成三个独立面板,用 Row 折叠起来。
第二种,需要精确读出绝对值的关键指标。双轴会破坏你和网格线之间的直觉参照,左轴一条网格线对应的是什么值,右轴又是什么值,看久了会串。特别是当左右轴的 Min 不一样、零线不在同一水平线上的时候,误判几乎是必然的。
第三种,两轴单位可以用换算统一的情况。比如一个是字节、一个是 MB,那就别双轴了,把单位统一成 bytes,让 Grafana 的自动单位格式化去处理,它会在图例里自动显示 GiB、MiB 这种可读形式。
提示:把两个单位能直接换算的指标拆成双轴,是最常见也最没有技术含量的错误用法。先看能不能换算,再考虑双轴。
1.3 我自己用的一张判断表
| 情况 | 建议 | 理由 |
|---|---|---|
| 量纲差 10 倍以上,看趋势同步性 | 用双轴 | 双轴的核心价值场景 |
| 量纲相同,看高低对比 | 共轴 | 双轴反而破坏对比 |
| 需要读精确绝对值 | 拆成上下两个面板 | 共享 X 轴时间,读数不受干扰 |
| 右轴指标超过 2 个 | 拆面板或做聚合 | 右轴刻度会被最大范围撑开 |
| 单位可换算(B / MB,ms / s) | 统一单位,共轴 | Grafana 自带单位格式化 |
2. Time series 面板里把右轴配出来的完整路径
2.1 先确认你的版本,Graph 和 Time series 是两套逻辑
这件事必须先说清楚,因为网上大量教程还停留在 Graph 面板时代,你照着做会发现界面对不上。Grafana 8.0 之后 Time series 面板成为默认的时间序列面板,它的坐标轴配置逻辑和老的 Graph 面板完全不同。老 Graph 面板把轴单独放在一个 Axes 标签页里,右 Y 轴有个 Show 勾选框;新面板没有这个勾选框,右轴是通过字段覆盖(Overrides)里的 Axis placement 属性"长出来"的。
| 版本区间 | 默认面板 | 右轴配置入口 |
|---|---|---|
| 7.x 及更早 | Graph | Axes 标签页勾选 Right Y,再在 Series overrides 里给系列指定 yaxis: 2 |
| 8.x | Time series(默认)+ Graph (old) | Overrides 中给字段加 Axis > Placement = Right |
| 9.x | Time series | 同上,路径一致 |
| 10.x / 11.x | Time series | 同上,Overrides 属性面板做了分组,Axis 相关属性在 Axis 分组下 |
如果你手上的面板还是 Graph 老面板,有两个选择:一是直接在上面继续改,逻辑在第四章讲;二是在面板菜单里选择迁移到 Time series,迁移后绝大多数配置能自动转换,但双轴的转换偶尔会出问题,我在第四章也写了怎么排查。
2.2 Standard options 和 Overrides 的分工,是新手最容易绊倒的地方
Time series 面板右侧的编辑区分成上下两块。下面那块叫 Standard options,你可以把它理解成"这片土地上所有字段的默认值"——单位、最小值、最大值、小数位、颜色、阈值,都先在这里定一个全局默认。上面那块叫 Overrides,意思是"针对某一个特定字段,我要破例"。
关键认知在这里:右轴这件事,在 Standard options 里根本找不到入口。你不可能通过某个开关"打开右轴"。右轴是随着 Overrides 里出现第一个 Axis Placement 设为 Right 的字段,才凭空出现的。反过来说,如果你把那个 Override 删掉,右轴就会跟着消失,这也就是后面排查时"右轴不出现"最常见的根因。
单位也是同一套逻辑。标准选项里的单位作用于所有字段,你在 Override 里给右轴字段设了 ms,只对这个字段生效;但如果你反过来只在 Standard options 里把单位设成 ms,那左轴的 QPS 也会被贴上 ms 单位,图例里就会出现 "3000 ms" 这种荒谬显示。
另外还有一个细节,Overrides 的匹配方式决定了这条规则"粘"在哪个字段上。可用的匹配器有按字段名(byName)、按正则(byRegexp)、按字段类型(byType)、按查询编号(byFrameRefID)。默认你点的是"Fields with name",它会精确匹配图例上的那个名字。名字一变,规则就静默失效——这是第五章要重点讲的坑。
2.3 六步挂上第二条曲线到右轴
我把完整步骤按顺序列一下,你可以对着操作。
- 打开仪表盘,编辑目标面板,确认面板类型是 Time series(右上角面板类型选择器里能看到)。
- 在下方 Query 区域新增第二条查询。此时两条查询的结果会同时出现在图上,共用左轴,通常其中一条会被压扁。
- 给第二条查询的 Legend 填一个有意义的格式,比如直接写
P99 延迟,或者用{{instance}} P99这样的模板变量组合。名字要稳定、可读,因为后面 Override 要靠它匹配。 - 鼠标移到右侧编辑区上方的 Overrides 区域,点
+ Add an override,选Fields with name,在下拉里选中刚刚那个字段名。 - 在
+ Add override property里依次添加这几个属性:Axis > Placement选Right;Standard options > Unit选你需要的单位(延迟用milliseconds (ms)或seconds (s),百分比用Percent (0-100));Standard options > Decimals定小数位数,通常 2 位够用。 - 如果右轴数值波动很大,继续加
Axis > Soft min和Axis > Soft max,把右轴视野锁死在一个合理区间,比如延迟锁 0 到 1000ms。
第 5 步做完,图上应该立刻出现右侧的第二条 Y 轴,刻度是 ms。如果没有,去第六章对照排查。
同一个 Override 在面板 JSON 里长这样,理解这个结构对后面拷贝面板很有用:
"overrides": [ { "matcher": { "id": "byName", "options": "P99 延迟" }, "properties": [ { "id": "custom.axisPlacement", "value": "right" }, { "id": "unit", "value": "ms" }, { "id": "decimals", "value": 2 }, { "id": "custom.axisSoftMin", "value": 0 }, { "id": "custom.axisSoftMax", "value": 1000 } ] } ]2.4 右轴的单位、Min/Max 和 Scale 该定成什么
单位这块,Grafana 的单位字符串是有讲究的。延迟类指标建议直接用ms,Grafana 会自动处理成毫秒显示;如果你选的是s,但数据实际是毫秒量级的数值,图例上会出现 0.06s 这种读起来不直观的写法,虽然数学上没错,但排查问题时容易看走眼。Prometheus 的 histogram_quantile 算出来的分位数原始单位是秒,很多人图省事不乘 1000,然后在 Grafana 里硬把单位设成 s,结果阈值告警配的是毫秒,两边对不上。我的习惯是查询里就* 1000换算成毫秒,单位也统一用 ms,全链路一个量纲。
Min / Max 和 Soft min / Soft max 是两组不同的东西,混淆了会出问题。Min 和 Max 是硬边界,数据超出范围会被直接截断,超出的部分在图上画不出来;Soft min 和 Soft max 是软边界,数据超出时视图会自动扩展,保证数据始终可见。右轴我一般用 Soft min / Soft max,因为业务指标偶尔会突刺,硬截断会让我漏掉异常峰值这个重要信号。
Scale 的选型上,右轴用对数轴的场景其实不多,但也有典型例子:右轴是错误数量,从个位数到几十万都可能出现,线性轴会把小值全压在底部,这时候把右轴的 Scale 切成 Logarithmic 会好看很多。不过要提醒一句,对数轴会让"两条线是否同步"这个判断失效,因为对数变换改变了曲线的形状,如果这张图的目的是看同步性,就别动 Scale。
3. 单位、零线、阈值和图例:双轴面板里四个高频翻车点
3.1 单位设了不生效,八成是设错了层
我遇到过最多次的问题就是这个。现象是:Override 里明明给右轴字段设了 ms,但图上的右轴刻度还是显示成百分比或者无单位。排查下来无非三种原因。
第一种,Override 的匹配器匹配错了字段。你可能在Fields with name里选了一个已经不存在的名字,比如查询的 Legend 从P99 延迟改成了{{service}} P99,图例上显示成order-svc P99,名字对不上,但这条 Override 还留在配置里,界面上看不出任何异常,它只是静静地不生效。
第二种,单位被字段本身携带的信息覆盖了。Prometheus 数据源返回的 metric 如果带了 unit 元信息,或者你用了Alias类型的字段,某些情况下字段自带的单位会优先。解决办法是在 Override 里显式再设一遍单位,显式覆盖总是生效的。
第三种,也是最隐蔽的:你以为图上的右轴是右轴,其实它是左轴的镜像。当两个字段的数值范围恰好接近,而你在 Override 里只设了 Placement 忘了设单位,两条轴可能都显示左轴的单位。判断方法是看两条轴的刻度数值是否真的不一样,一样就是配置没生效。
注意:每次改完 Override,别急着关面板。先把鼠标悬停在图例上,逐个字段确认它被分配到了哪条轴、单位是什么。多花十秒,省掉后面半小时的怀疑人生。
3.2 左右零线不对齐带来的视觉误导
这是个纯粹视觉层面但后果很严重的问题。左轴是 QPS,范围 0 到 3000;右轴是延迟,范围自动算出来是 60 到 400。这时候左轴的零点在画布最底部,右轴的零点在画布下方外面,两条曲线的相对位置失去了共同参照,你看到延迟线在某个时间点"高于"QPS 线,会下意识觉得延迟出问题了,其实只是两条轴的零点不一样。
处理办法有两个。简单办法是给右轴设 Soft min = 0,让右轴也从零点开始,这样至少底部对齐了。更彻底的办法是用 Axis 区域里的 Centered zero(居中零线)选项,它会把零线放在画布中间,正负值分列上下,配合 Negative Y 变换能做出很直观的进出流量图,这个我在第六章的案例里会展开。
还有一个更隐蔽的情况:右轴是百分比,左轴是整数,右轴设了 Min = 0、Max = 100,左轴自动范围是 0 到 3000。这时候右轴的网格线位置和左轴的网格线位置是不重合的,视觉上会出现两套网格。Time series 面板对此的处理是只让一条轴画网格线,另一条轴的网格线是关闭的,所以你看到图上只有一套网格,它属于哪条轴需要你心里清楚。
3.3 阈值线到底画在哪条轴上
阈值(Thresholds)在 Time series 面板里是个容易被忽视的存在。Standard options 里设的阈值,默认会作用于所有字段,也就是说左轴和右轴的曲线都会被染色。这在双轴场景下几乎必然出问题:你给延迟设的 500ms 阈值,会把 QPS 的曲线也按 500 这个数染色,而 QPS 的数值是几千,于是整条 QPS 线一直是红色,看起来像是全线告警。
正确做法是把阈值也放进 Override 里,针对右轴那个字段单独设置。在 Override 属性里选Thresholds,然后按该字段的单位来配。这样左轴的 QPS 保持自己的颜色逻辑,右轴的延迟才有红黄绿的分级。阈值线的绘制位置,我的经验是它会跟随字段所在的轴,但也有版本差异,如果你发现阈值线画在了不对的轴上,最稳的验证方式是临时把右轴字段隐藏,看阈值线是否跟着消失,跟着消失就说明阈值绑定在该字段上。
3.4 图例和 Tooltip 的显示策略
Time series 面板的图例是一整块,不分左右,你没办法把左轴的字段和图例的左半边绑定、右轴的字段绑到右半边。这在字段多的时候很难读,看半天不知道哪条线属于哪条轴。
我的处理习惯是在 Override 里给字段改显示名,前面加个标记。左轴字段的 Display name 设成[左] QPS,右轴字段设成[右] P99 延迟。这纯属土办法,但效果立竿见影,尤其是面板要给不熟悉技术细节的同事看的时候。
Tooltip 这块,建议把 Mode 设成 All,这样鼠标悬停时会列出该时间点所有字段的值,双轴面板尤其需要这个,因为你需要同时看到 QPS 和延迟的值才能判断因果关系。Values 我一般选All或者Last not null,前者信息全,后者在数据有空洞时更干净。图例的 Placement 我偏好放 Right,因为双轴面板通常字段不多但名字长,放底部会挤成两行,影响面板高度。
4. 从 Graph 旧面板迁移到 Time series 的双轴差异
4.1 Graph 面板的老配置逻辑:Axes 加 Series overrides
很多存量仪表盘还是 Graph 面板,尤其是 2019 年前后做的那些。它的双轴配置分两步,步骤分散在两个不同的标签页里,这也是为什么老教程看起来特别绕。
第一步在 Axes 标签页。这里能配置左 Y 轴和右 Y 轴的显示、单位、缩放范围、标签文字。要让右轴出现,得在右 Y 轴那一块勾上 Show,这时候右侧会多出一条刻度轴,但还没有任何数据挂上去。
第二步在 Series overrides 标签页。这才是把数据挂到右轴的地方。你需要新增一条 override,通过 alias 匹配某一个系列的名字(老面板用的是 alias,不是字段名),然后设置Y-axis: 2。填 1 表示左轴,填 2 表示右轴。
对应到 JSON 里是这样的结构:
"seriesOverrides": [ { "alias": "P99 延迟", "yaxis": 2 } ]和 Time series 面板的 overrides 结构比,你会发现它简单得多,但匹配方式也更脆弱,因为它完全依赖 alias 字符串。而 alias 又经常配合 Legend format 模板变量生成,一旦变量取值变化,匹配就断了。
4.2 迁移之后曲线跑到左轴了,怎么修
Grafana 8 之后打开老仪表盘,Graph 面板还在,但你可以从面板菜单里选择迁移到新的 Time series 面板。迁移工具会把 Axes 和 Series overrides 尽量翻译成新的 fieldConfig 结构,大部分情况能翻译对,但双轴这块我遇到过两次翻译失败。
失败的表现是:迁移完成后,原本在右轴的字段回到了左轴,右轴整条消失。原因通常是原面板的 seriesOverrides 用的是 alias 匹配,而迁移工具把它转成了 byName 匹配,同时新面板的字段名是由数据源返回的帧名决定的,两者对不上。
修复方式很直接:进 Overrides 区域,找到那条可疑的规则,点开匹配器,改成实际字段名,或者干脆删掉重新加一条。如果字段名会随查询变化,建议改用按查询编号匹配。按查询编号匹配在 JSON 里的 id 是byFrameRefID,options 填查询的 refId,比如 A、B、C。这个匹配方式和字段名无关,查询改了 Legend 也不会失效,我在跨环境复用面板时基本都用它。
4.3 老版本 JSON 里的 legacy 查询报错
迁移或者拷贝老面板时,还有一个经典报错会拦路:failed to upgrade legacy queries datasource xxx was not found。这个报错和双轴没有直接关系,但特别容易在你拷贝一个老的双轴面板到新 Grafana 实例时撞上,因为老面板的 JSON 里数据源是用字符串名字记录的,比如"datasource": "Prometheus",而新版 Grafana 的数据源是用对象加 UID 记录的。
解决思路是在面板 JSON 里把那个字符串换成对象形式,指向目标实例上真实存在的数据源:
"datasource": { "type": "prometheus", "uid": "你的数据源UID" }UID 可以从目标实例的数据源配置页 URL 里看到,或者直接在数据源列表里点开复制。这个报错修好之后,面板就能正常加载,双轴配置也会跟着恢复——前提是 Overrides 里的字段名也对得上,这就是下一章要说的。
5. 面板拷贝与跨实例复用:双轴最容易在复制粘贴里失效
5.1 面板 JSON 里双轴的全部信息都在哪
想搞清楚拷贝为什么失效,得先知道双轴这件事在 JSON 里被拆成了几块。第一块是fieldConfig.defaults,这是全局默认;第二块是fieldConfig.overrides,这是字段级破例,右轴归属、单位、Min/Max 全在这里;第三块是每个targets里的datasource和查询语句,它决定了字段的实际名字。
拷贝面板的常规路径是:面板标题菜单 → Inspect → Panel JSON,复制整段 JSON,然后在目标仪表盘里新建面板 → 编辑 → 粘贴 JSON → Apply。整个过程看起来干净,但三块信息里任何一块与目标环境不匹配,双轴就可能失效。
最常见的失配是数据源 UID。源实例上 Prometheus 数据源的 UID 是一串随机字符,目标实例上完全不一样,粘贴过去之后查询加载不出来,字段名自然也就生成不出来,Overrides 里的名字匹配全部落空。
5.2 byName 匹配的脆弱性,以及换成 byFrameRefID 的写法
前面反复提到 byName 脆弱,这里把它讲透。byName 匹配的是字段在图例上的显示名。这个显示名怎么来的?两部分决定:查询的 Legend format 模板,以及模板变量在当前仪表盘里的取值。只要其中任何一项变了,显示名就变了。
举个具体例子。你的查询 Legend 写的是{{instance}} 延迟,在开发环境里只有一个实例dev-01,字段名就是dev-01 延迟,你的 Override 按这个字符串匹配,工作正常。把面板拷到生产环境,那里有 20 个实例,图例上变成 20 个字段,dev-01 延迟这个字段压根不存在,Override 静默失效,右轴消失。
换成按查询编号匹配就没这个问题:
"overrides": [ { "matcher": { "id": "byFrameRefID", "options": "B" }, "properties": [ { "id": "custom.axisPlacement", "value": "right" }, { "id": "unit", "value": "ms" } ] } ]含义是"B 这条查询产生的所有字段,全部挂到右轴,单位用 ms"。查询改了 Legend、实例数变了、变量取值变了,都不影响这条规则。代价是,如果 B 查询同时返回了多个你不想放右轴的字段,它也会一起被带上右轴,所以这种写法适合一条查询只服务于一个语义的场景。
提示:如果你预计面板要跨环境复用,从一开始就用 byFrameRefID 或 byRegexp,别用 byName。改两次名字你就知道有多烦了。
5.3 datasource uid 找不到的那条报错
再回到那条报错。datasource was not found类问题在拷贝面板场景下出现的频率非常高,特别是从别人那儿拷一个现成的双轴面板过来的时候。我总结的处理顺序是这样的。
先看报错信息里的那个标识符,它在老面板里通常是数据源的名字,在新面板里是 UID。然后去目标实例的数据源列表里找到对应的 Prometheus 数据源,复制它的 UID。最后在面板 JSON 里搜索所有的datasource字段,逐个替换。注意targets数组里每一条查询都有自己的 datasource,fieldConfig里也可能有,别只改第一处。
如果你是用仪表盘导入的方式(Import),可以在 JSON 里把数据源写成变量形式${DS_PROMETHEUS},导入向导会让你从下拉里选,这样跨环境复用最省事。这个方法在拷贝整个仪表盘而不是单个面板时特别值得用。
5.4 一条可复用的拷贝检查清单
| 检查项 | 检查方法 | 失效表现 |
|---|---|---|
| 数据源 UID | JSON 里搜 datasource,逐个核对 | 查询加载失败或报 legacy queries 错误 |
| Override 匹配器 | Overrides 里点开 matcher 看匹配方式 | 右轴消失,字段还在左轴 |
| 单位字符串 | Override 里的 unit 值 | 单位显示成 none 或错单位 |
| 模板变量名 | 查询 Legend 里引用的变量 | 图例名异常,字段名对不上 |
| 面板类型 | 目标实例是否支持 Time series | 面板渲染异常,配置项对不上 |
| 版本差异 | 目标实例的 Grafana 版本 | 某些 Override 属性不存在,被忽略 |
拷贝这件事,我的习惯是不直接粘 JSON,而是在目标环境里手动重建一遍双轴配置,三分钟的事,比事后排查半小时划算。只有仪表盘结构特别复杂、几十个面板的时候才走批量导入。
6. 三个真实场景的双轴配置与调试过程
6.1 场景一:QPS 与 P99 延迟
这是最经典的双轴组合,我在好几个项目里都配过。左轴 QPS,单位 reqps 或者 short,范围自动;右轴 P99,单位 ms,Soft min 设 0,Soft max 设成你告警阈值的两倍左右,比如阈值定 500ms 就设 1000。
调试时踩过的一个点是:QPS 用的是sum(rate(http_requests_total[5m])),延迟用的是histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))。这两个查询的时间窗口都是 5m,但 histogram_quantile 的结果在流量低的时候会剧烈抖动,右轴曲线上下乱跳,看起来比左轴还吓人。解决办法是给右轴的查询套一个max_over_time或者加长窗口到 10m,代价是灵敏度下降,需要根据业务节奏权衡。
另一个点是阈值。P99 阈值设好后,一定要放进 Override 里只作用于右轴字段,否则 QPS 曲线会被 500 这个数值整条染色,图上全是红的,第一眼以为是重大故障。
6.2 场景二:CPU 使用率与内存用量
这个组合的量纲差异比上一个更大,CPU 是百分比 0 到 100,内存是字节数,动辄几十 GB。左轴 CPU,单位 Percent (0-100),Min 0、Max 100,这样网格线位置固定,看起来舒服;右轴内存,单位bytes(IEC),Grafana 会自动显示成 GiB,Soft min 设 0。
这个场景里我用了一个表格式图例(Legend Mode 选 Table),把 Last、Max、Mean 三列都打开。CPU 和内存的变化节奏不一样,CPU 会跟着流量尖峰跳,内存更平缓但会累积。只看曲线判断趋势不够,配合图例里的 Max 值才能知道这台机器到底有没有接近容量上限。
需要注意的地方是内存的 Min。如果你把右轴的 Min 硬设成 0,而实际内存使用一直在 16GB 到 20GB 之间波动,曲线的变化会很微弱,看不出细节。这时候我一般把 Soft min 设成一个接近实际下限的值,比如 8G,让曲线在可见范围内展开,同时心里清楚右轴的零点不在画布底部。
6.3 场景三:进出流量用 Negative Y 做镜像
网络或者磁盘的进出流量,用双轴来做其实是个不错的选择,但方式要反过来用。左轴放"进",右轴放"出",单位都是 bytes/sec,然后给"出"的那个字段加一个 Transform 属性里的 Negative Y,让它向下生长。两条曲线以零线为轴上下镜像,看起来就像带宽的上下行。
零线的位置在这里是关键。如果左轴 Min 是自动算出来的负值或者正值,镜像效果就会歪。我一般把左轴的 Soft min 设成 0、Soft max 设成峰值的一点二倍,右轴同样处理,再加上 Axis 区域的 Centered zero,零线会稳定在画布中间。这样进出流量的不对称一眼能看出来,某一边突然翘起来就是异常。
这个场景还有一个好处:不需要额外的第三个轴。进出流量单位相同,本来就是可以共轴的,Negative Y 让它们在视觉上分开了,又保持了同一套刻度,读起来比硬拆双轴更准。
6.4 需要第三条轴的时候怎么办
先说结论:在我用过的 8.x 到 11.x 版本里,Time series 面板能稳定挂上去的 Y 轴就是左、右两条,Overrides 里 Axis 的 Placement 选项就是那几个。10.x 之后部分版本在面板选项的 Axis 区域提供了增加轴的入口,如果你在界面上看到了 Add axis 之类的按钮,可以试着加,加完之后 Overrides 里会出现指向具体轴的选项。但这属于版本特性,你手上是什么版本得自己确认,别照着某个特定版本的截图硬找。
在只有两条轴的前提下,需要第三条轴时有三个办法。第一,把可换算的指标统一到同一轴,比如所有延迟类都换算成毫秒放右轴,只给流量留左轴。第二,做归一化,比如把三个指标都换算成"占峰值的百分比",三条线都放左轴,看相对趋势。第三,也是最推荐的,拆面板。用 Row 把三个面板折在同一个折叠行里,共享时间范围,鼠标在任一面板上框选时间区间,其他面板会同步缩放,体验其实比挤在一张图上更好。
我做过一个折中方案:主图用双轴放最核心的两个指标,剩下的指标放到下方一个高度只有主图三分之一的小面板里,单位统一、只画线不画填充。这样既保留了主图的清晰度,又不丢信息。
7. 双轴不出、曲线贴底、缩放错乱的排查手册
7.1 右轴根本没出现
按这个顺序查。第一,看 Overrides 里到底有没有一条 Axis Placement = Right 的规则,很多人以为自己加了,其实加的是别的属性。第二,看这条规则的匹配器指向的字段名,和图上实际显示的字段名是否完全一致,包括空格和大小写,中文名也算。第三,看这条规则是不是被后面的另一条规则覆盖了,Overrides 是有顺序的,后匹配的会盖住先匹配的,我遇到过一条宽泛的 byRegexp 把所有字段都设成了左轴,把前面精心配的右轴规则全压掉了。第四,如果用的是 Graph 老面板,确认 Axes 标签页里右 Y 轴的 Show 有没有勾上。
7.2 曲线被压成一条直线
右轴出现了但曲线贴底,通常是单位或缩放范围的问题。如果左轴是 0 到 3000 的范围、右轴自动算出来也是 0 到 3000,那右轴的延迟数据(几十到几百)自然就贴底了。给右轴设 Soft max,或者把 Scale 切成对数,都能解决。还有一种情况是数据源返回的数值单位和你以为的不一样,Prometheus 的 seconds_bucket 分位数是秒,你按毫秒理解,数值就会小三个数量级,曲线自然贴底——这种情况不是配置问题,是量纲认知问题,去查询里乘 1000 就行。
7.3 改完 Override 图没变
这是最让人抓狂的一类。原因通常有三个。一是面板没刷新,Time series 面板的配置改完需要点 Apply 或者说右上角的刷新,某些版本里有短暂的渲染缓存。二是你改的 Override 匹配到了零个字段,界面上不会有任何提示,规则就那么挂着。三是有多个同名的仪表盘或者同一面板被复制过,你在编辑 A,看的是 B。最后这个我真实踩过,排查了二十分钟才发现看的不是同一个面板。
7.4 一段可复用的排查顺序
| 步骤 | 动作 | 预期结果 |
|---|---|---|
| 1 | 打开 Panel JSON,搜 overrides | 确认右轴规则存在且 id 正确 |
| 2 | 检查 matcher 匹配器的 id 和 options | 与图上字段名或查询编号对齐 |
| 3 | 检查 unit 和 min/max 属性的层级 | 属性挂在正确的 Override 下 |
| 4 | 临时删掉其他 Override | 排除规则互相覆盖 |
| 5 | 检查查询的 Legend format | 字段名是否稳定可预测 |
| 6 | 检查数据源 UID 和查询是否正常返回 | 查询报错则后面全部无效 |
| 7 | 换个面板类型验证(Graph old) | 排除面板类型差异 |
这套顺序我是按"从配置到数据"的方向排的,因为实际排查中最浪费时间的是先怀疑数据源、后怀疑配置,结果绕了一大圈。先看 JSON 这个动作看起来笨,但信息密度最高,一分钟能排除掉一大半可能性。
最后分享一个我自己养成的小习惯:每配好一个双轴面板,就把它的 Panel JSON 复制一份存到项目文档里,附上当时用的 Grafana 版本号和字段名说明。这么做一开始觉得多余,直到有一次集群重建、仪表盘全丢,靠这些存档十分钟就把核心面板全恢复了,从那以后我就没断过这个习惯。