1. PromQL语句介绍
官方文档:https://prometheus.io/docs/prometheus/latest/querying/basics/
Prometheus提供一个函数式的表达式语言PromQL (Prometheus Query Language),可以使用户实时地查找和聚合时间序列数据,表达式计算结果可以在图表中展示,也可以在Prometheus表达式浏览器中以表格形式展示,或者作为数据源, 以HTTP API的方式提供给外部系统使用。
2. PromQL数据类型
2.1 查询数据类型
2.1.1 Instant Vector
在 Prometheus 中,Instant Vector(即即时向量)是一种数据类型,它表示在给定时间点上收集的指标值。Instant Vector 是 Prometheus 查询语言(PromQL)的基本单位,用于执行即时的、点状的查询。
Instant Vector 由以下两个主要组成部分构成:
- 时间戳(Timestamp):Instant Vector 中的每个数据点都包含一个时间戳,也是查询必带条件,表示该数据点的采集时间。
- 标签(Labels):Instant Vector 中的每个数据点也包含一组标签,用于标识所选取的指标。标签是键值对的形式,例如 instance=“server1” 或 job=“prometheus”。
该类型数据的特点:只会返回给定时间点上的数据,而不是时间范围内的数据。
以下是查询node节点可用内存的瞬时向量表达式:
[root@prometheus-server ~]# curl 'http://10.31.200.100:9090/api/v1/query' --data 'query=node_memory_MemFree_bytes' --data time=1708579600
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"node_memory_MemFree_bytes","instance":"10.31.200.101:9100","job":"prometheus-node"},"value":[1708579600,"1624408064"]}]}}
,注意--data time=1708579600
要换成当前的unix时间戳。返回内容这里显示不好识别,我在线转成了json格式:
2.1.2 Range Vector
在 Prometheus 中,Range Vector(范围向量/范围数据)是一种数据类型,用于表示在一段时间范围内收集的指标值。与 Instant Vector(即时向量)不同,Range Vector 表示的是一段时间内的连续数据。
比如最近一天的网卡流量趋势图、或最近5分钟的node节点内容可用字节数等。
Range Vector 由以下三个主要组成部分构成:
- 时间范围(Time Range):Range Vector 表示的是在一个时间范围内的数据。时间范围由开始时间和结束时间组成,表示数据的持续时间段。
- 时间戳(Timestamp):Range Vector 中的每个数据点都包含一个时间戳,表示该数据点的采集时间。
- 标签(Labels):Range Vector 中的每个数据点也包含一组标签,用于标识所选取的指标。标签是键值对的形式,例如 instance=“server1” 或 job=“prometheus”。
Range Vector 通常用于表示在某个时间范围内特定标签匹配的指标值。如下是查询node节点可用内存的范围向量表达式:
[root@prometheus-server ~]# curl 'http://10.31.200.100:9090/api/v1/query' --data 'query=node_memory_MemFree_bytes{instance="10.31.200.101:9100"}[5m]' --data time=1708581334
2.1.3 scalar
标量/纯量数据,是一个浮点数类型的数据值,使用node_load1获取到时一个瞬时向量后,在使用prometheus的内置函数scalar()将瞬时向量转换为标量,例如:scalar(sum(node_load1))
curl 'http://10.31.200.100:9090/api/v1/query' --data 'query=scalar(sum(node_load1{instance="10.31.200.101:9100"}))' --data time=1708583079
{"status":"success","data":{"resultType":"scalar","result":[1708583079,"0"]}}
2.1.4 string
简单的字符串类型的数据,目前未使用.
2.2 指标数据类型
(1)Counter:计数器
(2)Gauge:仪表盘
(3)Histogram:累积直方图
(4)Summary:摘要
2.2.1 Counter
Counter(计数器)类型代表一个累积的指标数据,在没有被重启的前提下只增不减(生活中的电表、水表),比如磁盘I/O总数、Nginx/API的请求总数、网卡流经的报文总数等。
该类型数据直增不减,除非重启。
注意:如果想用Counter的指标来绘图的话,必须结合rate或者ireate使用。
2.2.2 Gauge
Gauge(仪表盘)类型代表一个可以任意变化的指标数据,值可以随时增高或减少,如带宽速率、CPU负载、内存利用率、nginx 活动连接数等。
2.2.3 Histogram
Histogram(累积直方图)会在一段时间范围内对数据进行采样(通常是请求持续时间或响应大小等)。
假如每分钟产生一个当前的活跃连接数,那么一天24小时*60分钟=1440分钟就会产生1440个数据,查看数据的每间隔的绘图跨度为2小时,那么2点的柱状图(bucket)会包含0点到2点即两个小时的数据,而4点的柱状图(bucket)则会包含0点到4点的数据,而6点的柱状图(bucket)则会包含0点到6点的数据,可用于统计从当天零点开始到当前时间的数据统计结果,如http请求成功率、丢包率等,比如ELK的当天访问IP统计。
2.2.4 Summary
Summary:摘要图,也是一组数据,默认统计选中的指标的最近10分钟内的数据的分位数,可以指定数据统计时间范围,基于分位数(Quantile),亦称分位点,是指用分割点(cut point)将随机数据统计并划分为几个具有相同概率的连续区间,常见的为四分位,四分位数是将数据样本统计后分成四个区间,将范围内的数据进行百分比的占比统计,从0到1,表示是0%100%,(0%25%,%2550%,50%75%,75%~100%),利用四分位数,可以快速了解数据的大概统计结果。
就是类似skywallking,显示某个环节执行时间。
3. node-exporter指标数据格式
3.1 没有标签的
# metric_name metric_value
# TYPE node_load15 gauge
node_load15 0.1
3.2 一个标签的
# metric_name{label1_name=“label1-value”} metric_value
# TYPE node_network_receive_bytes_total counter
node_network_receive_bytes_total{device=“eth0”} 1.44096e+07
3.3 多个标签的
# metric_name{label1_name=“label1-value”,“labelN_name=“labelN-value} metric_value
# TYPE node_filesystem_files_free gauge
node_filesystem_files_free{device=”/dev/sda2”,fstype=“xfs”,mountpoint=“/boot”} 52398
3.4 PromQL查询指标数据示例
# 查询node节点总内存大小
node_memory_MemTotal_bytes
# 查询node节点剩余可用内存
node_memory_MemFree_bytes
# 基于标签查询指定节点的总内存
node_memory_MemTotal_bytes{instance="172.31.1.181:9100"}
#基于标签查询指定节点的可用内存
node_memory_MemFree_bytes{instance="172.31.1.181:9100"}
# 查询指定磁盘的每秒磁盘io
node_disk_io_time_seconds_total{device="sda"}
# 查看指定磁盘的磁盘剩余空间
node_filesystem_free_bytes{device="/dev/sda1",fstype="xfs",mountpoint="/"}
4. PromQL标签匹配符
标签 | 含义 |
---|---|
= | 选择与提供的字符串完全相同的标签,精确匹配 |
!= | 选择与提供的字符串不相同的标签,取反 |
=~ | 选择正则表达式与提供的字符串(或子字符串)相匹配的标签。 |
!~ | 选择正则表达式与提供的字符串(或子字符串)不匹配的标签。 |
4.1 使用示例
4.1.1 精确匹配
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=node_load5{job="prometheus-node01",instance="10.31.200.101:9100"}'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"__name__": "node_load5",
"instance": "10.31.200.101:9100",
"job": "prometheus-node01"
},
"value": [
1708654029.026,
"0.01"
]
}
]
}
}
4.1.2 取反
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=node_load5{instance!="10.31.200.101:9100"}'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"__name__": "node_load5",
"instance": "10.31.200.102:9100",
"job": "prometheus-node02"
},
"value": [
1708654185.69,
"0.01"
]
}
]
}
}
4.1.3 包含正则的精确匹配
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=node_load1{instance=~"10.31.200.*:9100"}'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"__name__": "node_load1",
"instance": "10.31.200.101:9100",
"job": "prometheus-node01"
},
"value": [
1708654466.689,
"0"
]
},
{
"metric": {
"__name__": "node_load1",
"instance": "10.31.200.102:9100",
"job": "prometheus-node02"
},
"value": [
1708654466.689,
"0"
]
}
]
}
}
4.1.4 包含正则且取反
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=node_load5{instance!~"10.31.200.101:9100"}'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"__name__": "node_load5",
"instance": "10.31.200.102:9100",
"job": "prometheus-node02"
},
"value": [
1708654541.466,
"0.01"
]
}
]
}
}
5. PromQL 时间范围符
符号 | 含义 |
---|---|
s | 秒 |
m | 分钟 |
h | 小时 |
d | 天 |
w | 周 |
y | 年 |
5.1 使用示例
5.1.1 查询节点总内存大小,单位从默认字节转为GB(瞬时向量表达式)
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=node_memory_MemTotal_bytes{instance="10.31.200.101:9100"}/1024/1024/1024'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"instance": "10.31.200.101:9100",
"job": "prometheus-node"
},
"value": [
1708598477.82, # 2024-02-22 18:41:17
"1.7952041625976562" # 10.31.200.101实例的内存总大小约为1.8G
]
}
]
}
}
5.1.2 查询最近1分钟内存缓存量
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=node_memory_Cached_bytes[1m]'|jq # 数据收集是15s一次,不然查的时间范围太大,数据会显示很多
{
"status": "success",
"data": {
"resultType": "matrix",
"result": [
{
"metric": {
"__name__": "node_memory_Cached_bytes",
"instance": "10.31.200.101:9100",
"job": "prometheus-node"
},
"values": [
[
1708601740.24,
"153559040"
],
[
1708601755.241,
"153559040"
],
[
1708601770.24,
"153559040"
],
[
1708601785.24,
"153559040"
]
]
}
]
}
}
6. PromQL 指标数据运算符
符号 | 含义 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取模 |
^ | 次方 |
6.1 使用示例
6.1.1 计算所有节点内存使用百分比
(node_memory_Active_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes) / node_memory_MemTotal_bytes * 100
6.1.2 计算所有节点磁盘读写数据量
node_disk_read_bytes_total{device="sda"} + node_disk_written_bytes_total{device="sda"}
7. PromQL聚合运算符
注意:使用聚合函数时,会自动过滤掉返回值的标签,并只显示最符合条件的值,如图聚合运算的目标是多个,可以通过加by (标签)来显示返回值对应的标签
符号 | 含义 |
---|---|
max() | 最大值 |
min() | 最小值 |
avg() | 平均值 |
sum() | 求和 |
count() | 统计返回值的条数 |
count_values | 统计返回value的条数,并赋值给一个新的自定义标签,从而形成一个新的label。 |
abs() | 返回指标数据的绝对值。如返回结果是-10,则返回10. |
absent() | 判断对应监控指标是否有数据,有数据就返回空,没有数据就返回1。判断数据是否为空,为空为真。可用于对监控项设置告警通知(如果返回值等于1就触发告警通知) |
stddev() | 标准差 |
stdvar() | 求方差 |
topk() | 返回值排名最大的N个数据,就是降序排序 |
bottomk() | 返回值排名最小的N个数据,升序排序 |
rate() | rate函数是专门搭配counter数据类型使用函数,rate会取指定时间范围内所有数据点,算出一组速率,然后取平均值作为结果,适合用于计算数据相对平稳的数据,比较适合绘图展示。 |
irate() | 也是专门搭配counter数据类型使用函数,irate取的是在指定时间范围内的最近两个数据点来算速率,适合计算数据变化比较大的数据,显示的数据相对比较准确,所以官网文档说:irate适合快速变化的计数器(counter),而rate适合缓慢变化的计数器(counter)。更推荐使用该函数替代rate,比它更准。 |
by | 保留指定的标签,移除其他的标签 |
without | 移除指定的标签,保留其他标签 |
7.1 使用示例
7.1.1 计算每个节点网卡当前最大流量-max
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=max(node_network_receive_bytes_total) by (instance)/1024/1024'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"instance": "10.31.200.101:9100"
},
"value": [
1708606788.054,
"28.275794982910156"
]
}
]
}
}
演示下不加by的区别
7.1.2 计算节点最近1分钟每个device的最大流量
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=max(rate(node_network_receive_bytes_total[1m])) by (device)'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"device": "ens192"
},
"value": [
1708606461.396,
"78.60174670548234"
]
},
{
"metric": {
"device": "lo"
},
"value": [
1708606461.396,
"0"
]
}
]
}
}
7.1.3 统计Prometheus server 总请求次数-sum
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=sum(prometheus_http_requests_total)'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {},
"value": [
1708671038.503,
"2023"
]
}
]
}
}
7.1.4 统计有多少台被监控的主机-count
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=count(node_os_version)'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {},
"value": [
1708671604.554,
"2"
]
}
]
}
}
7.1.5 统计当前系统版本,并复制个要给自定义标签-count_values
7.1.6 判断指标是否有数据-absent
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=absent(sum(prometheus_http_requests_total{handler="/metrics"}))'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [] # 为空为真,为空就是有数据
}
}
7.1.7 返回监控指标的绝对值-abs
[root@prometheus-server ~]# curl -s 'http://10.31.200.100:9090/api/v1/query' --data 'query=abs(sum(prometheus_http_requests_total{handler="/metrics"}))'|jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {},
"value": [
1708677039.986,
"1607" # 如果这里的值是-1607,那么也会返回1607
]
}
]
}
}
7.1.8 统计prometheus前6个访问次数最多的接口
topk(6,prometheus_http_requests_total)
7.1.9 使用rate和irate对瞬时数据进行绘图展示
默认情况下,查询类型的数据,是不支持绘图展示的,但是可以通过函数
7.1.9.1 rate
rate取的是一组数据的平均值,所以看着没有太大的波动