如何在普罗米修斯中优雅地避免被零除

Yoo*_* N. 6 prometheus

有时您需要将一个指标除以另一个指标.

例如,我想像这样计算平均延迟:

rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
/
rate({__name__="hystrix_command_latency_total_seconds_count"}[60s])
Run Code Online (Sandbox Code Playgroud)

如果在指定的时间段内没有活动rate(),则分隔符中的内容将变为0分割结果NaN.如果我做了,结果(一些聚集avg()sum()或其他),整个聚合结果变成NaN.

所以我在divider中添加了一个零检查:

rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
/
(rate({__name__="hystrix_command_latency_total_seconds_count"}[60s]) > 0)
Run Code Online (Sandbox Code Playgroud)

NaN将从结果向量中删除s.并且撕掉图表上的线条以撕碎.

让我们用0值标记不活动时段,使图表再次连续:

rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
/
(rate({__name__="hystrix_command_latency_total_seconds_count"}[60s]) > 0)
or
rate({__name__="hystrix_command_latency_total_seconds_count"}[60s]) > bool 0
Run Code Online (Sandbox Code Playgroud)

这有效地替换了NaNs 0,图形是连续的,聚合工作正常.

但结果查询有点麻烦,尤其是当您需要进行更多标签过滤并对结果进行一些聚合时.像这样的东西:

avg(
    1000 * increase({__name__=~".*_hystrix_command_latency_total_seconds_sum", command_group=~"$commandGroup", command_name=~"$commandName", job=~"$service", instance=~"$instance"}[60s])
    /
    (increase({__name__=~".*_hystrix_command_latency_total_seconds_count", command_group=~"$commandGroup", command_name=~"$commandName", job=~"$service", instance=~"$instance"}[60s]) > 0)
    or
    increase({__name__=~".*_hystrix_command_latency_total_seconds_count", command_group=~"$commandGroup", command_name=~"$commandName", job=~"$service", instance=~"$instance"}[60s]) > bool 0
) by (command_group, command_name)
Run Code Online (Sandbox Code Playgroud)

长话短说:有没有更简单的方法来处理分频器中的零?或者任何常见做法?

bri*_*zil 10

如果在指定时间段内没有活动,除法器中的rate()将变为0,除法结果将变为NaN。

这是正确的行为,NaN 就是您想要的结果。

聚合工作正常。

您无法汇总比率。您需要分别聚合分子和分母,然后进行除法。

所以:

   sum by (command_group, command_name)(rate(hystrix_command_latency_total_seconds_sum[5m]))
  /
   sum by (command_group, command_name)(rate(hystrix_command_latency_total_seconds_count[5m]))
Run Code Online (Sandbox Code Playgroud)


eve*_*zon 5

最后我对我的具体问题有了一个解决方案:

除以零会导致 NaN 显示 - 作为技术结果来说这很好并且是正确的,但不是用户想要看到的(不满足业务要求)。

所以我搜索了一下,在grafana社区找到了我的问题的“解决方案”:

用 包围您有问题的值max(YOUR_PROLEMATIC_QUERY, or vector(-1))。然后,附加值映射会产生有用的输出。

(当然,您必须根据您的问题调整解决方案...最小/最大...向量(42)/向量(101)/向量(...))

更新(1)

好的。然而。根据查询,这似乎有点棘手。例如,我有另一个查询因除以零而失败并显示 NaN。上述解决方案不起作用。我必须用括号将查询括起来并添加 > 0 or on() vector(100).