首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何优雅地避免普罗米修斯的零除法

如何优雅地避免普罗米修斯的零除法
EN

Stack Overflow用户
提问于 2017-11-01 13:55:45
回答 5查看 19.7K关注 0票数 22

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

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

代码语言:javascript
复制
rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
/
rate({__name__="hystrix_command_latency_total_seconds_count"}[60s])

如果在指定的时间段内没有活动,则除法器中的rate()变成0,除法的结果变成NaN。如果我对结果(avg()sum()或其他什么)进行一些聚合,则整个聚合结果将变成NaN

所以我在除法器中加了一个零的检查:

代码语言:javascript
复制
rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
/
(rate({__name__="hystrix_command_latency_total_seconds_count"}[60s]) > 0)

这将从结果向量中删除NaNs。把图表上的线撕成碎片。

让我们用0值标记不活动期,使图形再次连续:

代码语言:javascript
复制
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

这有效地取代了NaN0,图形是连续的,聚合工作正常。

但是产生的查询有点麻烦,特别是当您需要进行更多的标签过滤和对结果进行一些聚合时。就像这样:

代码语言:javascript
复制
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)

长话短说:有没有更简单的方法来处理除法器中的零?或者有什么常见的做法吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2017-11-01 14:05:36

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

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

聚合工作正常。

你不能把比率相加。您需要将分子和分母分别聚合起来,然后再进行除法。

所以:

代码语言:javascript
复制
   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]))
票数 9
EN

Stack Overflow用户

发布于 2020-06-15 14:00:44

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

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

于是我搜索了一下,并在grafana社区找到了一个解决我的问题的“解决方案”:

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

(当然,你必须适应你的问题.min/max..。向量(42)/vector(101)/vector(.))

更新(1)

好吧。然而。基于查询,它似乎要复杂一些。例如,我有另一个查询在NaN中失败,结果是退视率为零。以上解决方案不起作用。我不得不用括号包围查询,并添加了> 0 or on() vector(100)

票数 4
EN

Stack Overflow用户

发布于 2022-03-30 11:53:00

只需将> smallest_value添加到查询中,然后将其包装到聚合函数(如avg() )中,其中smallest_value是值,它小于内部查询的任何预期有效结果。例如:

代码语言:javascript
复制
avg((
  rate({__name__="hystrix_command_latency_total_seconds_sum"}[60s])
  /
  rate({__name__="hystrix_command_latency_total_seconds_count"}[60s])
) > -1e12)

当将NaN值与任何数字与>运算符比较时,Prometheus会删除它们。例如,NaN >bool -1e12。同样的情况也适用于<运算符,例如NaN <bool 1e12。因此,可以使用><来过滤NaN值,然后再用聚合函数聚合它们。

MetricsQL中不需要这个技巧,因为当聚合函数被应用到VictoriaMtrics时,VictoriaMtrics会自动跳过它们的NaN值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47056557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档