未分类

Prometheus PromQL

1. 什么是 PromQL?

PromQL(Prometheus Query Language)是 Prometheus 内置的数据查询语言,它能实现对事件序列数据的查询、聚合、逻辑运算等。它并且被广泛应用在 Prometheus 的日常应用当中,包括对数据查询、可视化、告警处理当中。

2. PromQL 基础用法

当 Prometheus 通过 Exporter 采集到相应的监控指标样本数据后,我们就可以通过 PromQL 对监控样本数据进行查询。

当我们直接使用监控指标名称查询时,可以查询该指标下的所有时间序列。我们这里启动 Prometheus 服务器,并打开 http://localhost:9090/graph 地址。在查询框中,我们输入:system_cpu_usage 并点击执行。
file

PromQL 支持户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。

2.1 完全匹配

PromQL 支持使用 = 和!= 两种完全匹配模式。

等于。通过使用 label=value 可以选择那些标签满足表达式定义的时间序列。

不等于。通过使用 label!=value 则可以根据标签匹配排除时间序列。

例如我们上面查询出了所有指标名称为 system_cpu_usage 的数据。这时候我们希望只查看错误的请求,即过滤掉所有 code 标签不是 200 的数据。那么我们的 PromQL 表达式可以修改为:system_cpu_usage{service!="nacos"}。
file

2.2 正则匹配

PromQL 还可以使用正则表达式作为匹配条件,并且可以使用多个匹配条件。

正向匹配。使用 label=~regx 表示选择那些标签符合正则表达式定义的时间序列。

反向匹配。使用 label!~regx 进行排除。

例如我想查询指标 system_cpu_usage 中,所有 instance 标签以 10.0.1 开头的记录,那么我的表达式为:system_cpu_usage{instance=~"10.0.1.*"}。

file

2.3 范围查询

我们上面直接通过类似 system_cpu_usage 表达式查询时间序列时,同一个指标同一标签只会返回一条数据。这样的表达式我们称之为瞬间向量表达式,而返回的结果称之为瞬间向量。

而如果我们想查询一段时间范围内的样本数据,那么我们就需要用到区间向量表达式,其查询出来的结果称之为区间向量。时间范围通过时间范围选择器 [] 进行定义。例如,通过以下表达式可以选择最近 5 分钟内的所有样本数据:

system_cpu_usage{instance=~"10.0.1.*"}[5m]

file

通过查询结果可以看到,此时我们查询出了所有的样本数据,而不再是一个样本数据的统计值。

除了使用 m 表示分钟以外,PromQL 的时间范围选择器支持其它时间单位:

s - 秒

m - 分钟

h - 小时

d - 天

w - 周

y - 年

2.4 时间位移操作

如果我们想查询 5 分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢?这个时候我们就可以使用位移操作,位移操作的关键字为 offset。
system_cpu_usage{instance=~"10.0.1.*"} offset 5m

system_cpu_usage{instance=~"10.0.1.*"}[1d] offset 1d

file

file

2.5 聚合操作

Prometheus 还提供了聚合操作符,这些操作符作用于瞬时向量。可以将瞬时表达式返回的样本数据进行聚合,形成一个新的时间序列。目前支持的聚合函数有:

sum (求和)

min (最小值)

max (最大值)

avg (平均值)

stddev (标准差)

stdvar (标准方差)

count (计数)

count_values (对 value 进行计数)

bottomk (后 n 条时序)

topk (前 n 条时序)

quantile (分位数)

不进行聚合的情况下,请求很多,如下图:
file

  • count

count(http_server_requests_seconds_count)
file

  • sum

sum(http_server_requests_seconds_count)
file

  • bottomk 后几条

bottomk 用于对样本值进行排序,返回当前样本值后 N 位的时间序列。

例如获取 HTTP 请求量后 5 位的请求,可以使用表达式:
bottomk(5, http_server_requests_seconds_count)
file

  • topk 前几条

topk 用于对样本值进行排序,返回当前样本值前 N 位的时间序列。

例如获取 HTTP 请求量前 5 位的请求,可以使用表达式:topk(5, http_server_requests_seconds_count)

  • 标量

在 PromQL 中,标量是一个浮点型的数字值,没有时序。例如:10。

需要注意的是,当使用表达式 count(http_server_requests_seconds_count),返回的数据类型,依然是瞬时向量。用户可以通过内置函数 scalar () 将单个瞬时向量转换为标量。

file
如上图所示,我们将 sum 操作的值用 scalar 转换了一下,最终的结果就是一个标量了。

  • 字符串

在 PromQL 中,字符串是一个简单的字符串值。直接使用字符串作为 PromQL 表达式,则会直接返回字符串。

file

2.6 PromQL 操作符

