一个计算机技术爱好者与学习者

0%

Prometheus查询语言:PromQL

1. PromQL简介

Prometheus提供了一种称为PromQL(Prometheus查询语言)的功能查询语言,使用户可以实时选择和汇总时间序列数据。表达式的结果既可以显示为图形,也可以在Prometheus的表达式浏览器中显示为表格数据,也可以由外部系统通过HTTP API使用。

参考文档:

2. 基本概念

2.1. 指标(Metric)

指标是一种测量数据,通常由名称和一组标签组成。

指标(样本)格式:

1
metric_name [ {label_name="label_value"} ] value [ timestamp ]

指标说明:

  • metric_name:指标名称(本质是__name__的标签值),只能使用字母、数字、下划线和冒号,区分大小写,不能以下划线和数字开头
  • value:指标值,是一个float格式的数据
  • label_name:标签名称,只能使用字母、数字和下划线,区分大小写,不能以下划线和数字开头
  • label_value:标签值,字符串
  • timestamp:时间戳,类型为int64(从1970-01-01 00:00:00以来的毫秒数),timestamp可选,默认为当前时间
  • 注释:#号开头表示注释
  • 指标组:具有相同 metric_name 的样本必须按照一个组的形式排列,并且每一行必须是唯一的指标名称和标签键值对组合
  • 两种指标类型:Gauge是当前状态的数值,Counter是一个永远递增的数值。

指标示例:

1
2
http_requests_total{host="www.voidking.com", method="GET", status="200"} 34
http_requests_total{host="blog.voidking.com", method="GET", status="200"} 21

该指标组表示 HTTP GET 请求中状态码为 200 的计数,host 、method 和 status 是标签。

2.2. 时间序列(Time Series)

时间序列是一系列具有相同指标和标签组合的数据点,按时间排序。

Prometheus会将所有采集到的指标数据以时间序列(time-series)的方式保存在内存数据库中,并且定时保存到硬盘上。

时间序列示例:

1
2
3
http_request_total{host="www.voidking.com", method="GET", status="200"}@1434417560000 => 30
http_request_total{host="www.voidking.com", method="GET", status="200"}@1434417561000 => 34
http_request_total{host="www.voidking.com", method="GET", status="200"}@1434417562000 => 45

我们可以将time-series理解为一个数字矩阵,X轴是时间戳,Y轴是指标。

3. PromQL表达式

3.1. 基本选择器

基本选择器用于从 Prometheus 中选择特定的时间序列数据。它通过指标名称和标签条件来过滤数据。
例如:

1
http_requests_total{method="GET", status="200"}

这个表达式选择了当前时刻所有 HTTP GET 请求中状态码为 200 的时间序列,是瞬时数据(瞬时向量)。

Prometheus绘图时,只接受瞬时向量。

3.2. 操作符

PromQL 支持多种操作符,用于在表达式中进行逻辑运算、比较和匹配。常见操作符有:

  • ==:等于
  • !=:不等于
  • =~:正则表达式匹配
  • !~:不匹配正则表达式
  • andor:逻辑与、逻辑或

PromQL 中的所有正则表达式都使用RE2语法

例如:

1
http_requests_total{method=~"POST|PUT"} and status="500"

这个表达式选择了所有方法为 POST 或 PUT 且状态码为 500 的时间序列。

3.3. 时间范围选择

PromQL 允许我们选择特定时间范围内的数据,用于计算速率、增量等。例如:

1
http_requests_total[5m]

这个表达式选择了过去 5 分钟内的 HTTP 请求计数,是范围数据(范围向量)。

持续时间以数字指定,后面跟着单位。
单位标识:s - seconds,m - minutes,h - hours,d - days,w - weeks,y - years

3.4. 偏移量

偏移量允许更改查询中各个瞬时向量和范围向量的时间偏移。

1
2
3
4
http_requests_total offset 5m
sum(http_requests_total{method="GET"} offset 5m) // GOOD.
sum(http_requests_total{method="GET"}) offset 5m // INVALID.
rate(http_requests_total[5m] offset 1w)

