Prometheus ‘@’ 修饰符详解
概述
在 Prometheus 的监控查询语言 PromQL 中,@ 修饰符是一个强大的新特性(自 v2.25.0 引入),它允许查询在特定的、固定的时间点进行计算,而非默认的查询评估时间。这对于解决范围查询(Range Query)中某些聚合函数(如 topk())返回结果数量不确定的问题至关重要。在 SRE 实践中,稳定、可预测的监控查询是分析性能趋势、定位问题和建立可靠 SLI(服务级别指标)的基础。@ 修饰符使得对历史数据进行定点分析和比较变得更加直接和可靠。
核心概念
@ 修饰符的核心作用是将 PromQL 选择器(vector selector、range vector selector 和 subquery)的评估时间固定在一个指定的 Unix 时间戳(float literal)上。这与 offset 修饰符不同,后者是将评估时间相对于当前时间进行偏移。
其基本语法如下:
<vector-selector> @ <timestamp>
<range-vector-selector> @ <timestamp>
<subquery> @ <timestamp>
例如,查询 http_requests_total 在特定时间点 2021-01-04T07:40:00+00:00(Unix 时间戳 1609746000)的值:
http_requests_total @ 1609746000
此外,@ 修饰符还支持两个特殊值:start() 和 end()。
- 在范围查询中,
start()解析为查询范围的起始时间,end()解析为结束时间,并且在整个查询的所有步长(step)中保持不变。 - 在即时查询(Instant Query)中,
start()和end()均解析为当前的查询评估时间。
这组特性使得在复杂的范围查询中引用一致的时间点成为可能,从而解决了长期以来 topk() 等函数在范围查询中表现不稳定(结果数量可能超过 k)的痛点。
实践
@ 修饰符最典型的应用场景是固定范围查询中的排序逻辑。一个常见的需求是:在一段时间范围内,持续绘制那些在过去一小时内流量排名前五的服务的当前速率。
如果不使用 @ 修饰符,直接运行 topk(5, rate(http_requests_total[1h])) 作为范围查询,由于每个查询步长都独立计算 topk,最终图表中可能包含数十条甚至上百条时间线,失去了“Top 5”的意义。
使用 @ 修饰符,我们可以将排名逻辑固定在范围查询的结束时间点(end()):
rate(http_requests_total[1m])
and
topk(5, rate(http_requests_total[1h] @ end()))
查询解析:
topk(5, rate(http_requests_total[1h] @ end())):计算查询时间范围结束时,过去一小时的请求速率,并返回 Top 5 的时间序列标签集合。由于使用了@ end(),这个“Top 5 列表”在整个范围查询期间是固定不变的。rate(http_requests_total[1m]):计算每个时间点上,过去一分钟的请求速率。and操作符:返回上述两个结果集中标签集合匹配的条目。效果是:在每个时间点上,只绘制那些在查询结束时刻属于 Top 5 的服务的 1 分钟速率曲线。
这种模式可以推广到其他函数,例如使用 histogram_quantile() 固定分位数计算的时间点,或用 sum_over_time() 替换 rate()。
注意: @ 修饰符在 Prometheus v2.25.0 中是实验性特性,需要通过启动标志 --enable-feature=promql-at-modifier 手动启用。
SRE 要点
- 与可靠性的关联:
@修饰符极大地提升了监控查询的确定性与可解释性。在排查事件或进行容量规划时,SRE 可以精确地将分析锚定在某个特定的故障时间点(例如@ 1609746000),对当时各服务的流量、延迟、错误率进行横向对比,避免了因时间窗口滑动造成的混淆。这直接支持了快速、准确的事件响应。 - 最佳实践与反模式:
- 最佳实践:将
@修饰符与and、or等逻辑操作符结合,用于构建“基于某个基准时间的过滤器”或“排行榜”。这对于创建稳定、可重复的 Grafana 仪表板面板非常有用。 - 常见反模式:在需要动态反映“当前 Top N”的即时查询中滥用
@修饰符。此时直接使用不带@的查询更为合适。误用start()或end()可能导致查询结果与预期不符。
- 最佳实践:将
- 相关指标(SLI/SLO/SLA):在定义和监控复杂的 SLI 时,
@修饰符有助于创建更清晰的复合指标。例如,你可以定义一个 SLI,专门监控“过去 24 小时内平均延迟最高的 3 个 API 端点”的当前错误率。这为设定针对特定高风险服务的 SLO 提供了精确的数据基础。 - 可观测性:
@修饰符增强了对时间序列数据的探索能力。它使得对历史数据进行定点快照分析和跨时间点对比(如比较本周一与上周一同一时刻的性能)变得更加直观,丰富了可观测性的分析维度。