PromQL向量运算
背景:使用PromQL在prometheus中进行数据查询时,有时候会涉及对多个向量进行加减乘除运算,此时对向量有一些使用规范,否则要么直接报错,要么出现错误结果。
实验数据
#PromQL1
WriteCount{__MEASURE__="disk",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas",ip="10.94.14.102"}
#向量1
{__INST__="30b1bf0516cc57e382136a1063f494da3055cbc01cba4390865782add1cfdbcf", __MEASURE__="disk", __NAME__="WriteCount", appid="drp-service-reservation-admin-overseas", clustercode="sin01-prod001", group="sgp-1", hostip="10.1.120.58", idc="sin01-prod001", ip="10.94.14.102", label="/", name="baymax", podname="drp-service-reservation-admin-overseas-sgp-1-0", poduid="de61c60d-d27d-11eb-b60a-0263c97cac90", type="vm", zonecode="FREIGN-SGP"}
{__INST__="30b1bf0516cc57e382136a1063f494da3055cbc01cba4390865782add1cfdbcf", __MEASURE__="disk", __NAME__="WriteCount", appid="drp-service-reservation-admin-overseas", clustercode="sin01-prod001", group="sgp-1", hostip="10.1.120.58", idc="sin01-prod001", ip="10.94.14.102", label="/home/service/var", name="baymax", podname="drp-service-reservation-admin-overseas-sgp-1-0", poduid="de61c60d-d27d-11eb-b60a-0263c97cac90", type="vm", zonecode="FREIGN-SGP"}
#PromQL2:
Liveness{__MEASURE__="system",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas"}
#向量2
{__INST__="de7cedf3-d27d-11eb-b60a-0263c97cac90", __MEASURE__="system", __NAME__="Liveness", appid="drp-service-reservation-admin-overseas", clustercode="sin01-prod001", group="sgp-1", hostip="10.1.122.48", ip="10.94.212.113", podname="drp-service-reservation-admin-overseas-sgp-1-1", poduid="de7cedf3-d27d-11eb-b60a-0263c97cac90", servertype="container", type="vm", zonecode="FREIGN-SGP"}
#PromQL3:
ReadCount{__MEASURE__="disk",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas",ip="10.94.14.102"}
#向量3:
{__INST__="30b1bf0516cc57e382136a1063f494da3055cbc01cba4390865782add1cfdbcf", __MEASURE__="disk", __NAME__="ReadCount", appid="drp-service-reservation-admin-overseas", clustercode="sin01-prod001", group="sgp-1", hostip="10.1.120.58", idc="sin01-prod001", ip="10.94.14.102", label="/", name="baymax", podname="drp-service-reservation-admin-overseas-sgp-1-0", poduid="de61c60d-d27d-11eb-b60a-0263c97cac90", type="vm", zonecode="FREIGN-SGP"}
{__INST__="30b1bf0516cc57e382136a1063f494da3055cbc01cba4390865782add1cfdbcf", __MEASURE__="disk", __NAME__="ReadCount", appid="drp-service-reservation-admin-overseas", clustercode="sin01-prod001", group="sgp-1", hostip="10.1.120.58", idc="sin01-prod001", ip="10.94.14.102", label="/home/service/var", name="baymax", podname="drp-service-reservation-admin-overseas-sgp-1-0", poduid="de61c60d-d27d-11eb-b60a-0263c97cac90", type="vm", zonecode="FREIGN-SGP"}
如上向量1,向量3有15个标签,向量1,3都有有“label”,“idc”,“name” 特有的标签,而向量2没有
向量2有13个标签,向量2有“servertype”的标签,而向量1,3则没有。
向量匹配模式
promql中向量与向量之间进行运算时会基于默认的匹配规则:“依次找到与左边向量元素匹配的右边向量元素进行运算,如果没有找到匹配元素,则直接丢弃。”这里的“匹配”:是表示标签完全一致。
匹配模式分三种:
- 一对一匹配(左、右向量的标签名完全一致(标签值可能不同))
标签名和标签值完全相同,则直接运算,否则要使用ignoring或者on修饰符 - 多对一匹配(左边向量标签是右边向量标签的超集) --使用group_left修饰符
指的是右边向量的每一个向量元素可以与左边向量的多个元素匹配的情况 - 一对多匹配(右边向量的标签是左边向量标签的超集) --使用group_right修饰符
指的是左边向量的每一个向量元素可以与右边向量的多个元素匹配的情况
注意:
1.多对一和一对多两种匹配模式指的是“一”侧的每一个向量元素可以与"多"侧的多个元素匹配的情况。在这种情况下,必须使用 group 修饰符:group_left 或者 group_right 来确定哪一个向量具有更高的基数(充当“多”的角色)。
2.“匹配上”的含义表示多个向量的标签名和标签值要能完全一致才称之为匹配上,才能进行相应运算。
比如:
#“数据1”
method_code:http_errors:rate5m{method="get", code="500"} 24
method_code:http_errors:rate5m{method="get", code="404"} 30
method_code:http_errors:rate5m{method="put", code="501"} 3
method_code:http_errors:rate5m{method="post", code="500"} 6
method_code:http_errors:rate5m{method="post", code="404"} 21
##“数据2”
method:http_requests:rate5m{method="get"} 600
method:http_requests:rate5m{method="del"} 34
method:http_requests:rate5m{method="post"} 120
如上:
如果忽略code这个标签,则数据2中的“get”,“post”类型的请求都可以与数据1中的两条数据进行匹配
所以如下两个查询是等效的:
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
method:http_requests:rate5m / ignoring(code) group_right method_code:http_errors:rate5m
一对一匹配
语法:
向量表达式1 运算符 向量表达式2
//左右向量标签数量和标签名完全一致
向量表达式1 运算符 ignoring(标签1[,标签2,...]) 向量表达式2
//左右向量标签数量相同,但个别标签名不相同,可以使用ignoring()忽略那些标签名不相同的字段
向量表达式1 运算符 on(标签1[,标签2,...]) 向量表达式2
//左右向量标签数量相同,但大部分标签名不相同,可以使用on()指定哪些标签来进行匹配
由于向量1和向量3 标签数量和标签名称完全一致,所以可以直接进行运算。
实例:promql1 + promql3
#promql1 + promql3
ReadCount{__MEASURE__="disk",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas",ip="10.94.14.102"} + WriteCount{__MEASURE__="disk",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas",ip="10.94.14.102"}
查询结果:
如果要将Promql1 与 Promql2 进行运算,则涉及到一对多或者多对一的匹配模式。
因为涉及向量的标签数量或者标签名不相同。
多对一匹配
语法:
向量表达式1 运算符 ignoring(标签1[,标签2,...]) group_left(标签1[,标签2,...]) 向量表达式2
//左边向量的标签多于右边向量的标签,忽略某些标签进行匹配
或者
向量表达式1 运算符 on(标签1[,标签2,...]) group_left(标签1[,标签2,...]) 向量表达式2
//指定在哪些标签上进行匹配
实例:promql1 + promql2
WriteCount{__MEASURE__="disk",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas",ip="10.94.14.102"} + on(ip) group_left Liveness{__MEASURE__="system",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas"}
查询结果:
一对多匹配
语法:
向量表达式1 运算符 ignoring(标签1[,标签2,...]) group_right(标签1[,标签2,...]) 向量表达式2
//忽略某些标签进行匹配
或者
向量表达式1 运算符 on(标签1[,标签2,...]) group_right(标签1[,标签2,...]) 向量表达式2
//指定在哪些标签上进行匹配
右边向量的指标标签比左边向量的标签要多
实例:PromQL2 + PromQL1
Liveness{__MEASURE__="system",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas"} + on(ip) group_right WriteCount{__MEASURE__="disk",zonecode=~"FREIGN-SGP",appid=~"drp-service-reservation-admin-overseas",ip="10.94.14.102"}
结果:
附
PromQL官方帮助文档