PromQL是Prometheus内置的数据查询DSL(Domain Specific Language)语言,其提供对时间序列丰富的查询功能,聚合以及逻辑运算能力的支持。当前,PromQL被广泛应用在Prometheus的日常使用中,包括数据查询、可视化、告警处理等,可以说,掌握PromQL是熟练使用prometheus的必备条件。
本文将通过Prometheus内置的表达式浏览器来演示PromQL语言的使用,考虑篇幅原因,本次内容会分为两篇文章进行讲解。
一. 基础查询
Prometheus的基础查询一般表达式格式为<metric name>{label=value},通过指标名称加标签的方式进行查询,如查看Prometheus更新接口的请求次数。
prometheus_http_requests_total{handler="/-/reload"}
在表达式浏览器上执行后,可看到显示出了三个数据,通过标签可看到分别对应code码为200、405和500的请求数。
查询表达式也可以支持通过指标名称(例如http_request_total),或者一个不会匹配到空字符串的标签过滤器(例如{code="200"})来进行查询。
prometheus_http_requests_total #合法
prometheus_http_requests_total{} #合法
{handler="/api/v1/query"} #合法
PromQL支持使用=和!=两种匹配模式,通过使用label =value 可以查询那些标签满足表达式的时间序列,而与之相反使用label !=value则会排除满足条件的时间序列。以上面的查询为例,假如我们只想关注非正常响应的请求,可使用下列表达式
prometheus_http_requests_total{handler="/-/reload",code!="200"}
此时,查询结果会排除code=200的时间序列,并返回其他类型的数据。
除了使用完全匹配的方式的进行查询外,PromQL还支持使用正则表达式作为匹配条件,书写格式为label =~regx,其中~为表示符,regx为正则内容。
例如,通过正则表达式的模糊匹配方式,上述的接口查询也可以使用下列表达式达到相同效果。
prometheus_http_requests_total{handler=~".*reload"}
如需要同时查询多个接口的时间序列的话,可使用如下正则表达式
prometheus_http_requests_total{handler=~"/graph|/rules|/metrics"}
二. 时间范围查询
在上述的基础查询案例中, 我们通过<metric name>{label=value}方式进行查询时,返回结果中只会包含该时间序列的最新一个值,这样的结果类型称为瞬时向量(instant vector )。除了瞬时向量,PromQL也支持返回时间序列在某个时间范围内的一组数据,这种称为范围向量(range vector )。
范围向量表达式需要定义时间选择的范围,时间范围被包含在[]号中,例如查询5分钟内的样本数据,可用下列表达式
prometheus_http_requests_total{handler="/-/reload",code="200"}[5m]
在Prometheus的表达式浏览器中,我们可以看到,返回的数据包含了5分钟内的所有采样结果。
除了使用m表示分钟以外,PromQL的时间范围选择器支持其它时间单位:
-
s - 秒
-
m - 分钟
-
h - 小时
-
d - 天
-
w - 周
-
y - 年
在时间序列的查询上,除了以当前时间为基准,也可以使用offset进行时间位移的操作。如以1小时前的时间点为基准,查询瞬时向量和5分钟内的范围向量:
prometheus_http_requests_total{handler="/-/reload",code="200"} offset 1h
prometheus_http_requests_total{handler="/-/reload",code="200"}[5m] offset 1h
三. 聚合操作
PromQL语言提供了不少内置的聚合操作符,用于对瞬时向量的样本进行聚合操作 ,形成一个新的序列。目前支持的聚合操作符如下:
-
sum (求和)
-
min (最小值)
-
max (最大值)
-
avg (平均值)
-
stddev (标准差)
-
stdvar (标准方差)
-
count (计数)
-
count_values (对value进行计数)
-
bottomk (后n条时序)
-
topk (前n条时序)
-
quantile (分位数)
聚合操作符有非常多的用途,例如可使用sum对返回结果进行汇总,得到一个总值 。
例如要计算所有接口的请求数量总和,可以用如下表达式:
sum(prometheus_http_requests_total{})
使用max,匹配其中样本值为最大的时间序列
max(prometheus_http_requests_total{})
使用avg,求出所有样本的平均值
avg(prometheus_http_requests_total{})
使用topk ,可显示匹配的前N条时间序列数据
topk (5,prometheus_http_requests_total{})
在聚合操作中,还可以在表达式中加上without或 by ,其中without用于在计算样本中移除列举的标签,而by正相反,结果向量中只保留列出的标签,其余标签则移除。
sum(prometheus_http_requests_total{}) without (code,handler,job)
sum(prometheus_http_requests_total{}) by (instance)