Prometheus 的查询语言支持基本的逻辑和算术运算符。对于两个瞬时向量之间的运算,可以修改匹配行为。
Prometheus 中存在以下二元算术运算符
+
(加法)-
(减法)*
(乘法)/
(除法)%
(取模)^
(幂/指数)二元算术运算符定义在标量/标量、向量/标量和向量/向量值对之间。
两个标量之间,行为很明显:它们计算为另一个标量,该标量是将运算符应用于两个标量操作数的结果。
瞬时向量和标量之间,该运算符应用于向量中每个数据样本的值。例如,如果时间序列瞬时向量乘以 2,则结果是另一个向量,其中原始向量的每个样本值都乘以 2。指标名称被删除。
两个瞬时向量之间,二元算术运算符应用于左侧向量中的每个条目及其在右侧向量中的匹配元素。结果将传播到结果向量中,分组标签成为输出标签集。指标名称被删除。在右侧向量中找不到匹配条目的条目不属于结果。
Prometheus 中存在以下以弧度为单位工作的三角二元运算符
atan2
(基于 https://pkg.go.dev/math#Atan2)三角运算符允许使用向量匹配在两个向量上执行三角函数,而这是普通函数无法实现的。它们的行为与算术运算符相同。
Prometheus 中存在以下二元比较运算符
==
(等于)!=
(不等于)>
(大于)<
(小于)>=
(大于或等于)<=
(小于或等于)比较运算符定义在标量/标量、向量/标量和向量/向量值对之间。默认情况下,它们会进行过滤。可以通过在运算符后提供 bool
来修改其行为,这将为该值返回 0
或 1
,而不是进行过滤。
两个标量之间,必须提供 bool
修饰符,这些运算符将产生另一个标量,该标量要么是 0
(false
),要么是 1
(true
),具体取决于比较结果。
瞬时向量和标量之间,这些运算符应用于向量中每个数据样本的值,并且比较结果为 false
的向量元素将从结果向量中删除。如果提供了 bool
修饰符,则将被删除的向量元素的值为 0
,而将被保留的向量元素的值为 1
。如果提供了 bool
修饰符,则指标名称将被删除。
两个瞬时向量之间,这些运算符默认情况下充当过滤器,应用于匹配的条目。表达式不为真或在表达式的另一侧找不到匹配项的向量元素将从结果中删除,而其他元素将传播到结果向量中,分组标签成为输出标签集。如果提供了 bool
修饰符,则将被删除的向量元素的值为 0
,而将被保留的向量元素的值为 1
,分组标签再次成为输出标签集。如果提供了 bool
修饰符,则指标名称将被删除。
这些逻辑/集合二元运算符仅在瞬时向量之间定义
and
(交集)or
(并集)unless
(补集)vector1 and vector2
生成一个向量,该向量由 vector1
中在 vector2
中存在标签集完全匹配的元素的元素组成。其他元素被删除。指标名称和值从左侧向量继承。
vector1 or vector2
生成一个向量,该向量包含 vector1
的所有原始元素(标签集 + 值),另外还包含 vector2
中在 vector1
中没有匹配标签集的所有元素。
vector1 unless vector2
生成一个向量,该向量由 vector1
中在 vector2
中没有标签集完全匹配的元素的元素组成。两个向量中的所有匹配元素都被删除。
向量之间的操作尝试在右侧向量中为左侧向量的每个条目找到匹配的元素。有两种基本的匹配行为类型:一对一和多对一/一对多。
这些向量匹配关键字允许在具有不同标签集的序列之间进行匹配,前提是
on
ignoring
提供给匹配关键字的标签列表将决定如何组合向量。示例可以在一对一向量匹配和多对一和一对多向量匹配中找到
这些分组修饰符启用多对一/一对多向量匹配
group_left
group_right
可以将标签列表提供给分组修饰符,其中包含要包含在结果指标中的“一侧”的标签。
多对一和一对多匹配是应该仔细考虑的高级用例。通常,正确使用 ignoring(<labels>)
可以提供所需的结果。
分组修饰符只能用于比较和算术。and
、unless
和 or
等操作默认与右侧向量中的所有可能条目匹配。
一对一在操作的每一侧找到唯一的条目对。在默认情况下,这是遵循格式 vector1 <operator> vector2
的操作。如果两个条目具有完全相同的标签集和对应的值,则它们匹配。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)
,则不会有匹配,因为指标不共享相同的标签集。方法为 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>
与 group 修饰符一起提供的标签列表包含来自“一”侧的附加标签,这些标签将包含在结果指标中。对于 on
,一个标签只能出现在列表中的一个。结果向量的每个时间序列都必须是唯一可识别的。
示例查询
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
在这种情况下,左向量每个 method
标签值包含多个条目。因此,我们使用 group_left
来指示这一点。右侧的元素现在与左侧具有相同 method
标签的多个元素匹配。
{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
Prometheus 支持以下内置聚合操作符,这些操作符可用于聚合单个瞬时向量的元素,从而生成一个具有聚合值的新向量,该向量的元素更少。
sum
(计算维度上的总和)min
(选择维度上的最小值)max
(选择维度上的最大值)avg
(计算维度上的平均值)group
(结果向量中的所有值均为 1)stddev
(计算维度上的总体标准偏差)stdvar
(计算维度上的总体标准方差)count
(计算向量中的元素数量)count_values
(计算具有相同值的元素的数量)bottomk
(按样本值排序的最小 k 个元素)topk
(按样本值排序的最大 k 个元素)quantile
(计算维度上的 φ-分位数 (0 ≤ φ ≤ 1))limitk
(采样 n 个元素)limit_ratio
(如果 𝑟 > 0
,则采样具有大约 𝑟 比率的元素,如果 𝑟 = -(1.0 - 𝑟)
,则采样此类样本的补集)这些操作符可以用于聚合所有标签维度,或者通过包含 without
或 by
子句来保留不同的维度。这些子句可以在表达式之前或之后使用。
<aggr-op> [without|by (<label list>)] ([parameter,] <vector expression>)
或
<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
label list
是一个未加引号的标签列表,可以包含尾随逗号,即 (label1, label2)
和 (label1, label2,)
都是有效的语法。
without
从结果向量中删除列出的标签,而所有其他标签都保留在输出中。 by
执行相反的操作,并删除未在 by
子句中列出的标签,即使它们的标签值在向量的所有元素之间都相同。
parameter
仅对于 count_values
、quantile
、topk
、bottomk
、limitk
和 limit_ratio
是必需的。
count_values
每个唯一的样本值输出一个时间序列。每个序列都有一个额外的标签。该标签的名称由聚合参数给出,标签值是唯一的样本值。每个时间序列的值是该样本值出现的次数。
topk
和 bottomk
与其他聚合器不同,因为结果向量中返回输入样本的子集,包括原始标签。by
和 without
仅用于对输入向量进行分组。
limitk
和 limit_ratio
也返回输入样本的子集,包括结果向量中的原始标签,这些是实验性操作符,必须使用 --enable-feature=promql-experimental-functions
启用。
quantile
计算 φ-分位数,即在聚合的维度中,在 N 个指标值中排名第 φ*N 位的值。 φ 作为聚合参数提供。 例如,quantile(0.5, ...)
计算中位数,quantile(0.95, ...)
计算第 95 个百分位数。 对于 φ = NaN
,返回 NaN
。 对于 φ < 0,返回 -Inf
。 对于 φ > 1,返回 +Inf
。
示例
如果指标 http_requests_total
的时间序列按 application
、instance
和 group
标签展开,我们可以通过以下方式计算每个应用程序和组的所有实例中看到的 HTTP 请求总数:
sum without (instance) (http_requests_total)
这等效于:
sum by (application, group) (http_requests_total)
如果我们只对所有应用程序中看到的 HTTP 请求总数感兴趣,我们可以简单地写:
sum(http_requests_total)
要计算每个构建版本中运行的二进制文件的数量,我们可以写:
count_values("version", build_version)
要获取所有实例中最大的 5 个 HTTP 请求计数,我们可以写:
topk(5, http_requests_total)
要采样 10 个时间序列,例如检查标签及其值,我们可以写:
limitk(10, http_requests_total)
要确定性地采样大约 10% 的时间序列,我们可以写:
limit_ratio(0.1, http_requests_total)
鉴于 limit_ratio()
实现了一个确定性的采样算法(基于标签的哈希值),您可以获得上述样本的补集,即大约 90%,但精确地说是那些没有被 limit_ratio(0.1, ...)
返回的样本:
limit_ratio(-0.9, http_requests_total)
您还可以使用此功能来验证例如 avg()
是否是您样本值的代表性聚合,通过检查当与标准偏差相比时,两个样本子集的平均值之间的差异是否“小”。
abs(
avg(limit_ratio(0.5, http_requests_total))
-
avg(limit_ratio(-0.5, http_requests_total))
) <= bool stddev(http_requests_total)
以下列表显示了 Prometheus 中二元运算符的优先级,从最高到最低。
^
*
, /
, %
, atan2
+
, -
==
, !=
, <=
, <
, >=
, >
and
, unless
或
同一优先级级别的运算符是左结合的。例如,2 * 3 % 2
等效于 (2 * 3) % 2
。但是 ^
是右结合的,因此 2 ^ 3 ^ 2
等效于 2 ^ (3 ^ 2)
。
原生直方图是一项实验性功能。 摄入原生直方图必须通过 功能标志启用。 一旦摄入原生直方图,就可以查询它们(即使在再次禁用功能标志后)。 但是,对原生直方图的操作符支持仍然非常有限。
即使涉及到直方图样本,逻辑/集合二元运算符也能按预期工作。 它们仅检查向量元素的存在,并且不会根据元素的样本类型(浮点数或直方图)更改其行为。 count
聚合操作符的工作方式类似。
完全支持两个原生直方图之间的二元 +
和 -
运算符以及用于聚合原生直方图的 sum
和 avg
聚合操作符。 即使涉及的直方图具有不同的桶布局,也会自动适当地转换桶,以便可以执行操作。 (使用当前支持的桶模式,这始终是可能的。) 如果任何操作符必须聚合直方图样本和浮点样本的混合,则相应的向量元素将完全从输出向量中删除。
二元 *
操作符在原生直方图和浮点数之间以任何顺序工作,而二元 /
操作符可以在原生直方图和浮点数之间以精确的顺序使用。
所有其他操作符(以及上述操作符的未提及情况)的行为都没有意义。 它们要么将直方图样本视为值为 0 的浮点样本,要么(在标量和向量之间的算术运算的情况下)它们保持直方图样本不变。 在原生直方图成为稳定功能之前,此行为将更改为有意义的行为。
此文档是 开源的。 请通过提交问题或拉取请求来帮助改进它。