PromQL 还支持丰富的操作符,用户可以使用这些操作符对进一步的对事件序列进行二次加工。这些操作符包括:数学运算符,逻辑运算符,布尔运算符等等。

  • 数学运算符

数学运算符比较简单,就是简单的加减乘除等。

例如我们通过 backup_storage_used_bytes_total 可以查询到 Prometheus 这个应用的 HTTP 响应字节总和。但是这个单位是字节,我们希望用 GB 显示。那么我们可以这么设置:backup_storage_used_bytes_total/1024/1024/1024 计算出来的单位为GB

file

PromQL 支持的所有数学运算符如下所示:

+ (加法)

- (减法)

* (乘法)

/ (除法)

% (求余)

^ (幂运算)

布尔运算符

布尔运算符支持用户根据时间序列中样本的值,对时间序列进行过滤。例如我们可以通过 backup_storage_used_bytes_total 查询出每个服务的备份大小,但是如果我们想筛选出超过1TB呢?

此时我们可以用下面的 PromQL 表达式:
可以看到我们将所有 value 值超过 1TB 的数据都筛选了出来。

file

file
目前,Prometheus 支持以下布尔运算符如下:

* == (相等)

!= (不相等)

> (大于)

< (小于)

>= (大于等于)

<= (小于等于)

2.7 PromQL 内置函数

PromQL 提供了大量的内置函数,可以对时序数据进行丰富的处理。例如 irate () 函数可以帮助我们计算监控指标的增长率,不需要我们去手动计算。

  • rate 增长率

我们知道 counter 类型指标的特点是只增不减,在没有发生重置的情况下,其样本值是不断增大的。为了能直观地观察期变化情况,需要计算样本的增长率。

increase(v range-vector) 函数是 PromQL 中提供的众多内置函数之一。其中参数 v 是一个区间向量,increase 函数获取区间向量中的第一个后最后一个样本并返回其增长量。因此,可以通过以下表达式 Counter 类型指标的增长率:

这里通过 node_cpu [2m] 获取时间序列最近两分钟的所有样本,increase 计算出最近两分钟的增长量,最后除以时间 120 秒得到 node_cpu 样本在最近两分钟的平均增长率。并且这个值也近似于主机节点最近两分钟内的平均 CPU 使用率。

除了使用 increase 函数以外,PromQL 中还直接内置了 rate (v range-vector) 函数,rate 函数可以直接计算区间向量 v 在时间窗口内平均增长速率。因此,通过以下表达式可以得到与 increase 函数相同的结果:

需要注意的是使用 rate 或者 increase 函数去计算样本的平均增长速率,容易陷入「长尾问题」当中,其无法反应在时间窗口内样本数据的突发变化。

例如,对于主机而言在 2 分钟的时间窗口内,可能在某一个由于访问量或者其它问题导致 CPU 占用 100% 的情况,但是通过计算在时间窗口内的平均增长率却无法反应出该问题。

为了解决该问题,PromQL 提供了另外一个灵敏度更高的函数 irate(v range-vector)。irate 同样用于计算区间向量的计算率,但是其反应出的是瞬时增长率。irate 函数是通过区间向量中最后两个样本数据来计算区间向量的增长速率。

这种方式可以避免在时间窗口范围内的「长尾问题」,并且体现出更好的灵敏度,通过 irate 函数绘制的图标能够更好的反应样本数据的瞬时变化状态。

  • irate

irate 函数相比于 rate 函数提供了更高的灵敏度,不过当需要分析长期趋势或者在告警规则中,irate 的这种灵敏度反而容易造成干扰。因此在长期趋势分析或者告警中更推荐使用 rate 函数。
predict_linear 增长预测

在一般情况下,系统管理员为了确保业务的持续可用运行,会针对服务器的资源设置相应的告警阈值。例如,当磁盘空间只剩 512MB 时向相关人员发送告警通知。这种基于阈值的告警模式对于当资源用量是平滑增长的情况下是能够有效的工作的。

但是如果资源不是平滑变化的呢?比如有些某些业务增长,存储空间的增长速率提升了高几倍。这时,如果基于原有阈值去触发告警,当系统管理员接收到告警以后可能还没来得及去处理问题,系统就已经不可用了。

因此阈值通常来说不是固定的,需要定期进行调整才能保证该告警阈值能够发挥去作用。那么还有没有更好的方法吗?

PromQL 中内置的 predict_linear(v range-vector, t scalar) 函数可以帮助系统管理员更好的处理此类情况,predict_linear 函数可以预测时间序列 v 在 t 秒后的值。

它基于简单线性回归的方式,对时间窗口内的样本数据进行统计,从而可以对时间序列的变化趋势做出预测。例如,基于 2 小时的样本数据,来预测主机可用磁盘空间的是否在 4 个小时候被占满,可以使用如下表达式:

留言

您的电子邮箱地址不会被公开。 必填项已用*标注

闽ICP备20008591号-1