“@”修饰符介绍
2021年2月18日作者 Ganesh Vernekar
你是否曾尝试为某个指标选择前10个时间序列,结果却得到了100个?如果是这样,这篇文章就是为你准备的。接下来,我将为你详细解释这个问题的根本原因以及我是如何修复它的。
目前,topk() 查询只在即时查询(instant query)中有意义,此时你能精确地得到 k 个结果。但当它作为范围查询(range query)运行时,你可能会得到远超 k 个的结果,因为每个时间步都是独立评估的。而这个 @ 修饰符可以让你在范围查询的所有时间步中固定排名。
在 Prometheus v2.25.0 中,我们引入了一个新的 PromQL 修饰符 @。类似于 offset 修饰符可以让你将向量选择器、范围向量选择器和子查询的评估时间相对于当前评估时间偏移一个固定的时长,@ 修饰符则可以让你固定这些选择器的评估时间,使其不受查询评估时间的影响。这个语法的功劳归于 Björn Rabenstein 。
<vector-selector> @ <timestamp>
<range-vector-selector> @ <timestamp>
<subquery> @ <timestamp>
<timestamp> 是一个 unix 时间戳,用浮点数字面量表示。
例如,查询 http_requests_total @ 1609746000 会返回 http_requests_total 在 2021-01-04T07:40:00+00:00 时的值。查询 rate(http_requests_total[5m] @ 1609746000) 会返回同一时间点 http_requests_total 的5分钟速率。
此外,start() 和 end() 也可以作为 @ 修饰符的特殊值使用。对于范围查询,它们分别解析为范围查询的开始和结束时间,并且在所有时间步中保持不变。对于即时查询,start() 和 end() 都解析为该查询的评估时间。
回到 topk() 的修复问题上,以下查询绘制了那些在过去1小时内速率排名前5的序列的 http_requests_total 的 1m 速率。因此,现在即使是范围查询,你也能理解 topk() 的意义,因为它会精确地绘制出 k 个结果。
rate(http_requests_total[1m]) # This acts like the actual selector.
and
topk(5, rate(http_requests_total[1h] @ end())) # This acts like a ranking function which filters the selector.
类似地,topk() 排名可以被其他函数替换,比如目前只在即时查询中有意义的 histogram_quantile()。rate() 可以被 <aggregation>_over_time() 等替换。欢迎告诉我们你是如何使用这个新修饰符的!
@ 修饰符默认是禁用的,可以通过 --enable-feature=promql-at-modifier 标志来启用。你可以在这篇博文中了解更多关于功能标志的信息,并在此处找到 @ 修饰符的文档。