prometheus从根本上存储的所有数据都是时间序列: 具有时间戳的数据流只属于单个度量指标和该度量指标下的多个标签维度。除了存储时间序列数据外,Prometheus也可以利用查询表达式存储5分钟的返回结果中的时间序列数据。

Prometheus提供一个函数式的表达式语言,可以使用户实时地查找和聚合时间序列数据。表达式计算结果可以在图表中展示,也可以在Prometheus表达式浏览器中以表格形式展示,或者作为数据源, 以HTTP API的方式提供给外部系统使用。

表达式语言数据类型

在Prometheus的表达式语言中,任何表达式或者子表达式都可以归为四种类型:

  • 即时向量(instant vector) 包含每个时间序列的单个样本的一组时间序列,共享相同的时间戳
  • 范围向量(Range vector) 包含每个时间序列随时间变化的数据点的一组时间序列
  • 标量(Scalar) 一个简单的数字浮点值
  • 字符串(String) 一个简单的字符串值(目前未被使用)
时间序列选择器
  1. 即时向量选择器
    即时向量选择器允许选择一组时间序列,或者某个给定的时间戳的样本数据。如:container_cpu_usage_seconds_total选择了具有container_cpu_usage_seconds_total的时间序列

查询pod (nginx-deployment-d8d99448f-h6585)聚合一分钟之内的cpu 负载

1
2
#查看当前K8S集群中所有的POD
kubectl get pod --all-namespaces

1
sum by (container_name)(rate(container_cpu_usage_seconds_total{image!="",container_name!="POD",pod_name="kubernetes-dashboard-666fbbf977-v9vsh"}[1m]))

等于

1
sum by (container_name)(rate(container_cpu_usage_seconds_total{image="k8scn/kubernetes-dashboard-amd64@sha256:811a618089732441fa2aaaac0c860956e61410cec4b5715bbb328d0d4a685393",container_name="kubernetes-dashboard",pod_name="kubernetes-dashboard-666fbbf977-v9vsh"}[1m]))

  • sum:求和。聚合操作符参考
  • by:固定语法。保留结果向量中的标签集合,其他标签被保留输出。
  • rate:计算范围向量中时间序列的每平平均增长率。rate范围向量参考)
  • container_cpu_usage_seconds_total:容器CPU每秒使用总和,是一个时间序列名称。
  • {}:即时矢量选择器。允许在给定的时间戳(即时)中为每个时间序列和每个样本值选择一组时间序列:比如仅指定度量标准名称。这将产生包含具有此度量标准名称的所有时间序列的元素的即时矢量。即时矢量选择器参考
  • {image!="",container_name!="POD",pod_name="kubernetes-dashboard-666fbbf977-v9vsh"}都是时间序列container_cpu_usage_seconds_total的标签。其中image是名称标签,container_name是工作标签,pod_name是组标签。
  • image!="":是时间序列container_cpu_usage_seconds_total的名称标签,意思是image不为空。container_name!="POD"意思同上,container_name不等于POD。pod_name="kubernetes-dashboard-666fbbf977-v9vsh"意思同上,意思是pod_name等于kubernetes-dashboard-666fbbf977-v9vsh。匹配操作符参考
  • [1m]:范围矢量选择器。在语法上,范围持续时间会附在矢量选择器末尾的[]内,意思是为每个结果范围矢量元素提取多久的时间值。范围矢量选择器参考

prometheus时间序列

