使用PromQL在Grafana生成桶计数热力图出现负值,求排查
Grafana热力图计算直方图桶增量出现负值的问题解决
背景数据
时间点t
raft_log_lag_count_bucket{type="applied_index",le="200"} 40 raft_log_lag_count_bucket{type="applied_index",le="205"} 64905 raft_log_lag_count_bucket{type="applied_index",le="210"} 119979
时间点t+1
raft_log_lag_count_bucket{type="applied_index",le="200"} 40 raft_log_lag_count_bucket{type="applied_index",le="205"} 67916 raft_log_lag_count_bucket{type="applied_index",le="210"} 125487
需求
计算t到t+1时间段内各le桶的新增计数(比如le="205"增量为67916-64905=3011),并在Grafana生成热力图:
- X轴为时间线
- Y轴范围0到无穷大
- 单元格(x,y)代表x时刻
le=y的桶的新增计数
遇到的问题
使用以下PromQL生成热力图时,Y轴出现大量负值:
sum(delta(raft_log_lag_count_bucket{type=~"applied_index"}[1m])) by (le)
问题原因
- delta不适配计数器类型指标:
raft_log_lag_count_bucket是累积直方图的桶,属于计数器类型(只会递增,可能因服务重启归零)。delta()仅计算时间区间首尾的差值,不会处理计数器重置场景——当服务重启后计数器归零,delta()会算出负值(比如从1000变为0,差值为-1000)。 - 累积直方图增量逻辑错误:你需要的是单个桶区间内的新增计数,但累积直方图的大
le桶数值包含了所有更小le桶的数值。直接用delta取累积桶的差值,得到的是累积增量而非单个区间的新增数,一旦出现计数器重置就会产生负值。
正确的PromQL写法
方案1:用increase处理计数器重置,计算区间增量
increase()专门用于计数器类型指标,会自动处理重置并返回非负值,再通过差值得到单个桶的新增计数:
sum(increase(raft_log_lag_count_bucket{type=~"applied_index"}[1m])) by (le) - ignoring(le) group_left sum(increase(raft_log_lag_count_bucket{type=~"applied_index"}[1m])) by (le) offset 1m
方案2:用rate转换为速率再计算区间增量
如果需要更平滑的结果,可先用rate得到每秒速率,再乘以时间区间长度(1m=60秒)得到区间增量:
sum(rate(raft_log_lag_count_bucket{type=~"applied_index"}[1m]) * 60) by (le) - ignoring(le) group_left sum(rate(raft_log_lag_count_bucket{type=~"applied_index"}[1m]) * 60) by (le) offset 1m
核心逻辑
两种方案都是通过当前桶的累积增量减去前一个更小桶的累积增量,得到单个区间的新增计数,同时用increase或rate避免计数器重置带来的负值。
内容的提问来源于stack exchange,提问作者calvin
相关产品推荐
相关产品推荐

