PromQl
Table of Contents
Section titled “Table of Contents”PromQL 是 prometheus 内置的数据查询语言, 使用 PromQL 对 prometheus 收集的数据进行筛选计算
prometheus 数据格式: data_name{label0=value, label1=value, label2=value} data_value
# Node exporter 收集的 metrics 数据示例 # HELP node_cpu_seconds_total Seconds the CPUs spent in each mode. # TYPE node_cpu_seconds_total counter node_cpu_seconds_total{cpu="0",mode="idle"} 24226.24 node_cpu_seconds_total{cpu="0",mode="iowait"} 0.96 node_cpu_seconds_total{cpu="0",mode="irq"} 0 node_cpu_seconds_total{cpu="0",mode="nice"} 0 # HELP node_memory_MemFree_bytes Memory information field MemFree_bytes. # TYPE node_memory_MemFree_bytes gauge node_memory_MemFree_bytes 9.904422912e+09 # HELP node_memory_Active_bytes Memory information field Active_bytes. # TYPE node_memory_Active_bytes gauge node_memory_Active_bytes 4.65158144e+08
使用 data_name{label0=value, label1=value}
筛选数据
# 显示所有的 node_cpu_seconds_total 数据中 cpu="0" 的数据(不同节点的信息会附带 instance 和 job) node_cpu_seconds_total{cpu="0"} > node_cpu_seconds_total{cpu="0", instance="10.143.232.175:9100", job="Node", mode="idle"} 26274.44 > ...... > node_cpu_seconds_total{cpu="0", instance="10.39.104.158:9100", job="Node", mode="system"} 392.63 > ...... > node_cpu_seconds_total{cpu="0", instance="10.39.104.18:9100", job="Node", mode="steal"} 0
metrics 数据类型
Section titled “metrics 数据类型”Prometheus 的 metrics 数据有多种类型, 数据注释结尾中会表明数据类型
prometheus 的数据本质是 /proc 下文件内容, /proc 记录着节点, 进程 等的实时数据
ex: /proc/stat (cpu 实时数据) /proc/meminfo (内存实时数据) /proc/<pid> (进程实时数据)
Counter
Section titled “Counter”计数器类型, 数值只增加(除非系统重置), 如 node_cpu_seconds_total 节点 cpu 执行时间
# HELP node_cpu_seconds_total Seconds the CPUs spent in each mode. # TYPE node_cpu_seconds_total counter node_cpu_seconds_total{cpu="0",mode="idle"} 31712.24 node_cpu_seconds_total{cpu="0",mode="iowait"} 0.96 node_cpu_seconds_total{cpu="0",mode="irq"} 0 node_cpu_seconds_total{cpu="0",mode="nice"} 0 node_cpu_seconds_total{cpu="0",mode="softirq"} 119.36 node_cpu_seconds_total{cpu="0",mode="steal"} 0 node_cpu_seconds_total{cpu="0",mode="system"} 617.85 node_cpu_seconds_total{cpu="0",mode="user"} 1529.83
可增减的仪表盘, 数值可增可减, 用于表示当前状态, node_memory_MemFree_bytes 当前空闲内存
# HELP node_memory_MemFree_bytes Memory information field MemFree_bytes. # TYPE node_memory_MemFree_bytes gauge node_memory_MemFree_bytes 9.904422912e+09 # HELP node_memory_MemTotal_bytes Memory information field MemTotal_bytes. # TYPE node_memory_MemTotal_bytes gauge node_memory_MemTotal_bytes 2.4360300544e+10 # HELP node_memory_Mlocked_bytes Memory information field Mlocked_bytes. # TYPE node_memory_Mlocked_bytes gauge node_memory_Mlocked_bytes 0
Histogram
Section titled “Histogram”直方图, 表示一组观测值的分布, 通常用于度量请求持续时间等
# HELP http_request_duration_seconds HTTP request duration in seconds # TYPE http_request_duration_seconds histogram http_request_duration_seconds_bucket{le="0.1"} 10 http_request_duration_seconds_bucket{le="1"} 20 http_request_duration_seconds_bucket{le="5"} 30 http_request_duration_seconds_bucket{le="10"} 40 http_request_duration_seconds_bucket{le="+Inf"} 50 http_request_duration_seconds_sum 235.5 http_request_duration_seconds_count 50 # 操作次数 50, 耗时 235.5s # 耗时 小于 0.1s 的有 10次 # 耗时 小于 1s 的有 20次 # 耗时 小于 5s 的有 30次 # 耗时 小于 10s 的有 40次 # 耗时 小于 无穷大的有 50次
Summary
Section titled “Summary”摘要, 类似于 Histogram,但是它会保留一系列指定的分位数
# HELP prometheus_tsdb_wal_fsync_duration_seconds Duration of WAL fsync. # TYPE prometheus_tsdb_wal_fsync_duration_seconds summary prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.5"} 0.012352463 prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.9"} 0.014458005 prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.99"} 0.017316173 prometheus_tsdb_wal_fsync_duration_seconds_sum 2.888716127000002 prometheus_tsdb_wal_fsync_duration_seconds_count 216 # 操作的总次数为216次,耗时2.888716127000002s, 按耗时给所有次数排序 # 中位数(quantile=0.5)的耗时为0.012352463 # 9分位数(quantile=0.9)的耗时为0.014458005s
Prometheus 采集的数据有类别, 时间和值类型 3 种属性 使用 PromQL 查询返回的数据有 4 种类型
- Instan vector: 瞬时向量, 某个时间点采集的数据集合
- Range vector: 区间向量, 指定时间范围内, 无数瞬时向量的集合
- Scalar: 标量, 浮点数字, 无时间类别属性
- String: 字符串
- 完全匹配: 等于
=
, 不等于!=
- 正则匹配: 正向
=~
反向!~
# cpu0 node_cpu_seconds_total{cpu="0"} # 非 cpu0 node_cpu_seconds_total{cpu!="0"} # cpu0 job 中包含 Node node_cpu_seconds_total{cpu="0",job=~".*Node.*"} # cpu0 job 中包含 Node node_cpu_seconds_total{cpu="0",job!~".*Node.*"}
上述查询的结果都是瞬时值, 是从最新的数据查询, 这样的结果称为瞬时向量
实际上, prometheus 获取的数据是带有时间的, 一段时间内的数据称作区间向量
# 在瞬时表达式结尾添加 [time] 表示从当前往前一段时间的数据 # 节点 5 分钟前到现在 cpu0 idle 的值(每 15s 查询一次), 34848.9(值) @1708573601.411(时间点) node_cpu_seconds_total{cpu="0", instance="10.143.232.175:9100", mode="idle"}[5m] > node_cpu_seconds_total{cpu="0", instance="10.143.232.175:9100", mode="idle"} 34848.9 @1708573601.411 > 34863.28 @1708573616.411 > 34877.63 @1708573631.411 > 34892 @1708573646.411 > 34906.3 @1708573661.411 > 34920.6 @1708573676.411 > 34934.85 @1708573691.411 > 34949.08 @1708573706.411 > 34963.29 @1708573721.411 > 34977.53 @1708573736.411 > 34991.82 @1708573751.411 > 35006.06 @1708573766.411 > 35020.08 @1708573781.411 > 35034.16 @1708573796.411 > 35048.44 @1708573811.411
符号 | s | m | h | d | w | y |
---|---|---|---|---|---|---|
含义 | 秒[5s] | 分钟[5m] | 小时[5h] | 天[5d] | 周[5w] | 年[5y] |
默认查询都是以当前时间作为基准, 取当前时间点或者, 当前往前推一段时间
若要更换时间基准, 如 1 天前同一时刻, 或者昨天一整天的数据, 使用 offset 切换时间基准
# 当前时间往前推 1 天 node_cpu_seconds_total{cpu="0", instance="10.143.232.175:9100", mode="idle"} offset 1d # 当前是 02/22 10:00, 先往前推 10 小时到 00:00, 再取 00:00 往前 1 天的数据 node_cpu_seconds_total{cpu="0", instance="10.143.232.175:9100", mode="idle"}[1d] offset 10h
对瞬时向量进行聚合操作
- sum:
求和 sum(node_cpu_seconds_total{cpu="0"})
- min:
最小值 min(node_cpu_seconds_total{cpu="0"})
- max:
最大值 max(node_cpu_seconds_total{cpu="0"})
- avg:
平均值 avg(node_cpu_seconds_total{cpu="0"})
- count:
计数 count(node_cpu_seconds_total{cpu="0"})
- topk:
前 n 条数据 topk(5, node_cpu_seconds_total{cpu="0"})
- bottomk:
最后 n 条数据 bottomkk(5, node_cpu_seconds_total{cpu="0"})
- stddev: 标准差
瞬时向量可以直接与标量计算, 如 Memory 原始数据单位是 Byte, 除以 1024, 单位变成 KB
瞬时向量和瞬时向量运算, 只有 {label0=value, label1=value}
完全一致才会计算
使用 on
或 ignore
让不同标签的向量也能做数学运算
node_cpu_seconds_total + on(instance, job, mode, cpu) node_cpu_guest_seconds_total
increase
Section titled “increase”计算一个 Counter 数据的增长, 取最后时刻的数据减去最初时刻的数据
increase(range-vector)
increase(node_cpu_seconds_total{cpu="0", instance="10.143.232.175:9100", job="V2-Node",mode="idle"}[5m]) > {cpu="0", instance="10.143.232.175:9100", job="V2-Node", mode="idle"} 218.2709700476184
计算平均每秒的增长, 即增长量除以时间
rate(range-vector) == increase(range-vector) / time
rate(node_cpu_seconds_total{cpu="0", instance="10.143.232.175:9100", job="V2-Node",mode="idle"}[5m]) > {cpu="0", instance="10.143.232.175:9100", job="V2-Node", mode="idle"} 0.7518475626666798
计算最后两组数据的增长率(瞬时变化): 最后的数据 - 最后前一次数据 / 两个数据时间差
# 由于仅取最后两组数据, 在同一个时间点, [2m] [5m] (无论往前推多少时间)的最后两组数据一致, 结果也一致 irate(node_cpu_seconds_total{cpu="0", instance="10.143.232.175:9100", job="V2-Node",mode="idle"}[2m]) > {cpu="0", instance="10.143.232.175:9100", job="V2-Node", mode="idle"} 0.8286666666666861
# job 中包含 Node 的(1 连接, 0 断连) up{job=~".*Node"} up{instance="10.121.238.42:6100", job="V2-Node"} 1 up{instance="10.121.238.42:7100", job="V2-Node"} 1 up{instance="10.143.232.175:9100", job="V2-Node"} 1 up{instance="10.144.226.244:9100", job="V1-Node"} 1
CPU 占用率
Section titled “CPU 占用率”/proc/stat 保存 CPU 执行时间数据(Counter类型)
CPU 占用: 一段时间内, CPU 工作时间(总时间 - 空闲时间)占总时间的比值
字段 | user | nice | system | idle | iowait | irq | softirq | steal/guest/guest_nice |
---|---|---|---|---|---|---|---|---|
值 | 1128155 | 0 | 990765 | 52801349 | 8147 | 0 | 5547 | 0/0/0 |
含义 | 用户态时间 | 低优先级用户态时间 | 内核态时间 | 空闲时间 | I/O等待时间 | 硬中断时间 | 软中断时间 | 虚拟机占用时间 |
CPU Used = 1 - (idle / (user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice))
# 2m 最后两组数据计算平均增长率 irate(node_cpu_seconds_total{mode="idle"}[2m]) irate(node_cpu_seconds_total[2m]) # 1 减去空闲百分比获得 CPU 占用百分比(按) 1 - (sum by(instance) (irate(node_cpu_seconds_total{mode="idle"}[2m])) / sum by(instance) (irate(node_cpu_seconds_total[2m]))) 1 - ((irate(node_cpu_seconds_total{mode="idle", instance="192.168.1.100"}[2m])) / (irate(node_cpu_seconds_total{instance="192.168.1.100"}[2m])))
# 注: sum by 语句后仅保留设置的索引, 类似于 pandas 的 groupby sum by(job,instance) (node_cpu_seconds_total{mode="idle"}) {instance="10.121.238.42:1100", job="V2-Node"} 192876.24 {instance="10.121.238.42:2100", job="V2-Node"} 1113100.96 {instance="10.121.238.42:6100", job="V2-Node"} 1156084.41 {instance="10.121.238.42:7100", job="V2-Node"} 1154130.68
/proc/meminfo 保存 Memory 数据(Gauge类型)
Memory Used: (MemTotal - MemAvailable) / MemTotal
# 已使用内存(单位 Byte) node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes # 已使用内存(单位 GB) (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / 1024 / 1024 / 1024 # 内存占用百分比 (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes
Disk Used: 1- (Disk Available / Disk Total)
# 可用空间 node_filesystem_avail_bytes # 硬盘总空间 node_filesystem_size_bytes 1 - ((node_filesystem_avail_bytes) / node_filesystem_size_bytes)
prometheus 提供了API, 可以通过 API 获取数据
import requests # 查询瞬时数据 query_url = "http://localhost:9090/api/v1/query" r = requests.get(query_url, params={"query": 'node_cpu_seconds_total{mode="idle", "instance": "192.168.1.100:9100", "cpu"="0"}'}) r.json() { "status": "success", "data": { "resultType": "vector", "result": [ { "metric": { "__name__": "node_cpu_seconds_total", "cpu": "0", "instance": "192.168.1.100:9100", "job": "Node", "mode": "idle" }, "value": [1719297314.563, "26458.92"] } ] } } # 查询时间段数据 query_range_url = "http://localhost:9090/api/v1/query_range" r = requests.get(query_range_url, params={ "query": 'node_cpu_seconds_total{mode="idle", "instance": "192.168.1.100:9100", "cpu"="0"}', "start": "2024-06-25T12:00:00+08:00", "end": "2024-06-25T12:05:00+08:00", "step": "1m" }) r.json() { "status": "success", "data": { "resultType": "matrix", "result": [ { "metric": { "__name__": "node_cpu_seconds_total", "cpu": "0", "instance": "192.168.1.100:9100", "job": "Node", "mode": "idle" }, "values": [ [1719230400, "4454.3"], [1719230460, "4504.85"], [1719230520, "4555.09"], [1719230580, "4605.51"], [1719230640, "4655.95"], [1719230700, "4697.64"] ] } ] } }