跳转至

PromQL详解(三)

PromQL详解(三)

前面已我们已经把操作符中的 算术运算符关系运算符 讲完了,我们现在来详细的讲一下 向量匹配逻辑运算符

向量匹配

在变量与瞬时向量之间使用运算符的可以满足很多运算需求,但在俩个瞬时向量之间使用运算符时,到底应该如何使用样本适用于其他样本,这种瞬时向量之间的匹配称为 向量匹配

Prometheus 提供俩种向量匹配模式: One-To-One and Many-To-One(One-To-Many)

  1. one to one

就是一对一的向量匹配,它从运算符的俩则表达式中获取瞬时向量,依次比较并找出唯一对唯一条序列行匹配,如果过俩个序列具有完全相同的标签和对应的值,则匹配返回向量结果。

表达式: 向量1 <运算符> 向量2

范例:

process_open_fds{instance="localhost:19100",job="prometheus"} / process_max_fds{instance="localhost:19100",job="prometheus"}

上面的表达式是指除了Label __name__ 中的指标名称之外,具有完全相同标签的样本被匹配在一起,也就是说俩个指标中都有标签{instance="localhost:19100",job="prometheus"} ,则匹配返回向量结果。

如果运算符两侧表达式标签不一致,可以使用关键字 onignoring 修改标签间的匹配行为;on 用于在指定标签上进行匹配,ignoring 可以忽略指定标签进行匹配。

表达式为:

<向量 表达式><选项> ignoring (<标签 列表>) <向量 表达式>

<向量 表达式><选项> on (<标签 列表>) <向量 表达式>

范例:

sum by (instance,job) (rate(node_cpu_seconds_total{mode="idle"}[5m])) / on (instance,job) sum by (instance,job) (rate(node_cpu_seconds_total[5m]))

上面的表达式中使用 rata 函数 计算5分钟内的平均增加率,其返回的是结果是 float值,其中使用了运算符聚合 sum 来计算签列表 Instance job 维度的所有匹配指标。,并且使用了 on 修改了标签匹配。

算术运算符返回的是计算结果得值,如果使用俩个瞬时向量使用关系运算的话,结果返回的值是左侧表达式的值。如: process_open_fds < process_max_fds process_max_fds>process_open_fds,其返回结果就是左侧的运算结果。

sum by (instance,job) (rate(node_cpu_seconds_total{mode="idle"}[5m])) / ignoring (instance) sum by (instance,job) (rate(node_cpu_seconds_total[5m]))

上面的表达式中与上面唯一不同是使用了向量匹配中的 ignoring ,用来忽略 instance 标签的时间序列,其返回的时间序列元素中会去掉标签 instance,如果同时 ignoring instance job,这是左侧时间序列元素中则返回一个空指标, 右侧同样返回向量数据 float 值。

  1. Many-To-One(One-To-Many)

多对一和一对多的匹配模式,可以理解向量元素中的一个样本数据匹配到了多个样本数据标签。在使用此匹配模式的时候,需要使用 group_left 或者 group_right修饰符明确指定哪一个向量具有更高的基数,也就是说左或者右决定了哪边 的向量具有更高的子集。

表达式为:

<向量 表达式><选项> ignoring (<标签 列表>) group_left (<标签 列表>) <向量 表达式>

<向量 表达式><选项> ignoring (<标签 列表>) group_right (<标签 列表>) <向量 表达式>

<向量 表达式><选项> on (<标签 列表>) group_left (<标签 列表>) <向量 表达式>

<向量 表达式><选项> on (<标签 列表>) group_right (<标签 列表>) <向量 表达式>

范例:

one-to-many

sum without (cpu) (rate(node_cpu_seconds_total[5m])) / ignoring (mode) group_left sum without (mode,cpu) (rate(node_cpu_seconds_total[5m]))

many-to-one

sum without (cpu,cpu) (rate(node_cpu_seconds_total[5m])) / ignoring (cpu) group_right sum without (cpu) (rate(node_cpu_seconds_total[5m]))

同样,上面的表达式中继续使用 rata 函数 计算5分钟内的平均增加率。

输出结果为左侧每组中的每个不同表达模式标签生产了一个输出样本。

左侧使用 sum 聚合运算符 与关键 without 去除左侧 cpu 标签,保留剩余标签。

右侧使用关键字 ignoring 忽略指定标签子集 mode ,保留剩余标签子集,定义左子集基数更高,同样是 sum 聚合运算符 中的关键字 without 去除 子集中的 mode cpu ,保留剩余标签子集。

其实上面的运算针对简单的警报系统 rules 规则来讲,一对一匹配已经足够了,一般情况下用不到如此复杂的运算。

逻辑运算符

Prometheus 提供了三种逻辑运算符:and or unless,逻辑运算符只能用于向量与向量之间运算,同时所有的逻辑运算符都是多对多的方式工作,也是唯一可以工作与多对多的运算符。 不同于算术运算符和比较运算符,因为没有执行任何数学计算,所以侧重点主要是描述一个组内是否包含样本。

vector1 and vector2

and 逻辑运算符会产生一个由 vector1 的元素组成的心的向量。该向量包含 vector1 中完全匹配 vector2 中的元素。

范例:

apiserver_request_duration_seconds_bucket{resource="prometheuses",le=~"2|3|10"} and apiserver_request_duration_seconds_bucket{resource="prometheuses",le=~"5|3|10"}

vector1 or vector2

or 逻辑运算符会产生一个新的向量,这个向量包含 vector1 的所有原始元素(标签集+值)的向量,以及 vector2 中没有与 vector1匹配标签集的所有元素组成。 如果vector2 中如果没有匹配的 vector1 中的子集元素,则返回结果为 0,可以在位数用 算术运算符 * 来判断。

表达式:

apiserver_request_duration_seconds_bucket{resource="prometheuses",le=~"20|30|40",verb="LIST"}or apiserver_request_duration_seconds_bucket{resource="prometheuses",le=~"20|40|60",verb="LIST"} * 0

vector1 unless vector2

unless 逻辑运算会产生一个由 vector1 的元素组成的向量,如果在 vector2 完全匹配的标签集元素,则删除俩个向量中所有匹配的元素。

表达式:

apiserver_request_duration_seconds_bucket{resource="prometheuses",le=~"20|30|40"} unless apiserver_request_duration_seconds_bucket{resource="prometheuses",le=~"30|40|60"}

apiserver_request_duration_seconds_bucket{resource="prometheuses",le=~"10|20|30"} unless apiserver_request_duration_seconds_bucket{resource="prometheuses",le=~"30|40|60"}