Prometheus通过指标名称(metrics name)以及对应的一组标签(label set)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而label则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤,聚合,统计从而产生新的计算后的一条时间序列。
PromQL时序数据查询语言,其提供对时间序列数据丰富的查询,聚合以及逻辑运算能力的支持。
一 基本查询
1. 基础查询示例
查询指标、查询指标和对应 label,查询指标并排除具体 label。查询如下:
// 1.普通查询 http_requests_total // 2.指定 label 查询 http_requests_total{instance="localhost:9090"} http_requests_total{instance!="localhost:9090"} // 3. 正则查询 // 使用label=~regx表示选择那些标签符合正则表达式定义的时间序列; // 反之使用label!~regx进行排除; http_requests_total{environment=~"staging|testing|development",method!="GET"}
以上查询返回值中只会包含该时间序列中的最新的一个样本值,这样的返回结果我们称之为瞬时向量。
2. 范围查询
区间向量表达式和瞬时向量表达式之间的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器
[]进行定义。http_request_total{}[1m] // 以下是查询五分钟的范围,返回 6 个点位 http_requests_total{code="200",handler="alerts",instance="localhost:9090",job="prometheus",method="get"}=[ 1@1518096812.326 1@1518096817.326 1@1518096822.326 1@1518096827.326 1@1518096832.326 1@1518096837.325 ]
注意这里为什么五分钟会返回六个点位,原因如下:
在 Prometheus 的查询中,表达式
http_request_total{}[1m] 返回了 6 个点位,而查询范围是 5 分钟,这种情况可以通过以下原因来解释:- 数据采集频率:
Prometheus 默认的采样间隔通常是 15 秒(可配置)。在 5 分钟的时间范围内,如果采样间隔为 15 秒,那么理论上会产生 5×6015=20155×60=20 个数据点。然而,返回的点位数量(6 个)可能是由于查询中指定了
[1m] 范围选择器,这意味着每个点位是基于过去 1 分钟的数据聚合,而不是直接返回所有原始采样点。- 时间序列聚合:
PromQL 的范围选择器(例如
[1m])会根据时间范围对数据进行聚合处理。具体来说,它会提取每分钟内的样本数据并生成一个点位。因此,查询结果中的每个点代表过去一分钟的数据,而不是所有原始样本。- 返回点位数量限制:
Prometheus 查询可能受到时间窗口和分辨率的限制。如果查询range 为 30min(6.-6.30),但是 step 为 25min,则会返回两个点,第一个点为6.时间戳(5.35-6 聚合),第二个点为 6.25 时间戳(6-6.25 聚合)
二 PromQL 操作符
1. 数学运算
node_memory_free_bytes_total / (1024 * 1024)
PromQL支持的所有数学运算符如下所示:
+ (加法) / - (减法)/ * (乘法)/ / (除法)/ % (求余)/^ (幂运算)2. 使用布尔运算过滤时间序列
// 内存使用率超过95%的主机 (node_memory_bytes_total - node_memory_free_bytes_total) / node_memory_bytes_total > 0.95 // 查看错误率不为 0 的接口 sum by(uri,status,exception)(increase(http_server_requests_seconds_count{status=~"5.*|4.*"}[$__interval])) != 0
Prometheus支持以下布尔运算符如下:
== (相等)!= (不相等)> (大于)< (小于)>= (大于等于)<= (小于等于)3. 匹配模式详解
向量与向量之间进行运算操作时会基于默认的匹配规则:依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行运算,如果没找到匹配元素,则直接丢弃。
接下来将介绍在PromQL中有两种典型的匹配模式:一对一(one-to-one),多对一(many-to-one)或一对多(one-to-many)。
3.1 一对一匹配
一对一匹配模式会从操作符两边表达式获取的瞬时向量依次比较并找到唯一匹配(标签完全一致)的样本值。默认情况下,使用表达式:
vector1 <operator> vector2
在操作符两边表达式标签不一致的情况下,可以使用on(label list)或者ignoring(label list)来修改便签的匹配行为。使用ignoreing可以在匹配时忽略某些便签。而on则用于将匹配行为限定在某些便签之内。
<vector expr> <bin-op> ignoring(<label list>) <vector expr> <vector expr> <bin-op> on(<label list>) <vector expr> eg: method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
3.2 一对多匹配
多对一和一对多两种匹配模式指的是“一”侧的每一个向量元素可以与"多"侧的多个元素匹配的情况。在这种情况下,必须使用group修饰符:group_left或者group_right来确定哪一个向量具有更高的基数(充当“多”的角色)。
<vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr> <vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr> <vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr> <vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>
多对一和一对多两种模式一定是出现在操作符两侧表达式返回的向量标签不一致的情况。因此需要使用ignoring和on修饰符来排除或者限定匹配的标签列表。
例如,使用表达式:
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
该表达式中,左向量
method_code:http_errors:rate5m包含两个标签method和code。而右向量method:http_requests:rate5m中只包含一个标签method,因此匹配时需要使用ignoring限定匹配的标签为code。 在限定匹配标签后,右向量中的元素可能匹配到多个左向量中的元素 因此该表达式的匹配模式为多对一,需要使用group修饰符group_left指定左向量具有更好的基数三 PromQL 聚合操作
PromQL 的聚合操作分为横向聚合 (跨标签维度)和纵向聚合 (跨时间维度),用于对时间序列数据进行降维分析或全局统计。
1. 横向聚合(跨标签维度分析)
横向聚合通过
by 或 without 子句对标签进行分组,适用于跨实例、服务等维度的全局统计。常见聚合操作符包括:sum():求和(如总请求量)
avg():计算平均值(如平均响应时间)
max()/min():获取极值(如最高CPU使用率)
count():统计时间序列数量
示例:按服务聚合请求量
sum by (job) (http_requests_total) # 按job标签分组汇总请求总量 [[2]][[6]] // 若需排除特定标签,可用 without sum without(instance) (http_requests_total) # 忽略实例差异,聚合同一服务的请求 [[3]][[7]]
2. 纵向聚合(跨时间维度分析)
纵向聚合专注于时间维度 ,对单条时间序列的多个时间点数据 进行统计。例如:
- 计算某接口过去1小时的总请求量(
sum_over_time)
- 分析某指标的峰值(
max_over_time)或均值(avg_over_time)
纵向聚合操作符包括:
sum_over_time():求和(如总请求量)
avg_over_time():计算平均值(如平均响应时间)
max_over_time()/min_over_time():获取极值(如最高CPU使用率)
四 PromQL 内置函数
常用的内置函数
1. 计算Counter指标增长率
Counter类型的监控指标其特点是只增不减,在没有发生重置(如服务器重启,应用重启)的情况下其样本值应该是不断增大的。
increase(v range-vector)函数是PromQL中提供的众多内置函数之一。其中参数v是一个区间向量,increase函数获取区间向量中的第一个后最后一个样本并返回其增长量。因此,可以通过以下表达式Counter类型指标的增长率:
increase(node_cpu[1m]) / 60 // rate函数可以直接计算区间向量v在时间窗口内平均增长速率。 // 等同于 rate(node_cpu[1m])
2. 统计Histogram指标的分位数
Histogram的分位数计算需要通过histogram_quantile(φ float, b instant-vector)函数进行计算。其中φ(0<φ<1)表示需要计算的分位数,如果需要计算中位数φ取值为0.5,以此类推即可。
以指标http_request_duration_seconds_bucket为例:
# HELP http_request_duration_seconds request duration histogram # TYPE http_request_duration_seconds histogram http_request_duration_seconds_bucket{le="0.5"} 0 http_request_duration_seconds_bucket{le="1"} 1 http_request_duration_seconds_bucket{le="2"} 2 http_request_duration_seconds_bucket{le="3"} 3 http_request_duration_seconds_bucket{le="5"} 3 http_request_duration_seconds_bucket{le="+Inf"} 3 http_request_duration_seconds_sum 6 http_request_duration_seconds_count 3
当计算90th时,使用如下表达式:
histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))