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

Prometheus 普罗米修斯如何优雅地避免被零除,prometheus,Prometheus,有时需要将一个度量除以另一个度量 例如,我想计算这样的平均延迟: rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s]) / rate({__name__="hystrix_command_latency_total_seconds_count"}[60s]) avg( 1000 * increase({__name__=~".*_hystrix_command_latency_total_seconds_su

有时需要将一个度量除以另一个度量

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

rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
/
rate({__name__="hystrix_command_latency_total_seconds_count"}[60s])
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)
如果在指定的时间段内没有活动,则除法器中的
rate()
变为
0
,除法结果变为
NaN
。 如果我对结果进行一些聚合(
avg()
sum()
或其他什么),整个聚合结果将变成
NaN

因此,我在除法器中添加了一个零检查:

rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
/
(rate({__name__="hystrix_command_latency_total_seconds_count"}[60s]) > 0)
这将从结果向量中删除
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
这有效地将
NaN
s替换为
0
,图形是连续的,聚合工作正常

但结果查询有点麻烦,尤其是当您需要对结果进行更多的标签过滤和聚合时。诸如此类:

rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
/
rate({__name__="hystrix_command_latency_total_seconds_count"}[60s])
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)
长话短说:有没有更简单的方法来处理除法器中的零?还是有什么常见的做法

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

这是正确的行为,NaN是你想要的结果

聚合工作正常

你不能合计比率。您需要分别聚合分子和分母,然后进行除法

因此:


最后,我为我的具体问题找到了一个解决方案:

零偏差导致NaN显示——这是技术结果,正确,但不是用户希望看到的(不满足业务要求)

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

max(PROLEMATIC\u查询或向量(-1))
包围有问题的值。然后,一个附加值映射将产生一个有用的输出

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

更新(1)


好的。然而。基于查询,这似乎有点棘手。例如,我有另一个查询,由于除法为零,NaN的查询失败。上述解决方案不起作用。我不得不用括号括住查询,并根据@eventhorizen的答案添加了
>0或on()vector(100)

,如果您将查询作为分母,有时可能返回零,那么它可能会弄乱图形,并在没有数据的情况下显示无穷大,您可以将结果限制在有效范围内

例如,该度量的输出应介于0和1之间,但在没有数据时也会产生无穷大:

(1/增加(有时为零查询[1m])

在本例中,您可以编写此代码,因此它显示的是
0
,而不是大于
100
的值:


max((1/增加(有时是零查询[1m])谢谢!我明白你的意思了。实际上,我希望我忽略了像
ifNaN(,默认值\u标量)这样的东西
替换向量中所有的
NaN
s,或者某种语言构造以这种方式运行,有人会告诉我。您的变体看起来很好,但仍然需要像
sum(…)/(sum(…)>0)或sum(…)>bool 0那样编写,以防除法器中的和因特定原因变为0(command_group,command_name)标签组合。此处不应使用
>0进行筛选,因为它会导致时间序列中缺少样本。NaN是正确的结果,因为这是除以0得到的结果。“它会导致缺少样本”--这就是我添加
或总和(…)>bool 0
查询的一部分,用零来填补空白,表示一些适合我的默认值。不过,这些时间段的延迟不是0,而是NaN。