基础
Prometheus 提供了一种功能查询语言,称为 PromQL(Prometheus Querying Language),允许用户实时选择和聚合时间序列数据。
当你向 Prometheus 发送查询请求时,它可以是瞬时查询(在某一时间点评估)或范围查询(在从开始到结束时间的等间隔步长中多次运行)。PromQL 在这两种情况下的使用方法完全相同;范围查询只是在不同的时间戳上多次运行的瞬时查询。
在 Prometheus 的 UI 中,“Table”用于瞬时查询,“Graph”用于范围查询。
其他程序可以通过 HTTP API 获取 PromQL 表达式的结果。
示例
此文档是 Prometheus 基本语言参考文档。对于初学者而言,从一些示例开始学习可能更容易。
表达式语言数据类型
在 Prometheus 的表达式语言中,表达式或子表达式可以评估为四种类型之一:
- 瞬时向量 - 包含每个时间序列的单个样本的时间序列集,所有样本共享相同的时间戳
- 范围向量 - 每个时间序列包含随时间变化的数据点范围的时间序列集
- 标量 - 简单的浮点数值
- 字符串 - 简单的字符串值;当前未使用
根据使用场景(例如绘图与显示表达式输出)的不同,用户指定的表达式结果只能是这四种类型中的某些类型。例如,返回瞬时向量的表达式是唯一可以绘图的类型。
关于实验性原生 Histogram(native histogram):
- 必须启用特性标志后才能消费原生 Histogram。
- 一旦将原生 Histogram消费到 TSDB 中(即使之后再次禁用特性标志),范围向量和瞬时向量现在可能包含不是简单浮点数(浮点样本)而是完整的 Histogram 样本。向量可能时包含浮点数样本和 Histogram 样本的混合。
字面量
字符串字面量
字符串字面量由单引号、双引号或反引号指定。
PromQL 遵循 Go 转义规则。对于单引号或双引号指定的字符串字面量,一个反斜杠开始一个转义序列,后面可能跟a
、b
、f
、n
、r
、t
、v
或\
。 使用八进制(\nnn
)或十六进制(\xnn
、\unnnn
和 \Unnnnnnnn
)表示法可以提供特定字符。
相反,在由反引号指定的字符串字面量中,不会解析转义字符。值得注意的是,与 Go 不同,Prometheus 不会丢弃反引号内部的新行。
示例:
浮点字面量
标量浮点值可以用整数或浮点数格式(仅为了更好的可读性而包括空格)编写:
示例:
从版本 2.54 开始,浮点字面量也可以使用时间间隔语法表示,其中时间间隔转换为与代表的秒数对应的浮点值。这是一个实验性功能,可能会有所更改。
示例:
时间序列选择器
时间序列选择器负责选择时间序列以及原始或推断的样本时间戳和值。
不要将时间序列选择器与可以执行时间序列选择器的即时和范围查询这些更高级别的概念相混淆。更高级别的即时查询将在一个时间点应用给定的选择器,但是范围查询将以常规步骤在最小和最大时间戳之间的多个不同时间应用选择器。
瞬时向量选择器
瞬时向量(instant vector)选择器允许选择一组时间序列,并在给定时间(时间点)为每个时间序列获取单个样本值。在最简单的形式下,只指定一个指标名称,这会得到包含所有具有此指标名称的时间序列的瞬时向量。
以下示例选择了具有http_requests_total
指标名称的所有时间序列:
可以通过附加由花括号包围的逗号分隔的标签匹配器列表来进一步筛选这些时间序列。
以下示例选择了具有http_requests_total
指标名称且job
标签设置为prometheus
和其group
标签设置为canary
的时间序列:
还可能对标签值进行负匹配,或者对标签值进行正则表达式匹配。存在以下标签匹配操作符:
=
:选择与提供的字符串完全相等的标签。!=
:选择与提供的字符串不相等的标签。=~
:选择与提供的字符串正则表达式匹配的标签。!~
:选择与提供的字符串不匹配正则表达式的标签。
正则表达式的匹配完全锚定。env=~"foo"
的匹配被视为env=~"^foo$"
。
例如,此示例选择了环境为staging
、testing
和development
的所有http_requests_total
时间序列以及除了GET
方法之外的 HTTP 方法。
匹配空标签值的标签匹配器也会选择所有没有设置特定标签的时间序列。对于同一标签名,可以有多个匹配器。
例如,给定以下数据集:
查询http_requests_total{environment=""
将匹配并返回:
而会排除:
可以为同一个标签名使用多个匹配器;它们必须都通过才能返回结果。
查询:
会选择以下序列:
矢量选择器要么指定名称,要么至少包含一个不匹配空字符串的标签匹配器。以下表达式非法:
相比之下,以下表达式有效,因为它们都具有不匹配空标签值的选择器。
标签匹配器还可以应用于指标名称,通过针对内部的__name__
标签匹配。例如,表达式http_requests_total
等同于{__name__="http_requests_total"}
。除了=
(!=
、=~
、!~
)之外的匹配器也可以使用。以下表达式选择名称以job:
开头的所有指标:
指标名称不能是关键字bool
、on
、ignoring
、group_left
和group_right
。以下表达式非法:
为此限制的一个变通方法是使用 __name__
标签:
Prometheus 中的所有正则表达式都使用 RE2语法。
范围向量选择器
范围向量(range vector)字面量的工作方式类似于瞬时向量字面量,但会为其每个结果范围向量元素从当前时间取回一段值。从语法上看,在范围向量选择器末尾附加一个由方括号包围的时间间隔([]
)以指定每个结果范围向量元素获取的值的时间段。该范围是一个闭区间,即边界处的样本仍然包含在选择中。
以下示例中,我们选择了过去 5 分钟内我们记录的所有值,所有具有http_requests_total
指标名称和job
标签设置为prometheus
的时间序列:
持续时间
持续时间以数字形式指定,紧随其后的是以下之一的单位:
ms
- 毫秒s
- 秒m
- 分钟h
- 小时d
- 天 - 假设一天总是有24小时w
- 周 - 假设一周总是有7天y
- 年 - 假设一年总是有365天1
1 对于年中的天数,跳过了闰日,相应地,对于分钟,则跳过了闰秒。
持续时间可以通过拼接进行组合。单位必须按照最长到最短的顺序排列。给定单位只能在一个持续时间中出现一次。
以下是一些有效的持续时间示例:
自版本 v2.54 起,持续时间也可以使用浮点字面量的语法表示,表示持续时间的秒数。这是一个实验性功能,未来可能还会更改。
示例:
偏移修饰符
offset
修饰符允许更改查询中单个即时和范围向量的时间偏移。
例如,以下表达式返回相对于当前查询评估时间的过去5分钟内的http_requests_total
值:
请注意,offset
修饰符始终需要紧跟选择器,因此以下操作是正确的:
而以下操作则是错误的:
offset
同样适用于范围向量。这返回一周前http_requests_total
的5分钟变化速率:
在查询过去的样本时,负偏移能够在时间上进行向前的比较:
请注意,这允许查询其评估时间之后的时间的数据。
@ 修饰符
@
修饰符允许更改查询中单个即时和范围向量的评估时间。提供给@
修饰符的时间需要是 Unix 时间戳,并用浮点字面量描述。
例如,以下表达式返回2021-01-04T07:40:00+00:00
时刻的http_requests_total
值:
请注意,@
修饰符始终需要紧跟选择器,因此以下操作是正确的:
而以下操作则是_错误_的:
@
同样适用于范围向量。这返回在2021-01-04T07:40:00+00:00
时刻的5分钟速率:
@
修饰符支持上述描述的所有数值字面量表示。它可以与offset
修饰符一起工作,其中偏移相对于@
修饰符时间应用。结果不受修饰符顺序的影响。
例如,这两个查询将产生相同的结果:
此外,start()
和end()
也可以作为@
修饰符的值使用作为特殊值。
对于范围查询,它们分别对应于查询范围的开始和结束,并对所有步骤保持不变。
对于即时查询,start()
和end()
都会被解析为评估时间。
请注意,@
修饰符允许查询查看其评估时间之后的时间。
子查询
子查询允许你为给定的范围和解析度运行即时查询。子查询的结果是一个范围向量。
语法:<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]
<resolution>
(解析度)是可选的。默认值是全局的评估间隔。
运算符
Prometheus 支持许多二进制和聚合运算符。这些在表达式语言运算符页面中有详细描述。
函数
Prometheus 支持几个函数来操作数据。这些在表达式语言函数页面中有详细描述。
注释
PromQL 支持以 #
开头的行注释。示例:
需要注意的陷阱
过时标记(Staleness)
在查询期间用于采样的时间戳独立于实际的时间序列数据。这是为了支持聚合(如sum
、avg
等)的情况而设计的,其中多个聚合的时间序列并不精确对齐。由于它们的独立性,Prometheus 需要在查找时间段内为每个相关时间序列分配一个值。默认情况下,该时间段为5分钟。
如果 Target 抓取或规则计算不再返回以前存在的时间序列的样本,则该时间序列将标记为stale
。如果 Target 被删除,之前检索的时间序列将在删除后不久标记为stale
。
如果查询在时间序列标记为stale
后的采样时间戳上进行评估,则不会返回该时间序列的值。如果随后为这个时间序列消费了新的样本,则它们将如预期那样返回。
当时间序列不再被导出(exported)或 Target 不存在时,时间序列将被标记为stale
。这样的时间序列将在最近收集的样本时消失,并且在标记为stale
后不会在查询中返回。
一些 Exporter 会在样本上放置自己的时间戳,这样会导致不同的行为:停止导出的时间序列在消失前会被置为5分钟(默认)的最后一个值。track_timestamps_staleness
配置项可以改变这一点。
避免缓慢查询和过载
如果查询需要处理大量数据,可能会导致绘图超时或服务器或浏览器过载。因此,在构建未知数据的查询时,你应该始终在 Prometheus 表达式浏览器的表格视图中构建查询,直到结果集看起来合理一些(最多只有几百个时间序列)。只有在已过滤或聚合了数据足够多之后,才建议切换到图形模式。如果表达式仍然无法在即时模式下快速绘图,那么可以通过记录规则来实现。
这尤其适用于 Prometheus 的查询语言,因为一个简单的指标名称选择器如api_http_requests_total
就有可能会扩展为数千个具有不同标签的时间序列。同时,请记住,聚合多个时间序列的表达式即使输出只有少量时间序列也会对服务器产生负载。这类似于在关系数据库中求一列所有值的总和,即使输出值只是一个数字,也会很慢。
该文档基于 Prometheus 官方文档翻译而成。