avg vs avg_over_time (promql)

遇到问题

最近在开发项目时遇到这么一个需求,需要提供一个展示某类网络产品过去7天平均带宽数据。数据已经存在于vm集群了。于是乎便有了以下promql:

avg(np_traffic_in{provider="aliyun",product="nat",region="cn-beijing",instance_id="xxx"}[7d]}

但是发现结果对不上,查阅文档后发现avg 原来不是这么用的。这里引用一下官方文档的描述

在这里插入图片描述

二者区别

这内置函数是用于聚合single instant vector, 即某一时刻的时序向量。而上面则需要聚合range vector 即一段时间内的时序向量。stackoverlfow上也有相关问题讨论

在这里插入图片描述

示例

为了更直观一些,这里用一个查询示例解释一下。

当前时序:

prometheus_http_requests_total{code="200", handler=~"/api/v1/query_.*"}[1m]
metricstime series
prometheus_http_requests_total{code=“200”, handler=“/api/v1/query_exemplars”, instance=“localhost:9090”, job=“prometheus”}0 @1724643114.007
0 @1724643129.007
0 @1724643144.007
0 @1724643159.007
prometheus_http_requests_total{code=“200”, handler=“/api/v1/query_range”, instance=“localhost:9090”, job=“prometheus”}6 @1724643114.007
6 @1724643129.007
6 @1724643144.007
6 @1724643159.007

使用avg :

avg(prometheus_http_requests_total{code="200", handler=~"/api/v1/query_.+"})
---
element       value
{}              3

可以看到avg 是对{handler="/api/v1/query_exemplars"}{handler="/api/v1/query_range"} 最后一条时序值做平均运算,即(0+6)/2 = 3

使用avg_over_time:

avg_over_time(prometheus_http_requests_total{code="200", handler=~"/api/v1/query_.+"}[1m])
---
element                                     value
{handler="/api/v1/query_range"}               6
{handler="/api/v1/query_exemplars"}           0

可以看到avg_over_time 为每个metric时序单独计算了平均值。因为这段时间值未发生变化(prometheus 采集到的一直是0和6),因此最终平均值为0和6。

总结

总结一下, avg返回一个scalaravg_over_time返回instant vector

关于scalarinstant vector 说明可以参考官方文档

拓展

回到上面需求,不难发现用avg_over_time 就能解决问题。但是avg_over_time 函数无法使用 by/without等聚合参数。例如上面需求改为统计nat平均带宽就得换个写法了

sum(sum_over_time(np_traffic_in{provider="aliyun",product="nat",region="cn-beijing"}[7d])) without (instance_id) / sum(count_over_time(np_traffic_in{provider="aliyun",product="nat",region="cn-beijing"}[7d])) without (instance_id)

先对每个nat时序值求和,然后除以时序数量,最后得到nat平均带宽。

如果每个instance的时序数量都相同的话,也可以这么写

avg(avg_over_time(np_traffic_in{provider="aliyun",product="nat",region="cn-beijing"}[7d])) without (instance_id)

Note:

上面这段是计算序列平均值的平均值,只有在特定情况下可以这么使用。
因为大部分场景下平均值的平均值 != 平均值
具体可参考: https://math.stackexchange.com/questions/95909/why-is-an-average-of-an-average-usually-incorrect

这里截取一段简单的说明示例:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值