子查询支持

简介

正如标题所示,子查询是一个查询的一部分,允许你在一个查询中执行范围查询,这在以前是不可能的。这是一个长期存在的功能请求:prometheus/prometheus/1227

用于子查询支持的pull request最近已合并到 Prometheus 中,将在 Prometheus 2.7 中可用。让我们在下面了解更多信息。

动机

有时,在某些情况下,你希望使用较低分辨率/范围(例如 5m)的 rate 来发现问题,同时为更高的范围(例如 1hmax_over_time)聚合此数据。

以前,上述操作对于单个 PromQL 查询是不可能的。如果你想在查询中进行范围选择以用于警报规则或绘图,则需要基于该查询制定记录规则,并在记录规则创建的指标上执行范围选择。示例:max_over_time(rate(my_counter_total[5m])[1h])

当你想要获得跨越数天或数周的数据的快速结果时,可能需要等待很长时间,直到你的记录规则中有足够的数据才能使用。忘记添加记录规则可能会令人沮丧。为查询的每个步骤创建记录规则将是乏味的。

通过子查询支持,所有等待和挫败感都得到了解决。

子查询

子查询类似于 /api/v1/query_range API 调用,但嵌入在即时查询中。子查询的结果是一个范围向量。

Prometheus 团队在慕尼黑举行的 2018 年 Prometheus 开发峰会上就子查询的语法达成共识。这些是关于峰会关于子查询支持的笔记,以及用于实现子查询支持的语法的简要设计文档

<instant_query> '[' <range> ':' [ <resolution> ] ']' [ offset <duration> ]
  • <instant_query> 等同于 /query_range API 中的 query 字段。
  • <range>offset <duration> 类似于范围选择器。
  • <resolution> 是可选的,它等同于 /query_range API 中的 step

当未指定分辨率时,全局评估间隔将作为子查询的默认分辨率。此外,子查询的步长是独立对齐的,并且不依赖于父查询的评估时间。

示例

min_over_time 函数内部的子查询以 1 分钟的分辨率返回过去 30 分钟内 http_requests_total 指标的 5 分钟速率。这等同于使用 query=rate(http_requests_total[5m]), end=<now>, start=<now>-30m, step=1m/query_range API 调用,并取所有接收值的最小值。

min_over_time( rate(http_requests_total[5m])[30m:1m] )

分解

  • rate(http_requests_total[5m])[30m:1m] 是子查询,其中 rate(http_requests_total[5m]) 是要执行的查询。
  • rate(http_requests_total[5m])start=<now>-30mend=<now> 执行,分辨率为 1m。请注意,start 时间与 1m 的步长独立对齐(对齐的步长为 0m 1m 2m 3m ...)。
  • 最后,上述所有评估的结果都传递给 min_over_time()

下面是一个嵌套子查询的示例,以及默认分辨率的用法。最内层的子查询获取 distance_covered_meters_total 在一段时间范围内的速率。我们使用它来获取速率的 deriv(),同样是在一段时间范围内。最后取所有导数的最大值。请注意,最内层子查询的 <now> 时间是相对于 deriv() 上的外部子查询的评估时间而言的。

max_over_time( deriv( rate(distance_covered_meters_total[1m])[5m:1m] )[10m:] )

在大多数情况下,你将需要默认评估间隔,这是默认情况下规则被评估的间隔。自定义分辨率在你想减少/增加计算频率的情况下会很有帮助,例如,你可能希望减少计算频率的昂贵查询。

结语

虽然子查询非常方便地用于替代记录规则,但不必要地使用它们会产生性能影响。繁重的子查询最终应转换为记录规则以提高效率。

也不建议在记录规则内部使用子查询。如果你确实需要在记录规则中使用子查询,则应创建更多记录规则。