PromQL教程(三)PromQL 入门操作

巴辉特 2024-10-08 14:08:22

PromQL 教程

在 2024 年的当下,Prometheus 生态基本已成为监控领域事实上的标准,学习 Prometheus 是每个运维人员的必修课,也是每个关注服务稳定性的研发人员的必修课。PromQL 是 Prometheus 的查询语言,全称是 Prometheus Query Language,想要学习 Prometheus,PromQL 是必学知识。本文是 PromQL 系列教程的第三讲,讲解 PromQL 入门操作。本系列其他文章:

PromQL 查询选择器

PromQL 用的最多的就是查询选择器,之前文章中演示的 env="plus" 就是典型的选择器的匹配过滤方式。

监控指标中,通常包含不同的标签,用于标识不同的维度,比如 jobinstanceenv 等。PromQL 提供了一种灵活的方式,可以通过标签选择器来过滤数据,只查询符合条件的数据。PromQL 支持四类过滤写法:

  • =:完全匹配,比如 app="clickhouse"
  • !=:完全不匹配,比如 app!="clickhouse"
  • =~:正则匹配,比如 app=~"n9e-.*"
  • !~:正则不匹配,比如 app!~"n9e-.*"

如前文所述,指标名称,通常放到大括号之外,但实际上,指标名称也是一个标签,其标签Key是 __name__,比如:

{__name__="mem_available_percent", app="clickhouse"}

有时采集的监控数据格式设计的不好,一些本该用 label 的信息,放到了 metric 名称中了,此时就可以用 __name__ 做一些正则匹配。或者有时我们想把多个类似的指标放到一张图中展示,也可以用 __name__ 来做正则匹配。

system_load

PromQL 简单聚合

除了查询选择器,PromQL 中另一个最常用的功能就是聚合计算,比如我有多台机器,我想知道所有机器的平均内存可用率,这时候就需要用到聚合计算。比如:

PromQL聚合计算

上例这个图中,第一个卡片是查询的原始数据,没有经过任何聚合,可以看到三台机器的内存可用率分别是多少。第二个卡片是对所有机器的内存可用率做了平均值计算,得到了一个平均值。因为经过了平均计算,所有的标签都会被抹掉,因为从语义上来看,经过了平均计算之后的值,其结果是一个全新的东西,无法用之前的标签来描述了。而第三张图是使用 env 做了 group by,其结果中就包含了 env 这个标签。这个逻辑和 SQL 中的 group by 是类似的。从语义上来看,相当于,不同的 env 会聚合出一个结果值(并带有 env 标签),当然,因为这里的 3 条原始数据恰好仅属于一个 env,所以结果就只有一条。

offset 关键字

监控系统里,经常会有同环比的需求,比如,当前的值相比一周之前,是否有巨大变化,那怎么才能获取历史数据呢?可以使用 offset 关键字。

offset 后面跟一个时间段,比如 5m、1d、7d、1w,offset 要紧跟查询选择器,比如:

sum(http_requests_total{method="GET"} offset 1d)

如果你使用夜莺监控的即时查询 Table 视图,要想查看历史某个时刻的数据,可以使用 offset 关键字,也可以直接在时间选择器中选择历史时间。

PromQL 运算符

PromQL 支持基本的算术运算符和比较运算符,可以对不同的即时向量做运算,这为监控系统带来了巨大的进步,算术运算符让很多计算不需要在采集端做了,可以轻易挪到服务端,而比较运算符则为告警逻辑提供了支撑。

如果服务端不支持指标运算,那这个运算逻辑就要挪到采集侧,比如 agent 侧,但是 agent 的变更是比较费劲的(毕竟要改动源码并编译升级),尤其是机器量比较大的情况下,所以,PromQL 的这个特性,让监控系统的运算逻辑变得更加灵活。

算术运算符

  • + (addition)
  • - (subtraction)
  • * (multiplication)
  • / (division)
  • % (modulo)
  • ^ (power/exponentiation)

举一个例子来演示真实环境下的算术运算符的应用,比如之前的例子,对于内存可用率的指标 mem_available_percent 这个指标是采集器直接计算好的,如果采集器没有计算,而是上报了原始指标 mem_available 和 mem_total,我们仍然可以使用 PromQL 计算出可用率指标:

PromQL算术运算

