Prometheus 通过指标名称(metrics name)以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而 label 则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度 过滤,聚合,统计从而产生新的计算后的一条时间序列。PromQL 是 Prometheus 内置的数据查询语言,其提供对时间序列数据丰富的查询,聚合以及逻辑运算能力的支持。并且被广泛应用在 Prometheus 的日常应用当中,包括对数据查询、可视化、告警处理当中。
基本用法
查询时间序列
当 Prometheus 通过 Exporter 采集到相应的监控指标样本数据后,我们就可以通过 PromQL 对监控样本数据进行查询。当我们直接使用监控指标名称查询时,可以查询该指标下的所有时间序列。
prometheus_http_requests_total
等同于:
prometheus_http_requests_total{}
该表达式会返回指标名称为 prometheus_http_requests_total 的所有时间序列:
PromQL 还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。
-
PromQL支持使用 = 和 != 两种完全匹配模式:
- PromQL支持使用 = 和 != 两种完全匹配模式
- PromQL支持使用 = 和 != 两种完全匹配模式
例如,如果我们只需要查询所有prometheus_http_requests_total时间序列中满足标签instance 为localhost:9090 的时间 序列,则可以使用如下表达式:
prometheus_http_requests_total{instance="localhost:9090"}
反之使用 instance!=“localhost:9090” 则可以排除这些时间序列:
prometheus_http_requests_total{instance!="localhost:9090"}
-
PromQL还可以支持使用正则表达式作为匹配条件,多个表达式之间使用 | 进行分离:
- 使用 label=~regx 表示选择那些标签符合正则表达式定义的时间序列
- 反之使用 label!~regx 进行排除
如果想查询多个环节下的时间序列序列可以使用如下表达式:
prometheus_http_requests_total{environment=~"staging|testing|development",method!="GET "}
排除用法
prometheus_http_requests_total{environment!~"staging|testing|development",method!="GET "}
范围查询
直接通过类似于PromQL表达式httprequeststotal查询时间序列时,返回值中只会包含该时间序列中的最新的一个样本值,这样的返回结果我们称之为瞬时向量。而相应的这样的表达式称之为瞬时向量表达式。
而如果我们想过去一段时间范围内的样本数据时,我们则需要使用区间向量表达式。区间向量表达式和瞬时向量表达式之间的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器 [] 进行定义。 例如,通过以下表达式可以选择最近5分钟内的所有样本数据:
prometheus_http_requests_total{}[5m]
该表达式将会返回查询到的时间序列中最近5分钟的所有样本数据:
- PromQL的时间范围选择器支持其它时间单位:
- s - 秒
- m - 分钟
- h - 小时
- d - 天
- w - 周
- y - 年
时间位移操作
在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准:
prometheus_http_requests_total{} # 瞬时向量表达式,选择当前最新的数据
prometheus_http_requests_total{}[5m] # 区间向量表达式,选择以当前时间为基准,
5 分钟内的数据
而如果我们想查询,5分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢? 这个时候我们就可以使用位移操作,位移操作的关键字为offset。 可以使用offset时间位移操作:
prometheus_http_requests_total{} offset 5m
prometheus_http_requests_total{}[1d] offset 1d
使用聚合操作
一般来说,如果描述样本特征的标签(label)在并非唯一的情况下,通过PromQL查询数据,会返回多条满足这些特征维度的时间序列。而PromQL提供的聚合操作可以用来对这些时间序列进行处理,形成一条新的时间序列:
# 查询系统所有http请求的总量
sum(prometheus_http_requests_total)
# 按照mode计算主机CPU的平均使用时间
avg(node_cpu_seconds_total) by (mode)
# 按照主机查询各个主机的CPU使用率
sum(sum(irate(node_cpu_seconds_total{mode!='idle'}[5m])) / sum(irate(node_cpu_ seconds_total [5m]))) by (instance)
标量和字符串
除了使用瞬时向量表达式和区间向量表达式以外,PromQL还直接支持用户使用标量
(Scalar)和字符串(String)。
-
标量(Scalar):一个浮点型的数字值
标量只有一个数字,没有时序
需要注意的是,当使用表达式count(prometheus_http_requests_total),返回的数
据类型,依然是瞬时向量。用户可以通过内置函数scalar()将单个瞬时向量转换为标量。 -
字符串(String):一个简单的字符串值
直接使用字符串,作为PromQL表达式,则会直接返回字符串。
合法的PromQL表达式
所有的PromQL表达式都必须至少包含一个指标名称(例如http_request_total),或者一个不会匹配到空字符串的标签过滤器(例如{code=”200”})。
因此以下两种方式,均为合法的表达式:
prometheus_http_requests_total # 合法
prometheus_http_requests_total{} # 合法
{method="get"} # 合法
同时,除了使用 {label=value} 的形式以外,我们还可以使用内置的 name 标签来指定监控指标名称:
{__name__=~"prometheus_http_requests_total"} # 合法
{__name__=~"node_disk_bytes_read|node_disk_bytes_written"} # 合法
PromQL操作符
使用PromQL除了能够方便的按照查询和过滤时间序列以外,PromQL还支持丰富的操作符,用户可以使用这些操作符对进一步的对事件序列进行二次加工。这些操作符包括:数学运算符,逻辑运算符,布尔运算符等等。
数学运算
- PromQL支持的所有数学运算符如下所示:
- + (加法)
- - (减法)
- * (乘法)
- / (除法)
- % (求余)
- ^ (幂运算)
布尔运算
-
Prometheus支持以下布尔运算符如下:
- == (相等)
- != (不相等)
- >(大于)
- < (小于)
- >= (大于等于)
- <= (小于等于)
-
使用bool修饰符改变布尔运算符的行为
布尔运算符的默认行为是对时序数据进行过滤。而在其它的情况下我们可能需要的是真正的布尔结果。例如,只需要 知道当前模块的HTTP请求量是否>=1000,如果大于等于1000 则返回1(true)否则返回0(false)。这时可以使 用bool修饰符改变布尔运算的默认行为。 例如:
prometheus_http_requests_total > bool 1000
使用bool修改符后,布尔运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果 0或者1。从而形成一条新的时间序列。
同时需要注意的是,如果是在两个标量之间 使用布尔运算,则必须使用bool修饰符
2 == bool 2 # 结果为1
使用集合运算符
使用瞬时向量表达式能够获取到一个包含多个时间序列的集合,我们称为瞬时向量。 通
过集合运算,可以在两个瞬时向量与瞬时向量之间进行相应的集合操作。
- 目前,Prometheus支持以下集合运算符:
- and (并且)
- or (或者)
- unless (排除)
vector1 and vector2 会产生一个由vector1的元素组成的新的向量。该向量包含vector1 中完全匹配vector2 中的元素组成。
vector1 or vector2 会产生一个新的向量,该向量包含vector1中所有的样本数据,以及vector2中没有与 vector1匹配到的样本数据。
vector1 unless vector2 会产生一个新的向量,新向量中的元素由vector1中没有与vector2 匹配的元素组成。
操作符优先级
对于复杂类型的表达式,需要了解运算操作的运行优先级。例如,查询主机的CPU使
用率,可以使用表达式:
100 * (1 - avg (irate(node_cpu_seconds_total{mode='idle'}[5m])) by(job) )
其中irate是PromQL中的内置函数,用于计算区间向量中时间序列每秒的即时增长率。
- 在PromQL操作符中优先级由高到低依次为:
- ^
- *, /, %
- +, -
- ==, !=, <=, =, >
- and, unless
- or
PromQL 聚合操作
Prometheus 还提供了下列内置的聚合操作符,这些操作符作用域瞬时向量。可以将瞬
时表达式返回的样本数据进行 聚合,形成一个新的时间序列。
- sum (求和)
- min (最小值)
- max (最大值)
- avg (平均值)
- stddev (标准差)
- stdvar (标准差异)
- count (计数)
- count_values (对 value 进行计数)
- bottomk (后n条时序)
- topk (前n条时序)
- quantile (分布统计)
使用聚合操作的语法如下:
<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
其中只有 count_values , quantile , topk , bottomk 支持参数(parameter)。
without 用于从计算结果中移除列举的标签,而保留其它标签。by则正好相反,结果向量中只保留列出的标签,其余标签则移除。通过without和by可以按照样本的问题对数据进行聚合。
例如:
sum(prometheus_http_requests_total) without (instance)
等价于
sum(prometheus_http_requests_total) by (code,handler,job,method)
如果只需要计算整个应用的HTTP请求总量,可以直接使用表达式:
sum(prometheus_http_requests_total)