kavin

Prometheus内置函数介绍

kavin 运维技术 2023-01-29 836浏览 0

Prometheus 当前有 42 个内置函数。分别如下:

abs()
absent()
absent_over_time()
ceil()
changes()
clamp()
clamp_max()
clamp_min()
day_of_month()
day_of_week()
days_in_month()
delta()
deriv()
exp()
floor()
histogram_quantile()
holt_winters()
hour()
idelta()
increase()
irate()
label_join()
label_replace()
ln()
log2()
log10()
minute()
month()
predict_linear()
rate()
resets()
round()
scalar()
sgn()
sort()
sort_desc()
sqrt()
time()
timestamp()
vector()
year()
_over_time()

abs()
abs(v instant-vector) 返回输入向量,所有样本值都转换为其绝对值;
这个针对单个 Metric 没什么效果,或者说这个函数应该是用在两个 Metric 做差的时候,保证结果永远是正数。

absent()
absent(v instant-vector) 如果传递给它的向量具有任何元素,则返回空向量;如果传递给它的向量没有元素,则返回值为 1 的 1 元素向量;
这这个函数主要用在给定 Metric 名称和 Label 组合不存在时间序列时发出警报或者在页面上展示。

# 这里提供的向量有样本数据
absent(http_requests_total{method="get"})  => no data
absent(sum(http_requests_total{method="get"}))  => no data

# 由于不存在 Metric nonexistent,所以返回不带 Metric 名称且带有 label 的时间序列,且样本值为1
absent(nonexistent{job="myjob"})  => {job="myjob"}  1
# 正则匹配的 instance 不作为返回 labels 中的一部分
absent(nonexistent{job="myjob",instance=~".*"})  => {job="myjob"}  1

# sum 函数返回的时间序列不带有 label,且没有样本数据
absent(sum(nonexistent{job="myjob"}))  => {}  1
# 这个时候即使使用 by ,针对 sum 这些聚合函数也不会返回 label。
absent(sum(nonexistent{job="myjob"}) by (job))  => {}  1

absent_over_time()
absent_over_time() 和 absent() 非常类似;
absent_over_time(v range-vector) 如果传递给它的范围向量有任何元素,则返回一个空向量,如果传递给它的范围向量没有元素,则返回一个值为 1 的 1 元素向量;
这对于在给定的指标名称和标签组合在一定时间内不存在时间序列时发出警报非常有用。

absent_over_time(nonexistent{job="myjob"}[1h])  => {job="myjob"}
absent_over_time(nonexistent{job="myjob",instance=~".*"}[1h])  => {job="myjob"}
absent_over_time(sum(nonexistent{job="myjob"})[1h:])  => {}

ceil()
ceil(v instant-vector) 将 v 中所有元素的样本值向上四舍五入到最接近的整数。例如:

node_load5{instance="192.168.1.75:9100"} # 结果为 2.79
ceil(node_load5{instance="192.168.1.75:9100"}) # 结果为 3

changes()
对于每个输入时间序列数据,changes(v range-vector) 将返回其值在所提供的时间范围内更改的次数作为即时向量。

# 如果样本数据值没有发生变化,则返回结果为 0
changes(node_load5{instance="10.32.50.24"}[1m]) # 结果为 0

clamp()
clamp(v instant-vector, min scalar, max scalar) 将所有元素的样本值钳制在 v 下限为 min 和上限为 max;
特殊情况: – 返回空向量 if min > max – 返回 NaNifmin 或 maxisNaN。

clamp_max()
clamp_max(v instant-vector, max scalar) 函数,输入一个瞬时向量和最大值,样本数据值若大于 max,则改为 max,否则不变。例如:

node_load5{instance="10.32.50.24"} # 结果为 2.79
clamp_max(node_load5{instance="10.32.50.24"}, 2) # 结果为 2

clamp_min()
clamp_min(v instant-vector, min scalar) 函数,输入一个瞬时向量和最小值,样本数据值若小于 min,则改为 min,否则不变。例如:

node_load5{instance="10.32.50.24"} # 结果为 2.79
clamp_min(node_load5{instance="10.32.50.24"}, 3) # 结果为 3

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 表示星期天。

day_of_week(node_load5{instance="10.32.58.24"})
# 值是 4,当前是周六。

days_in_month()
days_in_month(v=vector(time()) instant-vector) 函数,返回当月一共有多少天。返回值范围:28~31。

days_in_month(node_load5{instance="10.32.58.24"})
# 值是 31 ,因为是 10 月。

delta()
delta(v range-vector) 的参数是一个区间向量,返回一个瞬时向量。它计算一个区间向量 v 的第一个元素和最后一个元素之间的差值。由于这个值被外推到指定的整个时间范围,所以即使样本值都是整数,你仍然可能会得到一个非整数值;这个函数一般只用在 Gauge 类型的时间序列上。

例如,下面的例子返回过去一小时的 CPU 5 分钟负载的差
delta(node_load5[1h])

deriv()
deriv(v range-vector) 的参数是一个区间向量,返回一个瞬时向量。它使用简单的线性回归计算区间向量 v 中各个时间序列的导数;这个函数一般只用在 Gauge 类型的时间序列上。

deriv(node_load5[1h])

exp()
exp(v instant-vector) 函数,输入一个瞬时向量,返回各个样本值的 e 的指数值,即 e 的 N 次方。当 N 的值足够大时会返回 +Inf。特殊情况为:

Exp(+Inf) = +Inf
Exp(NaN) = NaN

floor()
floor(v instant-vector) 函数与 ceil() 函数相反,将 v 中所有元素的样本值向下四舍五入到最接近的整数。也就是去尾法。

node_load5{instance="10.23.50.24"} # 结果为 2.65
ceil(node_load5{instance="10.23.50.24"}) # 结果为 2

histogram_quantile()
histogram_quantile(φ float, b instant-vector) 从 bucket 类型的向量 b 中计算 φ (0 ≤ φ ≤ 1) 分位数(百分位数的一般形式)的样本的最大值。(有关 φ 分位数的详细说明以及直方图指标类型的使用,请参阅直方图和摘要)。向量 b 中的样本是每个 bucket 的采样点数量。每个样本的 labels 中必须要有 le 这个 label 来表示每个 bucket 的上边界,没有 le 标签的样本会被忽略。直方图指标类型自动提供带有 _bucket 后缀和相应标签的时间序列;可以使用 rate() 函数来指定分位数计算的时间窗口。
例如,一个直方图指标名称为 employee_age_bucket_bucket,要计算过去 10 分钟内 第 90 个百分位数,请使用以下表达式:

histogram_quantile(0.9, rate(employee_age_bucket_bucket[10m]))
返回如下值:{instance="10.0.86.71:8080",job="prometheus"} 35.714285714285715

这表示最近 10 分钟之内 90% 的样本的最大值为 35.714285714285715。

这个计算结果是每组标签组合成一个时间序列。我们可能不会对所有这些维度(如 job、instance 和 method)感兴趣,并希望将其中的一些维度进行聚合,则可以使用 sum() 函数。例如,以下表达式根据 job 标签来对第 90 个百分位数进行聚合:

# histogram_quantile() 函数必须包含 le 标签
histogram_quantile(0.9, sum(rate(employee_age_bucket_bucket[10m])) by (job, le))
如果要聚合所有的标签,则使用如下表达式:
histogram_quantile(0.9,sum(rate(employee_age_bucket_bucket[10m])) by (le))

histogram_quantile 这个函数是根据假定每个区间内的样本分布是线性分布来计算结果值的(也就是说它的结果未必准确),最高的 bucket 必须是 le=”+Inf” (否则就返回 NaN)。
如果分位数位于最高的 bucket(+Inf) 中,则返回第二个最高的 bucket 的上边界。如果该 bucket 的上边界大于 0,则假设最低的 bucket 的的下边界为 0,这种情况下在该 bucket 内使用常规的线性插值。
如果分位数位于最低的 bucket 中,则返回最低 bucket 的上边界。

holt_winters()
holt_winters(v range-vector, sf scalar, tf scalar) 函数基于区间向量 v,生成时间序列数据平滑值。平滑因子 sf 越低, 对旧数据的重视程度越高。趋势因子 tf 越高,对数据的趋势的考虑就越多。其中,0hour()
hour(v=vector(time()) instant-vector) 函数返回被给定 UTC 时间的当前第几个小时,时间范围:0~23。

idelta()
idelta(v range-vector) 的参数是一个区间向量, 返回一个瞬时向量。它计算最新的 2 个样本值之间的差值;这个函数一般只用在 Gauge 类型的时间序列上。

increase()
increase(v range-vector) 函数获取区间向量中的第一个和最后一个样本并返回其增长量, 它会在单调性发生变化时(如由于采样目标重启引起的计数器复位)自动中断。由于这个值被外推到指定的整个时间范围,所以即使样本值都是整数,你仍然可能会得到一个非整数值。
例如,以下表达式返回区间向量中每个时间序列过去 5 分钟内 HTTP 请求数的增长数:

increase(http_requests_total{job="apiserver"}[5m])

increase 的返回值类型只能是计数器类型,主要作用是增加图表和数据的可读性。使用 rate(v) 函数记录规则的使用率,以便持续跟踪数据样本值的变化。

irate()
irate(v range-vector) 函数用于计算区间向量的增长率,但是其反应出的是瞬时增长率。irate 函数是通过区间向量中最后两个两本数据来计算区间向量的增长速率,它会在单调性发生变化时(如由于采样目标重启引起的计数器复位)自动中断。这种方式可以避免在时间窗口范围内的“长尾问题”,并且体现出更好的灵敏度,通过 irate 函数绘制的图标能够更好的反应样本数据的瞬时变化状态。
例如,以下表达式返回区间向量中每个时间序列过去 5 分钟内最后两个样本数据的 HTTP 请求数的增长率:

irate(http_requests_total{job="api-server"}[5m])

irate 只能用于绘制快速变化的计数器,在长期趋势分析或者告警中更推荐使用 rate 函数。因为使用 irate 函数时,速率的简短变化会重置 FOR 语句,形成的图形有很多波峰,难以阅读;当将 irate() 函数与聚合运算符(例如 sum())或随时间聚合的函数(任何以 _over_time 结尾的函数)一起使用时,必须先执行 irate() 函数,然后再进行聚合操作,否则当采样目标重新启动时 irate() 无法检测到计数器是否被重置。

label_join()
该函数允许你将标签纸连接在用,类似于在重新标记时处理souce_lables方法,同样该函数也不会删除指标名称;语法格式是 label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, …) ;函数可以将时间序列 v 中多个标签 src_label 的值,通过 separator 作为连接符写入到一个新的标签 dst_label 中。可以有多个 src_label 标签。
例如,以下表达式返回的时间序列多了一个 foo 标签,标签值为 etcd,etcd-k8s:

up{endpoint="api",instance="192.168.123.248:2379",job="etcd",namespace="monitoring",service="etcd-k8s"}
==> up{endpoint="api",instance="192.168.123.248:2379",job="etcd",namespace="monitoring",service="etcd-k8s"} 1
 
label_join(up{endpoint="api",instance="192.168.123.248:2379",job="etcd",namespace="monitoring",service="etcd-k8s"}, "foo", ",", "job", "service")
==> up{endpoint="api",foo="etcd,etcd-k8s",instance="192.168.123.248:2379",job="etcd",namespace="monitoring",service="etcd-k8s"} 1

再看一个简单例子:

go_info{job="LocalServer"}
   ==> go_info{instance="localhost:9090", job="LocalServer", version="go1.16.4"} 1

label_join(go_info{job="LocalServer"},"newlable",'|',"job","version")
   ==> go_info{instance="localhost:9090", job="LocalServer", newlable="LocalServer|go1.16.4", version="go1.16.4"} 1

label_replace()
该函数允许你对标签值进行正则表达式替换。与大多数函数不同的是,该函数不会删除指标名称。为了能够让客户端的图标更具有可读性,可以通过 label_replace 函数为时间序列添加额外的标签。
label_replace 的具体参数如下:

label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)

该函数会依次对 v 中的每一条时间序列进行处理,通过 regex 匹配 src_label 的值,并将匹配部分 relacement 写入到 dst_label 标签中。如下所示:

label_replace(up, "host", "$1", "instance", "(.*):.*")
label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")

函数处理后,时间序列将包含一个 host 标签,host 标签的值为 Exporter 实例的 IP 地址:

up{host="localhost",instance="localhost:8080",job="cadvisor"} 1
up{host="localhost",instance="localhost:9090",job="prometheus"} 1
up{host="localhost",instance="localhost:9100",job="node"} 1

再看一个简单的例子:

up{job="LocalServer"}
==> up{instance="localhost:9090", job="LocalServer"}

label_replace(up{job="LocalServer"}, "instance", "$1:9200", "job",  "(.*)")
==> up{instance="LocalServer:9200", job="LocalServer"}

