01 引言
Prometheus查询语法官方文档地址:https://prometheus.io/docs/prometheus/latest/querying/basics/
Prometheus提供了一种名为PromQL (Prometheus query language)
的函数式查询语言,允许用户实时选择和聚合时间序列数据,表达式的结果可以以图形的形式显示,通过HTTP API由外部系统使用。
在Prometheus页面,输入查询语句,可以看到类似于如下接界面:
Table | Graph |
接下来,详细讲解下Prometheus
的查询语法。
02 概念
2.1 表达式类型(Expression language data types)
在Prometheus
的表达语言中,一个表达式或子表达式可以总结为以下四种类型:
- 瞬时向量(
Instant vector
):一组时间序列,包含每个时间序列的单一样本,所有共享相同的时间戳; - 范围向量(
Range vector
):一组时间序列,包含每个时间序列在一段时间内的数据点范围; - 标量(
Scalar
):一个简单的数字浮点值; - 字符串(
String
):一个简单的字符串值(目前未使用);
2.2 字面量(Literals)
2.2.1 String 字面量(String literals)
字符串可以指定为单引号、双引号或反引号中的文字。
PromQL
遵循与Go相同的转义规则。在单引号或双引号中,反斜杠开始转义序列,转义序列后面可以是a、b、f、n、r、t、v
或\
。可以使用八进制(\nnn
)或十六进制(\xnn, \unnnn和\ unnnnnn
)提供特定字符。
反引号内不处理转义,与Go
不同,Prometheus
不会在反引号内丢弃换行符。
例子:
"this is a string" 'these are unescaped: \n \\ \t' `these are not unescaped: \n ' " \t`
2.2.2 Float 字面量(Float literals)
标量浮点值可以写成文字整型数或浮点数格式(仅包含空格以提高可读性):
[-+]?( [0-9]*\.?[0-9]+([eE][-+]?[0-9]+)? | 0[xX][0-9a-fA-F]+ | [nN][aA][nN] | [iI][nN][fF] )
举例:
23 -2.43 3.4e-9 0x8f -Inf NaN
2.3 时间序列选择器(Time series Selectors)
2.3.1 瞬时向量选择器(Instant vector selectors)
瞬时向量选择器:允许在给定的时间戳(即时)上选择一组时间序列和每个序列的单个样本值,在最简单的形式中,只指定一个度量名称。这将产生一个包含所有具有此度量名称的时间序列元素的即时向量。
这个例子选择了所有带有http_requests_total
度量名称的时间序列:
http_requests_total
通过在花括号({}
)中添加逗号分隔的标签匹配器列表,可以进一步过滤这些时间序列。
举例:只选择那些带有http_requests_total
度量名称的时间序列,并且作业标签设置为prometheus
,它们的组标签设置为canary
:
http_requests_total{job="prometheus",group="canary"} • 1
也可以对标签值进行负匹配,或者将标签值与正则表达式进行匹配,存在以下标签匹配操作符:
=
: 选择与提供的字符串完全相等的标签;!=
: 选择与提供的字符串不相等的标签;=~
: 选择正则表达式与提供的字符串匹配的标签;!~
: 选择与提供的字符串不匹配的标签;
正则表达式匹配是完全对应的,匹配env=~"foo"
被视为env=~"^foo$"
。
举例:这将为staging、testing和development
环境以及除GET
之外的HTTP
方法选择所有http_requests_total
时间序列:
http_requests_total{environment=~"staging|testing|development",method!="GET"}
注意:向量选择器必须指定一个名称或至少一个与空字符串不匹配的标签匹配器,下面的表达式是非法的:
{job=~".*"} # Bad!
相反,这些表达式是有效的,因为它们都有一个不匹配空标签值的选择器:
{job=~".+"} # Good! {job=~".*",method="get"} # Good!
通过与内部的__name__
标签进行匹配,标签匹配器也可以应用于度量名称。例如,表达式http_requests_total
等价于{__name__="http_requests_total"}
,除= (!=, =~, !~)
也可以使用,以下表达式选择名称以job
开头的所有指标:
{__name__=~"job:.*"}
指标名不能是关键字bool, on, ignoring, group_left
和group_right
中的一个。下面的表达式是非法的:
on{} # Bad!
解决这个限制的方法是使用__name__
标签:
{__name__="on"} # Good!
Prometheus中的所有正则表达式都使用 RE2语法。
2.3.2 范量向量选择器(Range Vector Selectors)
范量标量:工作方式类似于瞬时向量,只是它们选择了从当前瞬间返回的一个样本范围。
从语法上讲,时间持续时间被附加在向量选择器末尾的方括号([]
)中,以指定应该为每个结果范围向量元素提取到多远的时间值。
举例:选择在过去5分钟内记录的所有时间序列的值,这些时间序列的度量名称为http_requests_total
,作业标签设置为prometheus
:
http_requests_total{job="prometheus"}[5m] • 1
2.3.3 持续时间(Time Durations)
时间持续时间指定为一个数字,后面紧跟着下列的其中一个单位:
ms
:毫秒s
:秒m
: 分钟h
: 小时d
: 天(一天24小时)w
: 周(一周7天)
-y
:年(一年365天)
时间持续时间可以进行串联组合(注意:单位必须从最长到最短订购,一个给定的单位在一段时间内只能出现一次),举例:
5h 1h30m 5m 10s
2.3.4 Offset修饰符(Offset modifier)
offset
修饰符:允许在查询中更改单个瞬间和范围向量的时间偏移量。
举例:以下表达式返回相对于当前查询评估时间过去5分钟的http_requests_total
的值:
http_requests_total offset 5m
注意:offset修饰符
必须跟在选择器后面,即:
sum(http_requests_total{method="GET"} offset 5m) // GOOD.
如果这样是错误的:
sum(http_requests_total{method="GET"}) offset 5m // INVALID.
对于范围向量也是一样的,下面例子将返回http_requests_total
一周前的5分钟速率:
rate(http_requests_total[5m] offset 1w)
对于时间上向前移动的比较,可以指定负偏移量:
rate(http_requests_total[5m] offset -1w)
2.3.5 @ modifier
@修饰符:允许在查询中改变单个瞬间向量和范围向量的计算时间,提供给@修饰符的时间是一个unix
时间戳,用浮点文字描述。
例如,以下表达式返回http_requests_total
在2021-01-04T07:40:00+00:00
的值:
http_requests_total @ 1609746000
注意,@修饰符必须跟在选择器后面,举例:
sum(http_requests_total{method="GET"} @ 1609746000) // GOOD.
以下是错误写法:
sum(http_requests_total{method="GET"}) @ 1609746000 // INVALID.
对于范围向量也是一样的,下面表达式将返回http_requests_total
在2021-01-04T07:40:00+00:00
处的5分钟速率:
rate(http_requests_total[5m] @ 1609746000)
@修饰符在int64
范围内支持上述浮点数字面量的所有表示。它还可以与offset修饰符一起使用,offset
是相对于**@修饰符**时间应用的,而不管哪个修饰符先写,这两个查询将产生相同的结果。
# offset after @ http_requests_total @ 1609746000 offset 5m # offset before @ http_requests_total offset 5m @ 1609746000
另外,start()
和end()
也可以作为**@修饰符**的特殊值使用,对于范围查询,它们分别解析到范围查询的开始和结束,并对所有步骤保持相同,对于即时查询,start()和end()都解析为计算时间。
http_requests_total @ start() rate(http_requests_total[5m] @ end())
注意,@修饰符允许查询提前查看其计算时间。
2.4 子查询(Subquery)
子查询允许您对给定的范围即时查询,子查询的结果是一个范围向量。
语法:
<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]
<resolution>
:是可选的,默认是全局计算间隔。
2.5 操作符(Operators)
Prometheus
支持许多二进制和聚合操作符,详情参考:https://prometheus.io/docs/prometheus/latest/querying/operators/
2.5.1 二元作符(Binary operators)
Prometheus
的查询语言支持基本的逻辑和算术运算符。对于两个瞬时向量之间的运算,可以修改匹配行为。
2.5.1.1 算术二元操作符(Arithmetic binary operators)
在Prometheus
中存在以下二进制算术运算符:
+
:(加)-
:(减)*
:(乘)
-/
:(除)%
:(取余)^
:(求幂)
二进制算术运算符定义在标量/标量、向量/标量和向量/向量值对之间:
- 两个标量之间的行为很明显:它们计算另一个标量,这个标量是应用于两个标量操作数的运算符的结果。
- 在瞬时向量和标量之间,将运算符应用于向量中每个数据样本的值。例如,如果一个时间序列瞬间向量乘以2,结果是另一个向量,其中原始向量的每个样本值乘以2,指标名称被删除。
- 在两个瞬时向量之间:对左边向量中的每一个元素以及右边向量中与其匹配的元素应用一个二元算术运算符。结果被传播到结果向量,分组标签成为输出标签集。指标名称被删除。右边向量中找不到匹配项的项不属于结果的一部分。
2.5.1.2 三角二元操作符符(Trigonometric binary operators)
以下是在弧度上工作的三角二元运算符,在普罗米修斯中存在:
- atan2(基于https://pkg.go.dev/math#Atan2)
三角运算符允许使用向量匹配对两个向量执行三角函数,这在普通函数中是不可用的。它们的作用与算术运算符相同。
2.5.1.3 比较二元操作符(Comparison binary operators)
比较二元操作符有如下:
- == (等于)
- != (不等于)
(大于)
- < (小于)
= (大于等于)
- <= (小于等于)