Prometheus通过指标名称(metric names)以及对应的一组标签(lables)来唯一定义一条时间序列。
指标名称metric name反应了监控样本的基本标识,label则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤、聚合,统计从而产生新的计算后的一条时间序列。
PromSQL是Prometheus内置的数据查询语言,其提供对时间序列数据丰富的查询、聚合以及逻辑运算能力的支持。并且广泛的运用于Prometheus的日常应用中,例如对数据的查询、可视化、告警处理等。
可以这么说,PromQL 是Prometheus 所有应用场景的基础,理解和掌握 PromQL 是 Prometheus 入门的第一课。
当Prometheus通过exporters采集到监控指标样本数据后,就可以使用PromQL来完成监控样本数据的查询了。
当直接使用监控指标名称进行查询时,能够查询到该指标下所有时间序列。
例如:
prometheus_http_request_total
相当于
prometheus_http_request_total{}
该表达式会返回指标名称为 prometheus_http_requests_total 的所有时间序列:
prometheus_http_requests_total{code="200",handler="alerts",instance="localhost:
9090",job="prometheus",method="get"}= (20889@1518096812.326)
prometheus_http_requests_total{code="200",handler="graph",instance="localhost:9
090",job="prometheus",method="get"}= (21287@1518096812.326)
Prometheus还支持用户根据时间序列的标签匹配模式来进行时间序列的过滤。
目前主要支持两种匹配模式:
PromSQL支持使用“ = ” 和“ != ”两种完全匹配模式。
使用 label = value 的形式可以选择那些标签符合表达式定义的时间序列
使用 label ! = value的形式可以根据标签排除时间序列
例如,要排除prometheus_http_requests_total时间序列中instance值不为ocalhost:9
090的时间序列:
prometheus_http_requests_total{instance!="localhost:9090"}
反之,要查询prometheus_http_requests_total时间序列中instance值为ocalhost:9
090的时间序列:
prometheus_http_requests_total{instance="localhost:9090"}
prometheus还支持使用正则表达式作为匹配形式,多个表达式之间可使用" | "来分割
使用label = ~regx 来选择那些标签符合表达式定义的时间序列
使用label !~regx来排除不符合表达式的时间序列
例如,想查询多个环境下的时间序列,可以
prometheus_http_requests_total{environment=~"staging|testing|development",method!="GET"}
排除用法:
prometheus_http_requests_total{environment!~"staging|testing|development",method!="GET"}
直接使用表达式查询某个标签名称得出的结果往往都是时间序列中最新的一条样本数据,这样的返回结果称为瞬时向量,相对应的这样的表达式称为瞬时向量表达式。
如果想要获取某一区间范围内的样本数据时,就需要使用区间向量表达式。其与瞬时向量表达式的最大区别就是,区间向量表达式需要定义需要查询的时间范围,时间范围通过**时间范围选择器[]**来定义。
例如,通过以下表达式可以返回最近5分钟之内该指标的所有样本数据:
prometheus_http_request_total{}[5m]
返回值
prometheus_http_requests_total{code="200",handler="alerts",instance="localhost:
9090",job="prometheus",method="get"}=[
1@1518096812.326
1@1518096817.326
1@1518096822.326
1@1518096827.326
1@1518096832.326
1@1518096837.325
] 9.
prometheus_http_requests_total{code="200",handler="graph",instance="localhost:9
090",job="prometheus",method="get"}=[
4@1518096812.326
4@1518096817.326
4@1518096822.326
4@1518096827.326
4@1518096832.326
4@1518096837.325
]
通过区间向量表达式得出的样本数据称为区间向量。
除了用m表示分钟之外,PromQL的时间选择器也支持其他时间单位:
标识 | 含义 |
---|---|
s | 秒 |
m | 分钟 |
h | 小时 |
d | 天 |
w | 周 |
y | 年 |
无论是使用瞬时向量表达式还是区间向量表达式,得到的都是以当前时间为基准的时间序列下的样本数据。
那么如果想要得到5min之前的瞬时向量或是前一天的样本数据呢?
此时就需要使用时间位移操作来对基准时间进行改变,时间位移的关键字为offset。
例如:
##5分钟前的该指标的瞬时向量
prometheus_http_request_total{}offset 5m
##前一天内的、该指标的区间向量
prometheus_http_request_total{}[1d]offset [1d]
一般情况下,在某指标的标签并非唯一的情况下,会返回不止一条符合标签值的样本数据。
而使用promQL的聚合操作,则可以对时间序列进行进一步的处理,而得出一条新的时间序列。
例如:
# 查询系统所有 http 请求的总量
sum(prometheus_http_request_total)
# 按照 mode 计算主机 CPU 的平均使用时间
ave(node_cpu_seconds_total)by(mode)
# 按照主机查询各个主机的 CPU 使用率
by(instance)
一个浮点型的数值类型。
标量只有数值,没有时序
10
需要注意的是,当时用表达式count(prometheus_http_request_total)
,返回的数据类型依然是瞬时向量。用户可以通过内置函数Scaler()来将其变为标量。
直接使用字符串作为 PromQL 表达式,则会直接返回字符串。
"this is a string"
合法的表达式必须至少包含一个标量名称(例如 http_request_total)或是不会匹配到空字符串的指标过滤器(例如{code=”200”})。
以下是合法的表达式:
http_request_total
http_request_total{}
{method="get"}
以下是不合法的:
{job=".*"}
不仅可以使用 label=value的形式来表示标签名称,还可以使用内置__name__
标签
来表示标签名称。
{__name__=~"http_request_total"}
{__name__="~node_disk_bytes_read|node_disk_bytes_written"}
使用PromQL除了可以用于快速查询和过滤时间序列之外,还可以通过使用操作符,对时间序列进行进一步的二次加工。这些操作符包括数学操作符、逻辑操作符和布尔操作符等等。
PromQL支持的所有数学操作符有:
符号 | 含义 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取余 |
^ | 幂运算 |
PromQL支持的布尔运算符有:
符号 | 含义 |
---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
使用布尔运算符默认执行的一般是对时间序列的过滤,但其实我们会比较需要的是一个具体的布尔值,比如,只需要知道当前模块的 HTTP 请求量是否>=1000,如果大于等于1000 则返回 1(true)否则返回 0(false)。这里使用bool修饰符就可以改变布尔运算的默认行为。
prometheus_http_requests_total > bool 1000
另外,两个标量之间使用布尔运算必须使用bool修饰符
例如:
1 == bool 11
输出结果为0
2 == bool 2
输出结果为1
使用瞬时向量表达式能够获得一个包含多个时间序列的数据集合,我们称之为瞬时向量。
通过集合运算,可以在两个瞬时向量之间进行相应的集合操作。
目前,Prometheus支持的聚合运算符有:
运算符 | 含义 |
---|---|
and | 并且 |
or | 或者 |
unless | 排除 |
对于复杂的正则表达式,需要知道操作符的优先级。
例如:
100 * (1 - avg (irate(node_cpu_seconds_total{mode='idle'}[5m])) by(job) )
其中 irate
是 PromQL 中的内置函数,用于计算区间向量中时间序列每秒的即时增长率。
在 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则正好相反,是将符合需要标签的结果留下。
例如:
sum(prometheus_http_request_total)without(instance)
等价于
sum(prometheus_http_request_total)by(code,handler,job,method)
如果只需要计算整个应用的 HTTP 请求总量,可以直接使用表达式:
sum(prometheus_http_requests_total)
count_values 用于时间序列中每一个样本值出现的次数。
count_values 会为每一个唯一的样本值输出一个时间序列,并且每一个时间序列包含一个额外的标签。
例如:
count_values("count", prometheus_http_requests_total)
topk 和 bottomk 则用于对样本值进行排序,返回当前样本值前 n 位,或者后 n 位的时间序列。
获取 HTTP 请求数前 5 位的时序样本数据,可以使用表达式:
topk(5, prometheus_http_requests_total)
quantile 用于计算当前样本数据值的分布情况 quantile(φ, express)其中 0 ≤ φ ≤ 1。
例如,当φ为 0.5 时,即表示找到当前样本数据中的中位数:
quantile(0.5, prometheus_http_requests_total)