You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

计算错误率比值时返回空结果的PromQL/Thanos问题排查

问题排查与解决:PromQL返回空结果(legacy客户端部分状态码错误率为0)

问题根源

PromQL里如果除法的分母是0,会直接丢掉这条时间序列,不会返回NaN或者其他值。当legacy客户端的400状态码错误率为0时,计算v1/v2和它的比值时,这个状态码+版本的组合就被过滤了;要是所有要计算的组合都有分母为0的情况,就会直接返回Empty query result。

先排查确认

  • 先单独验证各客户端各状态码的错误率是否正确,跑这几个查询:

    # legacy各状态码错误率
    sum by (status) (rate(http_response{version="legacy", status=~"4..|5.."}[5m])) 
      / 
    sum by (status) (rate(http_response{version="legacy"}[5m]))
    
    # v1各状态码错误率
    sum by (status) (rate(http_response{version="v1", status=~"4..|5.."}[5m])) 
      / 
    sum by (status) (rate(http_response{version="v1"}[5m]))
    
    # v2各状态码错误率
    sum by (status) (rate(http_response{version="v2", status=~"4..|5.."}[5m])) 
      / 
    sum by (status) (rate(http_response{version="v2"}[5m]))
    

    重点看legacy的400状态码是不是真的为0,同时确认401、503这些状态码有没有非0值。

  • 检查你原来的比值查询是不是没处理分母为0的情况,比如这种写法就会出问题:

    # 错误示例:没处理分母为0的情况
    sum by (version, status) (rate(http_response{version=~"v1|v2", status=~"4..|5.."}[5m])) / sum by (version, status) (rate(http_response{version=~"v1|v2"}[5m]))
      /
    sum by (status) (rate(http_response{version="legacy", status=~"4..|5.."}[5m])) / sum by (status) (rate(http_response{version="legacy"}[5m]))
    

    这种写法遇到legacy某状态码错误率为0时,直接就把这个组合过滤掉了。

解决办法

办法1:处理分母为0的情况,同时对齐标签

用or vector(0)把分母为0的情况转成0(或者你想要的默认值),还要确保标签对齐:

# 计算v1/v2和legacy的错误率比值,处理分母为0
(
  sum by (version, status) (rate(http_response{version=~"v1|v2", status=~"4..|5.."}[5m])) 
  / 
  sum by (version, status) (rate(http_response{version=~"v1|v2"}[5m]))
)
/
(
  sum by (status) (rate(http_response{version="legacy", status=~"4..|5.."}[5m])) 
  / 
  sum by (status) (rate(http_response{version="legacy"}[5m]))
  or vector(0)  # 把legacy错误率为0的情况转成0,避免被过滤
)
on(status) group_left(version)  # 按status对齐标签,保留v1/v2的version标签

要是你希望分母为0时显示极大值(比如表示v1/v2错误率相对legacy无限大),可以把or vector(0)换成or vector(1e-10),这样既不会除以0,又能保留这条序列。

办法2:直接过滤掉legacy错误率为0的组合

如果不需要计算legacy错误率为0的状态码,那就先把这些组合过滤掉:

# 只计算legacy错误率大于0的状态码比值
(
  sum by (version, status) (rate(http_response{version=~"v1|v2", status=~"4..|5.."}[5m])) 
  / 
  sum by (version, status) (rate(http_response{version=~"v1|v2"}[5m]))
)
/
(
  sum by (status) (rate(http_response{version="legacy", status=~"4..|5.."}[5m])) 
  / 
  sum by (status) (rate(http_response{version="legacy"}[5m]))
)
on(status) group_left(version)
and
sum by (status) (rate(http_response{version="legacy", status=~"4..|5.."}[5m])) > 0

这样只会返回legacy错误率大于0的状态码和v1/v2的比值。

办法3:用clamp_min()给分母设最小值

用clamp_min()确保分母不会是0,给它一个极小值:

(
  sum by (version, status) (rate(http_response{version=~"v1|v2", status=~"4..|5.."}[5m])) 
  / 
  sum by (version, status) (rate(http_response{version=~"v1|v2"}[5m]))
)
/
clamp_min(
  sum by (status) (rate(http_response{version="legacy", status=~"4..|5.."}[5m])) 
  / 
  sum by (status) (rate(http_response{version="legacy"}[5m])),
  1e-10  # 设置极小值,避免除以0
)
on(status) group_left(version)

验证修改

跑修改后的查询后,检查结果:

  • 对于legacy错误率为0的状态码,用办法1的话会返回NaN(如果用or vector(0))或者极大值(如果用or vector(1e-10));
  • 对于401、503这些legacy错误率非0的状态码,应该能正常显示比值。

内容的提问来源于stack exchange,提问作者c0tonet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 06:31:12