PromQL 是 Prometheus 提供的一个函数式的表达式语言,可以使用户实时地查找和聚合时间序列数据。表达式计算结果可以在图表中展示,也可以在 Prometheus表达式浏览器中以表格形式展示,或者作为数据源,以 HTTP API 的方式提供给外部系统使用。PromQL 虽然以 QL 结尾,但是它不是类似 SQL 的语言,因为在时间序列上执行计算类型时,SQL 语言相对缺乏表达能力。而 PromQL 语言表达能力非常丰富,可以使用标签进行任意聚合,还可以使用标签将不同的标签连接到一起进行算术运算操作。内置了时间和数学等很多函数可以使用。
然而 PromQL 也是大部分使用 Prometheus 的用户的梦魇,压根不知道如何去编写,很多情况下都是参考别人的来编写,假如自己去实现一个需求从0写一条 PromQL 语句还是比较费劲。这里我们就将一些常用的 PromQL 查询方式进行一些简单的说明,希望对大家有所帮助。
选择序列
选择指定指标名称的序列最新样本:
1 | my_metric_name |
选择指定指标名称序列5分钟的样本范围:
1 | my_metric_name[5m] |
筛选给定标签的序列:
1 | my_metric_name{label1="value1", label2="value2"} |
更复杂的标签匹配器:
1 | my_metric_name{label1!="value1", label2=~"regex1", label3!~"regex2"} |
匹配器:
=
: 等于!=
: 不等于=~
: 正则匹配!~
: 正则不匹配
Counter 的增长速率
过去5分钟每秒平均增长速率:
1 | rate(http_requests_total[5m]) |
1分钟时间窗口中最后两个样本计算的每秒增长速率:
1 | irate(http_requests_total[1m] |
过去1小时增加的绝对数值:
1 | increase(http_requests_total[1h]) |
多个序列聚合
对所有序列进行求和:
1 | sum(my_metric_name) |
根据方法和路径标签维度进行求和:
1 | sum by(method, path) (my_metric_name) |
without
用于从计算结果中移除列举的标签,而保留其它标签,by
则正好相反,结果向量中只保留列出的标签,其余标签则移除:
1 | sum without(method, path) (my_metric_name) |
其他常用的聚合运算符:sum(), min(), max(), avg(), stddev(), stdvar(), count(), count_values(),bottomk(), topk(), quantile()。
序列间的数学计算
将两个相同标签的序列相加:
1 | left_metric + right_metric |
只将匹配 instance 和 job 标签的序列相加:
1 | left_metric + on(instance, job) right_metric |
忽略匹配 instance 和 job 标签的序列相加:
1 | left_metric + ignoring(instance, job) right_metric |
多对一匹配模式:
1 | left_metric + on(instance, job) group_left right_metric |
在结果中包括一侧
(右侧)的 version 标签:
1 | left_metric + on(instance, job) group_left(version) right_metric |
集合操作
包括任何左侧或右侧的标签集合:
1 | left_metric or right_metric |
包括任何同时存在于左侧或右侧的标签集:
1 | left_metric and right_metric |
包含任何左侧的标签集合,但不包括右侧的:
1 | left_metric unless right_metric |
只在某些标签上匹配:
1 | left_metric and on(job, instance) right_metric |
过滤
只保留大于1024样本值的序列:
1 | left_metric > 1024 |
只保留左边样本值大于右边样本值的序列:
1 | left_metric > right_metric |
不过滤序列,而是比较序列,然后返回0
或1
:
1 | left_metric > bool right_metric |
在某些匹配的标签上操作:
1 | left_metric > on(job, instance) right_metric |
其他常用的比较运算符:==、!=、>、<、>=、≤。
直方图分位数
过去5分钟内,每个标签维度请求延迟的90%分位数:
1 | histogram_quantile(0.9, rate(my_request_durations_seconds_bucket[5m])) |
只针对 method 和 path 维度的90%分位数:
1 | histogram_quantile( 0.9, sum by(le, path, method) ( rate(my_request_durations_seconds_bucket[5m]) )) |
Gauges 的变化
过去一小时内的绝对值变化:
1 | delta(my_gauge[1h]) |
基于过去4小时的数据来预测1小时后的数据:
1 | predict_linear(my_gauge[4h], 3600) |
时间
获取 Unix 时间,以秒为单位:
1 | time() |
获取最后一次成功运行的批处理作业的年龄:
1 | time() - my_batch_job_last_success_timestamp_seconds |
查找一小时内没有成功的批处理作业:
1 | time() - my_batch_job_last_success_timestamp_seconds > 3600 |
缺失数据处理
当输入向量为空时,创建一个一个输出序列:
1 | absent(my_metric_name) |
当输入的范围向量5分钟内都是空的时候,创建一个空的输出序列:
1 | absent_over_time(my_metric_name[5m]) |
标签操作
用 -
分隔符连接两个标签的值:
1 | label_join(my_metric_name, "-", "label1", "label2") |
提取标签的一部分并将其存储在新标签中:
1 | label_replace(my_metric, "dest-label", "$1", "source-label", "(.*):.*") |
关于 PromQL 更多的使用方法,可以参考 PromQL 官方文档:
基础:https://prometheus.io/docs/prometheus/latest/querying/basics/
操作符:https://prometheus.io/docs/prometheus/latest/querying/operators/
函数:https://prometheus.io/docs/prometheus/latest/querying/functions/
示例:https://prometheus.io/docs/prometheus/latest/querying/examples/
此外还有一个比较友好的 PromQL Cheatsheet 文档,如下所示: