Prometheus--PromQL
参考:https://prometheus.io/docs/introduction/overview/
一、PromQL表达式
1.1、语言数据类型
PromQL表达式语言中,一个表达式或者子表达式可以表示以下4种类型之一:
- Instant vector:瞬时向量,一组time series(时间序列),每个time series包括了一个时间戳的数据点,所有time series数据点拥有相同的时间戳。
-
Range vector:范围向量,一组time series包含一个时间范围内的一组数据点。
- Scalar:标量,为一个浮点数值。
- String:字符串,为一个字符串数值。当前未使用。
1.2、Literals数据格式
1.2.1 String literals
字符串可以用单引号(‘’)、双引号(“”)或反引号(``)指定为文字。
PromQL遵循与Go相同的转义规则。在单引号或者双引号中,反斜杆开始转义序列,后面可以跟a, b, f, n, r, t, v, \。可以使用八进制(\nnn)或者十六进制(\xnn,\unnnn和\Unnnnnnnn)提供特定字符。
在反引号内没有处理转义。与Go不同的是,PromQL不会丢弃反引号中的换行符。
1.2.2 Float literals
浮点类型数值的格式为:-[.(digits)]
如:-2.43
1.3、Time series(时间序列)选择器
1.3.1 Instant vector selectors(即时矢量选择器)
瞬时向量选择器用于选择一组time series和每个time series对应的某一个时间戳数据点,唯一的要求是必须指定metric指标名。
例:查询指标名http_requests_total对应的所有time series表达式:
http_requests_total
可以通过在花括号 ( {}) 中附加一个逗号分隔的标签匹配器列表来进一步过滤这些时间序列。
例:仅选择具有http_requests_total 度量名称且job标签设置为prometheus且其 group标签设置为的时间序列canary:
http_requests_total{job="prometheus",group="canary"}
通过负匹配或正则表达式匹配tag选择时间序列,支持如下匹配运算符:
- = 等于
- != 不等于
- =~ 选择与提供的字符串进行正则表达式匹配的标签
- !~ 选择与提供的字符串不匹配的标签
例:选择staging,testing和development;除去GET的请求方法
http_requests_total{environment=~"staging|testing|development",method!="GET"}
匹配空标签值的标签匹配器还会选择根本没有设置特定标签的所有时间序列。同一个标签名称可以有多个匹配器。
矢量选择器必须指定一个名称或至少一个与空字符串不匹配的标签匹配器。以下表达式是非法的:
{job=~".*"} # Bad!
相反,这些表达式是有效的,因为它们都有一个不匹配空标签值的选择器
{job=~".+"} # Good! {job=~".*",method="get"} # Good!
标签匹配器也可以通过与内部标签匹配来应用于指标名称 __name__
例:表达式http_requests_total 等价于 {__name__="http_requests_total"},也可以使用=
( !=
, =~
, )以外的匹配器
!~以下表达式选择名称以 开头的所有指标job:
{__name__=~"job:.*"}
指标名称不能是关键字bool、on、ignoring和group_left之一group_right。以下表达式是非法的:
on{} # Bad!
此限制的解决方法是使用__name__标签
{__name__="on"} # Good!
1.3.2 Range vector selectors(范围矢量选择器)
范围向量字面量的工作方式类似于即时向量字面量,唯一区别是选择的时间序列是一个时间范围内的时序数据
从语法上讲,持续时间附加在[]向量选择器末尾的方括号 ( ) 中,以指定应该为每个结果范围向量元素获取多远的时间值
例:为所有时间序列选择了过去 5 分钟内记录的所有值,这些时间序列的指标名称http_requests_total和job标签设置为prometheus:
http_requests_total{job="prometheus"}[5m]
Time Durations(持续时间)
持续时间被指定为一个数字,后跟以下单位之一:
- ms 毫秒
- s 秒
- m 分钟
- h 小时
- d 天(假设一天总是 24 小时)
- w 周(假设一周总是7天)
- y 年(假设一年总是365天)
1.3.3 Offset modifier(偏移修改器)
Offset修改器允许修改查询中瞬时向量和范围向量的时间偏移。
例:返回 http_requests_total 相对于当前查询评估时间过去 5 分钟的值
http_requests_total offset 5m
注:offset修饰符总是需要立即跟随选择器
sum(http_requests_total{method="GET"} offset 5m) // GOOD sum(http_requests_total{method="GET"}) offset 5m // Bad
1.4、Subquery(子查询)
子查询允许针对给定的范围和分辨率运行即时查询。子查询的结果是一个范围向量。
[ : [ ]] [offset ]
注:
例:回过去30分钟CpuPercent 5m统计的rate(平均增长速率)值,精度是1分钟。
rate(CpuPercent{}[5m])[30m:1m]
二、PromQL运算符
PromQL支持基本的逻辑和算术运算。对于两个瞬时向量的运算,其结果可能影响匹配行为。
2.1、算数运算符
- +(加法)
- - (减法)
- * (乘法)
- / (除法)
- %(模数)
- ^(幂)
二进制算术运算符在标量/标量、向量/标量和向量/向量值对之间定义:
scalar/scalar:两个标量数值之间进行运算
vector/scalar:对瞬时向量里每个时间序列的数据点和标量数值进行运算
vector/vector:运算符应用于左边向量里的每个条目和右边向量匹配的条目(同一个time series),结果输出到结果向量里。metric指标名将被丢弃。右边向量未匹配的条目将不在结果向量里
2.2、比较运算符
- == (等于)
- != (不等于)
- > (大于)
- < (小于)
- >=(大于或等于)
- <=(小于或等于)
比较运算符在标量/标量、向量/标量和向量/向量值对之间定义。默认情况下,它们会过滤(满足条件的数据留下)。可以在operator后面带上bool标记来修改结果行为:返回0或者1
scalar/scalar:bool必须提供修饰符,并且这些运算符会产生另一个标量,即0( false) 或1 ( true),具体取决于比较结果
vector/scalar:比较瞬时向量里每个time series的值,过滤或者设置为bool
vector/vector:比较两个瞬时向量里每个time series的值,过滤或者设置为bool;如果左边向量里的time series没有在右边找到,则为比较失败
2.3、逻辑/集合运算符
逻辑/集合二元运算符仅在即时向量之间定义:
- and 过滤出两个向量里都有的时间序列
- or 过滤出两个向量里所有的时间序列
- unless 过滤出左边向量里,右边没有的时间序列
2.4、聚合运算符
Prometheus 支持以下内置聚合运算符,可用于聚合单个即时向量的元素,从而生成具有聚合值的元素更少的新向量
- sum (总和)
- min (最小值)
- max (最大值)
- avg (平均值)
- group (结果向量中的所有值都是1)
- stddev (计算维度上的总体标准偏差)
- stdvar (计算维度上的总体标准方差)
- count (计算向量中的元素个数)
- count_values(计算具有相同值的元素个数)
- bottomk (样本值的最小k个元素)
- topk (按样本值计算的最大k个元素)
- quantile (在维度上计算 φ-quantile (0 ≤ φ ≤ 1))
注:这些运算符既可以用于聚合所有标签维度,也可以通过包含without
orby
子句来保留不同的维度;这些子句可以在表达式之前或之后使用。
without将从结果中移除选定的tags,by则相反,将移除没有选定的tags。
其中count_values, quantile, topk, bottomk需要指定parameter,其他聚合函数不需要。
[without|by (
2.5、运算符优先级
- ^
- *,/,%
- +,-
- ==,!=,>,<,>=,<=
- and,unless
- or
三、PromQL内置函数
一些函数有默认参数,例如year(v=vector(time()) instant-vector). 这意味着有一个参数v是一个即时向量,如果没有提供,它将默认为表达式的值 vector(time())。
abs()
abs(v instant-vector) 返回输入向量,其中所有样本值都转换为其绝对值。
absent()
absent(v instant-vector) 如果传递给它的瞬时向量有任何元素,则返回一个空向量;如果传递给它的向量没有元素,则返回一个值为 1 的 1 元素向量
通常用于设置告警,判断给定的指标和标签没有数据时产生告警。
absent_over_time()
absent_over_time(v range-vector) 如果传递给它的范围向量有任何元素,则返回一个空向量;如果传递给它的范围向量没有元素,则返回一个值为 1 的 1 元素向量。
同absent(),常用于判断指标与标签组合,不存在于时间序列时报警。
ceil()
ceil(v instant-vector) 将所有元素的样本值四舍五入到最接近的整数。
changes()
changes(v range-vector) 计算给出的时间范围内,value是否发生变化,将发生变化时的条目作为即时向量返回
clamp()
clamp(v instant-vector, min scalar, max scalar) 设定所有元素的样本值的上限与下限
注:当min>max时,返回一个空向量:NaN if min or max is NaN
clamp_max()
clamp_max(v instant-vector, max scalar) 设定所有元素的样本值最大值为max,若 value > max 则修改max,value < max 则不变
clamp_min()
clamp_min(v instant-vector, min scalar) 设定所有元素的样本值最小值为min,若 value > min 则不变,value < min 则修改min
day_of_month()
day_of_month(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间的月份日期,返回值从 1 到 31。
day_of_week()
day_of_week(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间的星期几,返回值从 0 到 6,其中 0 表示星期日。
days_in_month()
days_in_month(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间该月的天数,返回值从 28 到 31。
delta()
delta(v range-vector) 计算范围向量中每个时间序列元素的第一个值和最后一个值之间的差,返回具有给定增量和等效标签的即时向量。增量被外推以覆盖范围向量选择器中指定的整个时间范围,因此即使样本值都是整数,也可以获得非整数结果。
注:delta()函数在可视化界面上只能用于仪表盘
例:返回现在和 2 小时前 CPU 温度的差异:
delta(cpu_temp_celsius{host="zeus"}[2h])
deriv()
deriv(v range-vector) 使用简单线性回归的方法计算时间序列在范围向量 中的每秒导数
注:deriv()函数在可视化页面上只能用于仪表盘
exp()
exp(v instant-vector) 计算v中所有元素的指数函数
特殊情况:
Exp(+Inf) = +Inf
Exp(NaN) = NaN
floor()
floor(v instant-vector) 将所有元素的样本值v向下舍入到最接近的整数。
histogram_quantile() 分位直方图
histogram_quantile(φ scalar, b instant-vector) 从instant vector中获取数据计算q分位(0<= q <=1)。b里的样本是每个桶的计数。每个样本必须具有标签le,表示桶的上限。直方图指标类型会自动提供了_bucket后缀和相应tags的time series。
使用rate()函数指定分位计算的时间窗口。
例1:一个直方图指标名:http_request_duration_seconds。计算其对应所有time series过去10分钟90分位数,使用如下表达式:
histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))
例2:为指标名http_request_duration_seconds对应的每个tags组合(每个time series)计算90分位数。为了聚合数据,比如使用sum()进行聚合,需要通过by子句包含le标签
histogram_quantile(0.9, sum(rate(http_request_duration_seconds_bucket[10m])) by (job, le))
例3:聚合所有time series
histogram_quantile(0.9, sum(rate(http_request_duration_seconds_bucket[10m])) by (le))
holt_winters()
holt_winters(v range-vector, sf scalar, tf scalar) 基于平滑因子sf和tf计算range_vector里time series的平滑值。sf越低则老数据越重要,tf越高则更多考虑数据的趋势。sf和tf的值介于0~1之间。
注:holt_winters()函数在可视化界面上只能用于仪表盘。
hour()
hour(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间的一天中的小时,返回值从 0 到 23。
idelta()
idelta(v range-vector) 计算范围向量中最后两个样本之间的差异,返回具有给定增量和等效标签的即时向量。
注:idelta()函数在可视化界面上只能用于仪表盘。
increase()
increase(v range-vector) 计算范围向量中时间序列的增量。单调性的中断(例如由于目标重新启动而导致的计数器重置)会自动调整。该增加被外推以覆盖范围向量选择器中指定的整个时间范围,因此即使计数器仅增加整数增量,也可以获得非整数结果。
例:返回范围向量中每个时间序列在过去 5 分钟内测量的 HTTP 请求数:
increase(http_requests_total{job="api-server"}[5m])
注:increase只能与counter类型指标一起使用。它是rate(v)乘以指定时间范围窗口下的秒数的语法糖,主要用于人类可读性。在记录规则中使用rate,以便每秒一致地跟踪增长。
irate()
irate(v range-vector) 计算范围向量中时间序列的每秒瞬时增长率。这是基于最后两个数据点。单调性的中断(例如由于目标重新启动而导致的计数器重置)会自动调整。
例:返回针对范围向量中每个时间序列的两个最近数据点的 HTTP 请求的每秒速率,最多可追溯 5 分钟:
irate(http_requests_total{job="api-server"}[5m])
注:irate仅应在绘制易失性、快速移动的计数器时使用。用于rate警报和缓慢移动的计数器,因为速率的短暂变化可以重置FOR子句,并且完全由罕见峰值组成的图形难以阅读。
当irate()与 聚合运算符(例如sum())或随时间聚合的函数(任何以 结尾的函数_over_time)结合时,总是先取一个irate(),然后再聚合。否则irate(),当目标重新启动时,无法检测到计数器重置。
label_join()
label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)
对于v中的每个时间序列,将连接所有src_labels using的所有值,separator并返回带有dst_label包含连接值的标签的时间序列。此函数中可以有任意数量src_labels。
例:返回一个向量,其中每个时间序列都有一个foo带有添加值的标签a,b,c:
label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")
label_replace()
label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)
对于v中的每个时间序列,将正则表达式regex与标签的值进行匹配src_label。如果匹配,则dst_label返回的时间序列中的标签值将是 的扩展replacement,以及输入中的原始标签。
正则表达式中的捕获组可以用 , 等引用$1。$2如果正则表达式不匹配,则返回时间序列不变。
例:返回带有a:c
标签service
和a
标签值的时间序列foo
:
label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")
ln()
ln(v instant-vector) 计算v中所有元素的自然对数
特殊情况:
ln(+Inf) = +Inf ln(0) = -Inf ln(x < 0) = NaN ln(NaN) = NaN
log2()
log2(v instant-vector) 计算v中所有元素的二进制对数
特殊情况:等价于ln
log10()
log10(v instant-vector) 计算v中所有元素的十进制对数
特殊情况:等价于ln
minute()
minute(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间的小时分钟,返回值从 0 到 59。
month()
month(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间的一年中的月份,返回值从 1 到 12,其中 1 表示一月。
predict_linear()
predict_linear(v range-vector, t scalar) 根据范围向量,使用简单线性回归的方法预测从现在开始的到未来t秒的时间序列的值
注:predict_linear()函数在可视化界面上只能用于仪表盘。
rate()
rate(v range-vector) 计算范围向量中时间序列的每秒平均增长率。单调性的中断(例如由于目标重新启动而导致的计数器重置)会自动调整。此外,计算推断到时间范围的末端,允许错过刮擦或刮擦周期与该范围的时间段的不完美对齐。
例:返回在过去 5 分钟内测量的每秒 HTTP 请求速率,范围向量中的每个时间序列:
rate(http_requests_total{job="api-server"}[5m])
注:rate()只能与counter类型指标一起使用。它最适合警报和缓慢移动计数器的图形。
当rate()与聚合运算符(例如sum())或随时间聚合的函数(任何以 结尾的函数_over_time)结合时,总是先取一个rate(),然后再聚合。否则rate(),当您的目标重新启动时,无法检测到计数器重置。
resets()
resets(v range-vector) 对于每个输入时间序列,resets(v range-vector)将提供的时间范围内的计数器重置次数作为即时向量返回。两个连续样本之间值的任何减少都被解释为计数器复位。
注:resets()只能作用于counter类型指标
round()
round(v instant-vector, to_nearest=1 scalar) 将所有元素的样本值四舍五入为v最接近的整数。平局通过四舍五入解决。可选to_nearest参数允许指定样本值应该四舍五入的最接近的倍数。这个倍数也可以是分数。默认为1。
scalar()
scalar(v instant-vector) 给定一个单元素输入向量,scalar(v instant-vector)以标量形式返回该单元素的样本值。如果输入向量没有恰好一个元素,scalar将返回NaN
sgn()
sgn(v instant-vector) 返回一个向量,其中所有样本值都转换为它们的符号,定义如下:如果 v 为正则为 1,如果 v 为负则为 -1,如果 v 等于 0,则为 0。
sort()
sort(v instant-vector) 返回按样本值升序排序的向量元素。
sort_desc()
sort_desc(v instant-vector) 与sort()相同,但按降序排序。
sqrt()
sqrt(v instant-vector) 计算v中所有元素的平方根
time()
time() 返回自 1970 年 1 月 1 日 UTC 以来的秒数。请注意,这实际上并不返回当前时间,而是要计算表达式的时间。
timestamp()
timestamp(v instant-vector) 返回给定向量的每个样本的时间戳,作为自 1970 年 1 月 1 日 UTC 以来的秒数(Prometheus 2.0+)
vector()
vector(s scalar) 将标量s作为没有标签的向量返回
year()
year(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间的年份。
_over_time()
以下函数允许随时间聚合给定范围向量的每个系列,并返回具有每个系列聚合结果的即时向量:
- avg_over_time(range_vector) 指定区间内所有点的平均值
- min_over_time(range_vector) 指定区间内所有点的最小值
- max_over_time(range_vector) 指定区间内所有点的最大值
- sum_over_time(range_vector) 指定区间内所有值的总和
- count_over_time(range_vector) 指定区间内所有值的计数
- quantile_over_time(s scalar, range_vector) 指定区间内的值的 φ 分位数 (0 ≤ φ ≤ 1)
- stddev_over_time(range_vector) 指定区间内值的总体标准差
- stdvar_over_time(range_vector) 指定区间内值的总体标准方差
- last_over_time(range-vector) 指定区间内最近的点值
- present_over_time(range-vector) 指定间隔内任何系列的值 1
注:指定区间中的所有值在聚合中具有相同的权重,即使这些值在整个区间中的间距不相等
另:标准差值(Population Standard Deviation)计算方法:
- 计算一组value的平均值mean
- 对每个value计算和mean的差值,并对结果做平方计算得到sd
- 对这组sd计算一个平均值sd-mean
- 将sd-mean做平方根计算得到result
- result即为标准差值
标准方差计算方法参考:https://www.wallstreetmojo.com/population-variance-formula/
三角函数
三角函数以弧度工作:
- acos(v instant-vector) 计算 v 中所有元素的反余弦值(special cases)
- acosh(v instant-vector) 计算 v 中所有元素的反双曲余弦值 (special cases)
- asin(v instant-vector) 计算 v 中所有元素的反正弦值 (special cases)
- asinh(v instant-vector) 计算 v 中所有元素的反双曲正弦值 (special cases)
- atan(v instant-vector) 计算 v 中所有元素的反正切 (special cases)
- atanh(v instant-vector) 计算 v 中所有元素的反双曲正切 (special cases)
- cos(v instant-vector) 计算 v 中所有元素的余弦 (special cases)
- cosh(v instant-vector) 计算 v 中所有元素的双曲余弦 (special cases)
- sin(v instant-vector) 计算 v 中所有元素的正弦值 (special cases)
- sinh(v instant-vector) 计算 v 中所有元素的双曲正弦值 (special cases)
- tan(v instant-vector) 计算 v 中所有元素的正切 (special cases)
- tanh(v instant-vector) 计算 v 中所有元素的双曲正切 (special cases)
度数和弧度进行转换:
- deg(v instant-vector) 将 v 中的所有元素的弧度转换为度数
- pi() 返回 pi
- rad(v instant-vector) 将 v 中的所有元素的度数转换为弧度