向量与向量之间进行运算操作时会基于默认的匹配规则:依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行运算,如果没找到匹配元素,则直接丢弃。
接下来将介绍在 PromQL 中有两种典型的匹配模式:一对一(one-to-one),多对一(many-to-one)或一对多(one-to-many)。
一对一向量匹配
一对一的向量匹配会从操作符的每一边表达式找到一对唯一的样本值。在默认情况下,这是遵循vector1 <operator> vector2
格式的操作。
在操作符两边表达式标签不一致的情况下,可以使用 on(label list)或者 ignoring(label list)来修改便签的匹配行为。ignoring 关键字允许在匹配时忽略某些标签,而 on 关键字允许将考虑的标签集减少到提供的列表:
<vector expr> <bin-op> ignoring(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) <vector expr>
复制代码
比如这样的数据样本:
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
method:http_requests:rate5m{method="get"} 600
method:http_requests:rate5m{method="del"} 34
method:http_requests:rate5m{method="post"} 120
复制代码
下面我们看一个查询的例子。
method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
复制代码
这该表达式会返回在过去 5 分钟内,HTTP 请求状态码为 500 的在所有请求中的比例。如果没有使用 ignoring(code),操作符两边表达式返回的瞬时向量中将找不到任何一个标签完全相同的匹配项。
同时由于 method 为 put 和 del 的样本找不到匹配项,因此不会出现在结果当中。
{method="get"} 0.04 // 24 / 600
{method="post"} 0.05 // 6 / 120
复制代码
一对多或者多对一向量匹配
多对一和一对多匹配是指“一”上的每个向量元素都可以与“多”上的多个元素匹配。这必须使用 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 指定左向量具有更好的基数。
最终的运算结果如下:
{method="get", code="500"} 0.04 // 24 / 600
{method="get", code="404"} 0.05 // 30 / 600
{method="post", code="500"} 0.05 // 6 / 120
{method="post", code="404"} 0.175 // 21 / 120
复制代码
多对一和一对多匹配是应该仔细考虑的高级用例。通常,正确使用 ignoring(<labels>) 可以得到预期的结果。
评论