介绍 '@' 修饰符

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

目前,topk() 查询只在即时查询时才有意义,你可以得到恰好 k 个结果。但是,当你将其作为范围查询运行时,由于每一步都是独立评估的,你可能会得到远多于 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 返回 2021-01-04T07:40:00+00:00 时刻的 http_requests_total 的值。查询 rate(http_requests_total[5m] @ 1609746000) 返回同一时刻的 http_requests_total 的 5 分钟速率。

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

回到 topk() 的修复,以下查询绘制了那些最后 1h 速率在前 5 名的序列的 http_requests_total1m 速率。因此,现在即使作为范围查询,你也可以理解 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 启用。有关功能标志的更多信息,请参阅这篇博客文章,并在此处找到有关 @ 修饰符的文档。