我们可以通过Prometheus的UI界面查询到该containername的具体信息,如下:
随便输入一个时间序列值,Prometheus默认会列出当前K8s里所有的监控信息,然后ctrl+F搜索
![prometheus
时间序列](https://note.youdao.com/yws/api/personal/file/F458416FAFC341B0BBDCD5D0C29DE7DE?method=download&shareKey=ab0ca193e6ec09a12f3cf779e2d43da3)

下面两个监控指标获取的监控目标相同
prometheus_时间序列
prometheus_时间序列

  1. 范围向量选择器
    范围向量表达式正如即时向量表达式一样运行,前者返回从当前时刻的时间序列回来。语法是,在一个向量表达式之后添加[]来表示时间范围,持续时间用数字表示,后接下面单元之一:
    时间长度有一个数值决定,后面可以跟下面的单位:
  • s - seconds
  • m - minutes
  • h - hours
  • d - days
  • w - weeks
  • y - years

见上面例子,范围矢量选择器参考

  1. 偏移修饰符(offset modifier)
    偏移修饰符允许更改查询中单个即时向量和范围向量的时间偏移量。偏移修饰符(offset modifier)参考

以下表达式返回container_cpu_usage_seconds_total在一天前5分钟内的速率

1
(rate(container_cpu_usage_seconds_total{image!="",container_name!="POD",pod_name="kubernetes-dashboard-666fbbf977-v9vsh"} [5m] offset 1d))

prometheus_偏移修饰符
prometheus_偏移修饰符

  1. 操作符

4.1. 二元操作符
Prometheus的查询语言支持基本的逻辑运算和算术运算。对于两个瞬时向量, 匹配行为可以被改变

4.2. 算术二元运算符

  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • %
  • ^ 幂等

二元运算操作符支持scalar/scalar(标量/标量)vector/scalar(向量/标量)、和vector/vector(向量/向量)之间的操作
在两个标量之间进行操作符运算,得到的结果也是标量

在向量和标量之间,这个操作符会作用于这个向量的每个样本值上。例如:如果一个时间序列瞬时向量除以2,操作结果也是一个新的瞬时向量,且度量指标名称不变, 它是原度量指标瞬时向量的每个样本值除以2
在两个向量之间,一个二元算术操作符作用在左边瞬时向量的每个样本值,且该样本值与操作符右边能匹配上的样本值计算,向量匹配。结果写入到一个没有度量指标名称的瞬时向量

4.3. 比较二元操作符
在Prometheus系统中,比较二元操作符有:

  • == 等于
  • != 不等于
  • > 大于
  • < 小于
  • >= 大于等于
  • <= 小于等于

比较二元操作符被应用于scalar/scalar(标量/标量)vector/scalar(向量/标量),和vector/vector(向量/向量)。比较操作符得到的结果是bool布尔类型值,返回1或者0值。

在两个标量之间的比较运算,bool结果写入到另一个结果标量中。
瞬时向量和标量之间的比较运算,这个操作符会应用到某个当前时刻的每个时间序列数据上,如果一个时间序列数据值与这个标量比较结果是false,则这个时间序列数据被丢弃掉,如果是true, 则这个时间序列数据被保留在结果中。

在两个瞬时向量之间的比较运算,左边度量指标数据中的每个时间序列数据,与右边度量指标中的每个时间序列数据匹配,没有匹配上的,或者计算结果为false的,都被丢弃,不在结果中显示。否则将保留左边的度量指标和标签的样本数据写入瞬时向量。

4.4. 逻辑/集合二元操作符
逻辑/集合二元操作符只能作用在即时向量, 包括:

  • and 交集
  • or 并集
  • unless 补集

vector1 and vector2 的逻辑/集合二元操作符,规则:vector1瞬时向量中的每个样本数据与vector2向量中的所有样本数据进行标签匹配,不匹配的,全部丢弃。运算结果是保留左边的度量指标名称和值。
vector1 or vector2的逻辑/集合二元操作符,规则: 保留vector1向量中的每一个元素,对于vector2向量元素,则不匹配vector1向量的任何元素,则追加到结果元素中。
vector1 unless vector2的逻辑/集合二元操作符,又称差积。规则:包含在vector1中的元素,但是该元素不在vector2向量所有元素列表中,则写入到结果集中。

  1. 向量匹配
    向量之间的匹配是指右边向量中的每一个元素,在左边向量中也存在。这里有两种基本匹配行为特征:
  • 一对一,找到这个操作符的两边向量元素的相同元素。默认情况下,操作符的格式是vector1 [operate] vector2。如果它们有相同的标签和值,则表示相匹配。ingoring关键字是指,向量匹配时,可以忽略指定标签。on关键字是指,在指定标签上进行匹配。格式如下所示:
    参考
  1. 聚合操作符
    Prometheus支持下面的内置聚合操作符。这些聚合操作符被用于聚合单个即时向量的所有时间序列列表,把聚合的结果值存入到新的向量中。
  • sum (在维度上求和)
  • max (在维度上求最大值)
  • min (在维度上求最小值)
  • avg (在维度上求平均值)
  • stddev (求标准差)
  • stdvar (求方差)
  • count (统计向量元素的个数)
  • count_values (统计相同数据值的元素数量)
  • bottomk (样本值第k个最小值)
  • topk (样本值第k个最大值)
  • quantile (统计分位数)

这些操作符被用于聚合所有标签维度,或者通过without或者by子句来保留不同的维度。
parameter只能用于count_values, quantile, topkbottomkwithout移除结果向量中的标签集合,其他标签被保留输出。by关键字的作用正好相反,即使它们的标签值在向量的所有元素之间。keep_common子句允许保留额外的标签(在元素之间相同,但不在by子句中的标签)

count_values对每个唯一的样本值输出一个时间序列。每个时间序列都附加一个标签。这个标签的名字有聚合参数指定,同时这个标签值是唯一的样本值。每一个时间序列值是结果样本值出现的次数。
topkbottomk与其他输入样本子集聚合不同,返回的结果中包括原始标签。by和without仅仅用在输入向量的桶中。

例如: 如果度量指标名称http_requests_total包含由group, application, instance的标签组成的时间序列数据,我们可以通过以下方式计算去除instance标签的http请求总数:

1
sum(http_requests_total) without (instance)

如果我们对所有应用程序的http请求总数:

1
sum(http_requests_total)

统计每个编译版本的二进制文件数量:

1
count_values("version", build_version)

通过所有实例,获取http请求第5个最大值:

1
topk(5, http_requests_total)

  1. 二元运算符优先级
    在Prometheus系统中,二元运算符优先级从高到低:
  • ^
  • *,/,%
  • +,-
  • ==,!=,<=,<,>=,>
  • and,unless
  • or

参考:https://github.com/1046102779/prometheus/blob/master/prometheus/querying/operators.md

  1. 函数
    一些函数有默认的参数,例如:year(v=vector(time()) instant-vector)。v是参数值,instant-vector是参数类型。vector(time())是默认值。
  • abs()
    abs(v instant-vector)返回输入向量的所有样本的绝对值
  • absent()
    absent(v instant-vector),如果赋值给它的向量具有样本数据,则返回空向量;如果传递的瞬时向量参数没有样本数据,则返回不带度量指标名称且带有标签的样本值为1的结果
    当监控度量指标时,如果获取到的样本数据是空的, 使用absent方法对告警是非常有用的。

    1
    2
    3
    absent(nonexistent{job="myjob"}) # => key: value = {job="myjob"}: 1
    absent(nonexistent{job="myjob", instance=~".*"}) # => {job="myjob"} 1
    absent(sum(nonexistent{job="myjob"})) # => key:value {}: 0
  • ceil()
    ceil(v instant-vector) 是一个向上舍入为最接近的整数

  • changes()
    changes(v range-vector)输入一个范围向量, 返回这个范围向量内每个样本数据值变化的次数。

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

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

  • count_saclar()
    count_scalar(v instant-vector)函数, 输入一个瞬时向量,返回key:value="scalar": 样本个数。而count()函数,输入一个瞬时向量,返回key:value=向量:样本个数,其中结果中的向量允许通过by条件分组

  • 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)函数,返回当月一共有多少天。返回值范围:28~31

  • delta()
    delta(v range-vector)函数,计算一个范围向量v的第一个元素和最后一个元素之间的差值。返回值:key:value=度量指标:差值

