遇到问题
最近在开发项目时遇到这么一个需求,需要提供一个展示某类网络产品过去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]
| metrics | time 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返回一个scalar, avg_over_time返回instant vector
关于
scalar和instant 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
这里截取一段简单的说明示例:

2737

被折叠的 条评论
为什么被折叠?



