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