3.5. 聚合函数

聚合函数用于对时间序列数据进行聚合计算,从而获得更高级别的洞察力。常见的聚合函数有:

  • sum:求和,所有指标名相同的指标求和
  • avg:平均值,所有指标名相同的指标求平均值
  • min:最小值,所有指标名相同的指标求最小值
  • max:最大值,所有指标名相同的指标求最大指
  • count:计数,计算指标名相同的指标的数量

例如:

1
sum(http_requests_total) by (method)

这个表达式按照 HTTP 请求方法对请求计数进行了求和。

使用 by 关键字,我们可以按照指定的标签对时间序列数据进行分组,从而进行聚合操作。

3.6. 向量操作和标量操作

PromQL 支持对向量(time series vectors)和标量(scalar)之间进行操作。例如:

1
http_requests_total + 100

这个表达式将每个时间序列的值都增加了 100。

3.7. 函数调用

PromQL 提供了多种内置函数,用于执行各种操作,如计算速率、计算增量、应用分位数等。常见函数有:

  • rate:计算速率,根据指定的时间范围内的第一个数据点和最后一个数据点的值,计算它们之间的增加量,并将结果转化为每秒的速率,结果单位是数据单位 per second
  • increase:计算增量,根据指定的时间范围内的第一个数据点和最后一个数据点的值,计算它们之间的增加量
  • histogram_quantile:计算分位数,计算数据在不同区间的频率
  • irate:计算速率,根据最后两个点的差值来计算增加量,并将结果转化为每秒的速率,结果单位是数据单位 per second。此时的数据范围不是用来计算的,而是用来限制向前找点的时间范围的,时间范围内没有点,这个点的计算就放弃了。

例如:

1
rate(http_requests_total[1h])

这个表达式计算了过去 1 小时内 HTTP 请求计数的速率。
函数通常需要接受一个或多个参数,参数可以是指标、标量、向量等。上例中的http_requests_total[1h]就是参数。

1
increase(http_requests_total[5m])

这个表达式计算了过去 5 分钟内 HTTP 请求的增量。

1
histogram_quantile(0.95, http_request_duration_seconds_bucket)

这个表达式计算了 HTTP 请求持续时间的分布中的 95 分位数值,即在所有持续时间中,95% 的请求的持续时间小于等于这个值。

3.8. 注释

在 PromQL 中,我们可以使用 # 来添加注释,以提高查询的可读性。例如:

1
2
# Calculate the error rate of HTTP requests
rate(http_requests_total{status=~"5.."}[1h])

这个表达式计算了过去 1 小时内 HTTP 请求状态码以 “5” 开头(表示服务器错误)的时间序列的速率。

3.9. 子查询

子查询对给定的范围进行即时查询。子查询的结果是范围向量。
语法:

1
<instant_query> '[' <range> ':' [<resolution>] ']' [ offset <duration> ]

resolution是可选的。默认值为全局评估间隔。

4. 例子

4.1. 简单时间序列查询

1
2
3
4
5
6
http_requests_total
{__name__="http_requests_total"}
http_requests_total{job="apiserver", handler="/api/comments"}
http_requests_total{job="apiserver", handler="/api/comments"}[5m]
http_requests_total{job=~".*server"}
http_requests_total{status!~"4.."}

4.2. 子查询

1
2
rate(http_requests_total[5m])[30m:1m]
max_over_time(deriv(rate(distance_covered_total[5s])[30s:5s])[10m:])

4.3. 函数运算等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
rate(http_requests_total[5m])

sum by (job) (
rate(http_requests_total[5m])
)

(instance_memory_limit_bytes - instance_memory_usage_bytes) / 1024 / 1024

sum by (app, proc) (
instance_memory_limit_bytes - instance_memory_usage_bytes
) / 1024 / 1024

topk(3, sum by (app, proc) (rate(instance_cpu_time_ns[5m])))

count by (app) (instance_cpu_time_ns)