返回过去两小时的CPU温度差:

1
delta(cpu_temp_celsius{host="zeus"}[2h])

delta函数返回值类型只能是gauges

  • deriv()
    deriv(v range-vector)函数,计算一个范围向量v中各个时间序列二阶导数,使用简单线性回归
    deriv二阶导数返回值类型只能是gauges

  • drop_common_labels()
    drop_common_labels(instant-vector)函数,输入一个瞬时向量,返回值是key:value=度量指标:样本值,其中度量指标是去掉了具有相同标签
    例如:
    http_requests_total{code=”200”, host=”127.0.0.1:9090”, method=”get”} : 4,
    http_requests_total{code=”200”, host=”127.0.0.1:9090”, method=”post”} : 5,
    返回值: http_requests_total{method=”get”} : 4, http_requests_total{code=”200”, method=”post”} : 5

  • exp()
    exp(v instant-vector)函数,输入一个瞬时向量, 返回各个样本值的e指数值,即为e^N次方。特殊情况如下所示:
    Exp(+inf) = +Inf Exp(NaN) = NaN

  • floor()
    floor(v instant-vector)函数,与ceil()函数相反。 4.3 为 4

  • histogram_quantile()
    histogram_quatile(φ float, b instant-vector)函数计算b向量的φ-直方图 (0 ≤ φ ≤ 1)参考中文文献

  • holt_winters()
    holt_winters(v range-vector, sf scalar, tf scalar)函数基于范围向量v,生成事件序列数据平滑值。平滑因子sf越低, 对老数据越重要。趋势因子tf越高,越多的数据趋势应该被重视。0< sf, tf <=1。 holt_winters仅用于gauges

  • hour()
    hour(v=vector(time()) instant-vector)函数返回被给定UTC时间的当前第几个小时,时间范围:0~23

  • idelta()
    idelta(v range-vector)函数,输入一个范围向量,返回key: value = 度量指标: 每最后两个样本值差值

  • increase()
    increase(v range-vector)函数, 输入一个范围向量,返回:key:value =度量指标:last值-first值,自动调整单调性,如:服务实例重启,则计数器重置。与delta()不同之处在于delta是求差值,而increase返回最后一个减第一个值,可为正为负
    返回过去5分钟,连续两个时间序列数据样本值的http请求增加值:

    1
    increase(http_requests_total{job="api-server"}[5m])
  • irate
    irate(v range-vector)函数, 输入:范围向量,输出:key: value =度量指标: (last值-last前一个值)/时间戳差值。它是基于最后两个数据点,自动调整单调性, 如:服务实例重启,则计数器重置
    针对范围向量中的每个时间序列数据,返回两个最新数据点过去5分钟的HTTP请求速率:

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

    irate只能用于绘制快速移动的计数器。因为速率的简单更改可以重置FOR子句,利用警报和缓慢移动的计数器,完全由罕见的尖峰组成的图形很难阅读

  • label_replace()
    对于v中的每个时间序列,label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)将正则表达式与标签值src_label匹配。如果匹配,则返回时间序列,标签值dst_label被替换的扩展替换。$1替换为第一个匹配子组,$2替换为第二个等。如果正则表达式不匹配,则时间序列不会更改。

    另一种更容易的理解是:label_replace函数,输入:瞬时向量,输出:key: value =度量指标: 值(要替换的内容:首先,针对src_label标签,对该标签值进行regex正则表达式匹配。如果不能匹配的度量指标,则不发生任何改变;否则,如果匹配,则把dst_label标签的标签纸替换为replacement 下面这个例子返回一个向量值a带有foo标签: label_replace(up{job="api-server", serice="a:c"}, "foo", "$1", "service", "(.*):.*")

  • ln()
    ln(v instance-vector)计算瞬时向量v中所有样本数据的自然对数。特殊例子:
    ln(+Inf) = +Inf ln(0) = -Inf ln(x<0) = NaN ln(NaN) = NaN

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

  • log10()
    log10(v instant-vector)函数计算瞬时向量v中所有样本数据的10进制对数。相当于ln()

  • 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)预测函数,输入:范围向量和从现在起t秒后,输出:不带有度量指标,只有标签列表的结果值

  • rate()
    rate(v range-vector)函数, 输入:范围向量,输出:key: value = 不带有度量指标,且只有标签列表:(last值-first值)/时间差
    rate(http_requests_total[5m])
    rate()函数返回值类型只能用counters,当用图表显示增长缓慢的样本数据时,这个函数是非常合适的
    注意:当rate函数和聚合方式联合使用时,一般先使用rate函数,再使用聚合操作, 否则,当服务实例重启后,rate无法检测到counter重置

  • resets()
    resets()函数, 输入:一个范围向量,输出:key-value=没有度量指标,且有标签列表[在这个范围向量中每个度量指标被重置的次数]。在两个连续样本数据值下降,也可以理解为counter被重置
    resets(http_requests_total[5m])。resets只能和counters一起使用

  • round()
    round(v instant-vector, to_nearest 1= scalar)函数,与ceil和floor函数类似,输入:瞬时向量,输出:指定整数级的四舍五入值, 如果不指定,则是1以内的四舍五入

  • scalar()
    scalar(v instant-vector)函数, 输入:瞬时向量,输出:key: value = “scalar”, 样本值[如果度量指标样本数量大于1或者等于0, 则样本值为NaN, 否则,样本值本身]

  • sort()
    sort(v instant-vector)函数,输入:瞬时向量,输出:key: value = 度量指标:样本值[升序排列]

  • sort_desc()
    sort(v instant-vector函数,输入:瞬时向量,输出:key: value = 度量指标:样本值[降序排列]

  • sqrt()
    sqrt(v instant-vector)函数,输入:瞬时向量,输出:key: value = 度量指标: 样本值的平方根

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

  • vector()
    vector(s scalar)函数,返回:key: value= {}, 传入参数值

  • year()
    year(v=vector(time()) instant-vector),返回年份

  • _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): 范围向量内每个度量指标的总体标准方差

参考:https://github.com/1046102779/prometheus/blob/master/prometheus/querying/functions.md
https://www.kancloud.cn/huyipow/prometheus/525003


本文出自”Jack Wang Blog”:http://www.yfshare.vip/2021/06/02/Prometheus查询语法/