ln()
ln(v instant-vector) 计算瞬时向量 v 中所有样本数据的自然对数。特殊情况:

ln(+Inf) = +Inf
ln(0) = -Inf
ln(x

log2()
log2(v instant-vector) 函数计算瞬时向量 v 中所有样本数据的二进制对数。特殊情况:

ln(+Inf) = +Inf
ln(0) = -Inf
ln(x

比如:

log2(vector(2)) # {} 1

log10()
log10(v instant-vector) 计算瞬时向量 v 中所有样本数据的十进制对数。特殊情况:

ln(+Inf) = +Inf
ln(0) = -Inf
ln(x

比如:

log10(vector(10)) # {} 1

minute()
minute(v=vector(time()) instant-vector) 函数返回给定 UTC 时间当前小时的第多少分钟。结果范围:0~59。

month()
month(v=vector(time()) instant-vector) 函数返回给定 UTC 时间当前属于第几个月,结果范围:0~12。

predict_linear()
predict_linear(v range-vector, t scalar) 函数可以预测时间序列 v 在 t 秒后的值。它基于简单线性回归的方式,对时间窗口内的样本数据进行统计,从而可以对时间序列的变化趋势做出预测。该函数的返回结果不带有度量指标,只有标签列表;这个函数一般只用在 Gauge 类型的时间序列上。
例如,基于 2 小时的样本数据,来预测主机可用磁盘空间的是否在 4 个小时候被占满,可以使用表达式:predict_linear(node_filesystem_free{job=”node”}[2h], 4 * 3600)

predict_linear(http_requests_total{code="200",instance="120.77.65.193:9090",job="prometheus",method="get"}[5m], 5)

结果:
{code="200",handler="query_range",instance="120.77.65.193:9090",job="prometheus",method="get"} 1
{code="200",handler="prometheus",instance="120.77.65.193:9090",job="prometheus",method="get"} 4283.449995397104
{code="200",handler="static",instance="120.77.65.193:9090",job="prometheus",method="get"} 22.99999999999999
...

例如, 预测四个小时内每个文件系统剩余的可用空间量。

predict_linear(node_filesystem_free_bytes{instance="192.168.1.107:9100"}[1h],4 * 3600)
==>  {device="/dev/mapper/ubuntu--vg-lv--0",fstype="ext4", instance="192.168.1.107:9100", job="linux_exporter", mountpoint="/"}
    81532763513.3
# 等同于
deriv(node_filesystem_free_bytes{instance="192.168.1.107:9100"}[1h] * 4 * 3600) + node_filesystem_free_bytes{instance="192.168.1.107:9100"}[1h]

rate()
rate(v range-vector) 函数可以直接计算区间向量 v 在时间窗口内平均增长速率,它会在单调性发生变化时(如由于采样目标重启引起的计数器复位)自动中断。该函数的返回结果不带有度量指标,只有标签列表。
例如,以下表达式返回区间向量中每个时间序列过去 5 分钟内 HTTP 请求数的每秒增长率:

rate(http_requests_total[5m])
结果:
{code="200",handler="label_values",instance="120.77.65.193:9090",job="prometheus",method="get"} 0
{code="200",handler="query_range",instance="120.77.65.193:9090",job="prometheus",method="get"} 0
{code="200",handler="prometheus",instance="120.77.65.193:9090",job="prometheus",method="get"} 0.2

rate() 函数返回值类型只能用计数器,在长期趋势分析或者告警中推荐使用这个函数;当将 rate() 函数与聚合运算符(例如 sum())或随时间聚合的函数(任何以 _over_time 结尾的函数)一起使用时,必须先执行 rate() 函数,然后再进行聚合操作,否则当采样目标重新启动时 rate() 无法检测到计数器是否被重置。

resets()
resets(v range-vector) 的参数是一个区间向量。对于每个时间序列,它都返回一个计数器重置的次数。两个连续样本之间的值的减少被认为是一次计数器重置;这个函数一般只用在计数器类型的时间序列上。
下面我们看一个例子,显示进程的 CPU 时间在过去一个小时重置的次数。

resets(process_cpu_seconds_total[1h]) ==> {instance="localhost:9090", job="prom-Server"}  0

round()
round(v instant-vector, to_nearest=1 scalar) 函数与 ceil 和 floor 函数类似,返回向量中所有样本值的最接近的整数。to_nearest 参数是可选的,默认为 1,表示样本返回的是最接近 1 的整数倍的值。你也可以将该参数指定为任意值(也可以是小数),表示样本返回的是最接近它的整数倍的值。

round(vector(6.5)) # 7
round(vector(6.4)) # 6

scalar()
scalar(v instant-vector) 函数的参数是一个单元素的瞬时向量,它返回其唯一的时间序列的值作为一个标量。如果度量指标的样本数量大于 1 或者等于 0, 则返回 NaN。

# 1.处理标量常量且仅仅适用于瞬时向量的数学函数
scalar(sqrt(vector(4)))  # >> scalar  2
# 2.与时间函数连用
scalar(year())  # >> scalar  2021
# 3.为你提供计算机CPU非空闲的时间比例(使用scalar会丢失所有的标签)
sum(rate(node_cpu_seconds_total{mode!="idle"}[5m])) / scalar(count(node_cpu_seconds_total{mode="idle"})) # {} 0.017490234375018142

sgn()
sgn(v instant-vector) 返回一个向量,该向量将所有样本值转换为其符号,定义如下:如果 v 是正的,则为 1;如果 v 是负的,则为-1;如果 v 等于 0,则为 0。

sort()
sort(v instant-vector) 函数对向量按元素的值进行升序排序,返回结果:key: value = 度量指标:样本值[升序排列]

正序:sort(node_load5{})

sort_desc()
sort(v instant-vector) 函数对向量按元素的值进行降序排序,返回结果:key: value = 度量指标:样本值[降序排列]

反序:sort_desc(node_load5{})

sqrt()
sqrt(v instant-vector) 函数计算向量 v 中所有元素的平方根。

time()
time() 函数返回从 1970-01-01 到现在的秒数。注意:它不是直接返回当前时间,而是时间戳。

timestamp()
timestamp(v instant-vector) 函数返回向量 v 中的每个样本的时间戳(从 1970-01-01 到现在的秒数);该函数从 Prometheus 2.0 版本开始引入, 与其它时间函数不同的是,它查看瞬时向量中的样本的时间戳而不是值。例子 1

timestamp(vector(time()))  ==> {}   1629783662.714

例子 2,可以看到每个目标的最后异常抓取的开始时间:

timestamp(up) 
==> {instance="localhost:9090", job="Server"} 1629783745.147

例子 3,返回 Prometheus 启动节点导出器抓取时间与节点导出器认为的当前实践的差值:

node_time_seconds - timestamp(node_time_seconds) 
==> {instance="192.168.1.107:9100", job="linux_exporter"} 0.0025420188903808594

vector()
vector(s scalar) 函数将标量 s 作为没有标签的向量返回,即返回结果为:key: value= {}, s。例如,vector(1024) 返回 {} 1024例如,sum(node_not_metrics) 或者 vector(1024) 返回 {} 1024,不存在的指标也始终返回一个样本。

year()
year(v=vector(time()) instant-vector) 函数返回被给定 UTC 时间的当前年份;注意: 即使区间向量内的值分布不均匀,它们在聚合时的权重也是相同的。实例演示:
1.查看进程是哪一年开始运行

year(process_start_time_seconds) 
==>  {instance="localhost:9090", job="Server"} 2021

2.计算本月启动的进程的时间序列

year(process_start_time_seconds) == bool scalar(year())  * (month(process_start_time_seconds) == bool scalar(month()))
==>  {instance="localhost:9090", job="Server"} 1
==>  {instance="192.168.1.225:9100", job="linux_exporter"} 0

3.计算本月启动的进程的时间序列个数

sum(year(process_start_time_seconds) == bool scalar(year())  * (month(process_start_time_seconds) == bool scalar(month())))  ==> {} 1

time_seconds) == bool scalar(month()))) ==> {} 1
Tips : 乘法运算符在布尔值使用时就像和运算符一样值 1 表示真,否则为假。

_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(scalar, range-vector) : 区间向量内每个度量指标的样本数据值分位数,φ-quantile (0 ≤ φ ≤ 1)。
stddev_over_time(range-vector) : 区间向量内每个度量指标的总体标准差。
stdvar_over_time(range-vector) : 区间向量内每个度量指标的总体标准方差。

这些值指定间隔内的所有值在聚合中具有相同的权重,即使这些值在整个间隔内的间隔不相等。

继续浏览有关 运维监控 的文章
发表评论