介绍“@”修饰符

2021年2月18日作者 Ganesh Vernekar

你是否曾为某项指标选择前10个时间序列,但结果却得到100个而不是10个?如果是,那这篇文章就是为你准备的。让我为你深入讲解其根本问题以及我是如何解决的。

当前,topk() 查询仅作为即时查询(instant query)时才有意义,在这种情况下你会获得恰好 k 个结果。但当你将其作为范围查询(range query)运行时,由于每一步都是独立评估的,你可能会得到远超 k 个结果。这个 @ 修饰符允许你为范围查询中的所有步骤固定排名。

在 Prometheus v2.25.0 中,我们引入了一个新的 PromQL 修饰符 @。类似于 offset 修饰符允许你根据评估时间以固定持续时间偏移向量选择器(vector selector)、范围向量选择器(range vector selector)和子查询(subqueries)的评估,@ 修饰符则允许你固定这些选择器的评估,而与查询评估时间无关。此语法的功劳归于 Björn Rabenstein 

<vector-selector> @ <timestamp>
<range-vector-selector> @ <timestamp>
<subquery> @ <timestamp>

<timestamp> 是一个 Unix 时间戳,并用浮点文字表示。

例如,查询 http_requests_total @ 1609746000 返回 http_requests_total2021-01-04T07:40:00+00:00 的值。查询 rate(http_requests_total[5m] @ 1609746000) 返回 http_requests_total 在同一时间点的5分钟速率。

此外,start()end() 也可以作为特殊值用于 @ 修饰符。对于范围查询,它们分别解析为范围查询的开始和结束时间,并在所有步骤中保持不变。对于即时查询,start()end() 都解析为评估时间。

回到 topk() 的修复,以下查询绘制了 http_requests_total 中过去 1h 速率排名前5的时间序列的 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 来启用。了解更多关于特性标志的信息,请参阅 这篇博文@ 修饰符的文档请查阅 此处