逻辑上,是先根据 mem_available{env="plus"} 找到相关指标数据,会找到3条,再根据 mem_total{env="plus"} 也能找到3条,二者相除的逻辑姑且可以理解为,循环遍历 mem_available 的3条记录,对于每一条,去 mem_total 的3条记录中找标签相同的记录,进行除法运算。除法运算得到 3 条结果(0~1之间的数字),然后跟100相乘(得到百分比大小),100这个数字称为标量,3条结果和标量计算,会把每一条结果分别乘以100,得到最终的结果,这个最终结果其实就是 mem_available_percent。

如果分子和分母对应的selector查到的数据标签不同,就没法做除法运算了,比如 net_bytes_recv 比内存相关的指标多了一个interface的标签(标明网卡),二者是没法做运算的(当然,语义上也没有意义),结果为空:

net_bytes_recv{env="plus"}/mem_total{env="plus"}

比较运算符

  • == (equal)
  • != (not-equal)
  • > (greater-than)
  • < (less-than)
  • >= (greater-or-equal)
  • <= (less-or-equal)

比较运算符通常用在告警规则中,比如:

cpu_usage_idle{env="plus"} < 10

这个告警规则的意思是,如果 CPU 空闲率小于 10%,就触发告警。不管是 Prometheus 还是 vmalert 还是 Nightingale,其告警引擎的逻辑都是类似的,以这个规则举例,其行为是:

  • 告警引擎拿着这个 PromQL 周期性去查询时序库,使用 /api/v1/query 接口
  • 如果查询结果是空,说明没有数据符合条件,告警引擎就不会触发告警
  • 如果查询结果不为空,说明有数据符合条件,即有些机器负载较高,需要告警,查到几条就产生几条告警
  • 如果觉得偶发性达到阈值不算啥事,无需告警,可以设置告警规则的 for 参数,比如 for: 5m,表示连续 5 分钟满足条件才会触发告警

告警引擎的这个逻辑,非常清晰。但是,只要查不到数据就认为是正常的,这个可能会给你带来困扰。如果想要确保查到数据并且符合阈值才告警,可以使用 Flashduty 的告警功能,Flashduty 是快猫星云提供的一款 SaaS 产品,提供多种告警机制,既支持 Prometheus 类似的方式,也扩展了一些更加灵活的告警方式。

逻辑/集合运算符

相关运算符有三个:and、or、unless 用于 instant-vector 之间的运算。首先来解释一下各个运算符的行为。

and

vector1 and vector2,其结果是一个由vector1的元素组成的向量,对于这些元素,vector2中存在着完全匹配的标签集,其他元素被删除。metric的名称和值从左边的向量转移过来。

用于什么场景?先经过 vector1 做过滤得到一批监控数据,可能里边有一些是不想要的,可以用 and 操作符,再加一个条件,用另一个 metric 的值做一些二次过滤。举例:

disk_used_percent{app="clickhouse"} > 70
and
disk_total{app="clickhouse"}/1024/1024/1024 < 500

磁盘利用率大于 70% 就告警,对于盘不大的情况是适用的,如果盘太大,比如 16T 一块盘,使用率 70% 还有非常大的余量,所以这里我们使用 and 附加一个条件,限制一下 disk_total,即磁盘总大小,磁盘总大小小于 500GB,才适用磁盘利用率大于 70% 这个规则。

or

vector1 or vector2,其结果是一个向量,包含vector1的所有原始元素(标签集+值)以及vector2中所有在vector1中没有匹配标签集的元素。

举一个例子,比如系统负载,有最近1分钟、最近5分钟、最近15分钟的负载,需求是:最近1分钟的负载大于8或者最近5分钟的负载大于8,就告警,PromQL 写法:

system_load1{app="clickhouse"} > 8
or
system_load5{app="clickhouse"} > 8

unless

vector1 unless vector2,结果是一个由vector1中的元素组成的向量,在vector2中没有完全匹配标签集的元素,两个vector中的所有匹配元素都被删除。姑且可以理解为一个减法,vector1 - vector2。

举个例子,还是磁盘利用率的问题,对于超过1个T的大盘,剩余量小于300G就告警,PromQL 怎么写?

disk_free{app="clickhouse"}/1024/1024/1024 < 300
unless
disk_total{app="clickhouse"}/1024/1024/1024 < 1024

使用 unless 排除掉小于1个T的盘,剩下的就只剩大于1个T的大盘了,效果达成。

结语

本文讲解了 PromQL 的查询选择器、简单聚合、offset 关键字、运算符等基础操作,这些知识是学习 PromQL 的必备知识,希望对你有帮助。如果对 PromQL 教程系列的内容感兴趣,欢迎持续关注。

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云
OpenSource
开源版
Flashcat
Flashcat