暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

看完这篇文章,完全掌握Prometheus计算函数(建议收藏!)

一元殿 2019-10-11
4101


点击上方“icloud布道师”,“星标或置顶公众号”

逆境前行,能帮你的只有自己

************************************


    


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




    基本概念

    表达式语句类型

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

    • instant vector
       瞬时向量 - 它是指在同一时刻,抓取的所有度量指标数据。这些度量指标数据的key都是相同的,也即相同的时间戳。

    • range vector
       范围向量 - 它是指在任何一个时间范围内,抓取的所有度量指标数据。

    • scalar
       标量 - 一个简单的浮点值

    • string
       字符串 - 一个当前没有被使用的简单字符串

    注意:
    根据表达式不同,得出的图像也是有适用性范围的!
    例如仪表盘类型的数据只能显示瞬时向量instant vector
    ;折线图则显示范维向量range vector

    时间序列选择器

    即时向量选择器

    瞬时向量选择器可以对一组时间序列数据进行筛选,并给出结果中的每个结果键值对(时间戳-样本值): 最简单的形式是,只有一个度量名称被指定。在一个瞬时向量中这个结果包含有这个度量指标名称的所有样本数据键值对。

    node_network_up
    为例子:

    我们可以查看到,node_network_up
    的搜寻结果有两条,分别是eth0
    lo
    两块网卡

    通过在度量指标后面增加{}
    一组标签可以进一步地过滤这些时间序列数据
    我们继续对这个查询语句进行加工,只筛选eth0
    网卡:

    可以采用不匹配的标签值也是可以的,或者用正则表达式不匹配标签。标签匹配操作如下所示:
    • =
       : 精确地匹配标签给定的值

    • !=
      : 不等于给定的标签值

    • =~
      : 正则表达匹配给定的标签值

    • !~
      : 给定的标签值不符合正则表达式

    依旧以node_network_up
    为例子:
    我们查询device
    不等于eth0
    的条件

    范围向量选择器

    范围向量类似瞬时向量, 不同在于,它们从当前实例选择样本范围区间。在语法上,时间长度被追加在向量选择器尾部的方括号[]
    中,用以指定对于每个样本范围区间中的每个元素应该抓取的时间范围样本区间

    时间长度由一个数值决定,后面可以跟下面的单位:

    • s
       - 秒

    • m
       - 分钟

    • h
       - 小时

    • d
       - 天

    • w
       - 周

    • y
       - 年

    例如,我们查询当前服务器所跑的进程,利用node_procs_running
    这个查询功能

    可以看到,我们当前服务器运行的进程为三个


    这时候,我们在后面加一个时间范围[1m]

    我们看到,在一分钟内的结果,有六个Value,这是因为我们的采集频率是十秒钟,所以会得出6个值。
    3 @1570497394.21
    的格式代表: - Value@时间戳


    偏移修饰符

    这个offset
    偏移修饰符允许在查询中改变单个瞬时向量和范围向量中的时间偏移

    我们继续使用node_procs_running
    这个查询功能,只不过刚才查询的是最近一分钟的数据,我们现在查询五分钟以前的瞬时数据

    注意:offset偏移修饰符必须直接跟在选择器后面
    这样用也是可以的node_procs_running[1m] offset 5m






    操作符

    二元操作符

    Prometheus的查询语言支持基本的逻辑运算和算术运算。

    算术二元运算符

    • +
       - 加法

    • -
       - 减法

    • *
       - 乘法

    • /
       - 除法

    • %
       - 模

    • ^
       - 幂

    比较二元运算符

    promerheus支持以下比较二元运算符:

    • ==
       - 等于

    • !=
       - 不等于

    • >
       - 大于

    • <
       - 小于

    • >=
       - 大于等于

    • <=
       - 小于等于

    比较二元操作符被应用于scalar/scalar(标量/标量)
    vector/scalar(向量/标量)
    ,和vector/vector(向量/向量)
    。比较操作符得到的结果是bool
    布尔类型值,返回1
    或者0
    值。
    在两个标量之间的比较运算,bool结果写入到另一个结果标量中

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

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

    逻辑/集合二元操作符

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

    • and
       - 交集

    • or
       - 并集

    • unless
       - 补集

    • vector1 and vector2
       的逻辑/集合二元操作符,规则:vector1
      瞬时向量中的每个样本数据与vector2
      向量中的所有样本数据进行标签匹配,不匹配的,全部丢弃。运算结果是保留左边的度量指标名称和值。

    • vector1 or vector2
      的逻辑/集合二元操作符,规则: 保留vector1
      向量中的每一个元素,对于vector2
      向量元素,则不匹配vector1
      向量的任何元素,则追加到结果元素中。

    • vector1 unless vector2
      的逻辑/集合二元操作符,又称差积。规则:包含在vector1
      中的元素,但是该元素不在vector2
      向量所有元素列表中,则写入到结果集中。

    聚合操作符

    rometheus支持下面的内置聚合操作符。这些聚合操作符被用于聚合单个即时向量的所有时间序列列表,把聚合的结果值存入到新的向量中

    • sum
       - (在维度上求和)

    • max
       - (在维度上求最大值)

    • min
       - (在维度上求最小值)

    • avg
       - (在维度上求平均值)

    • stddev
       - (求标准差)

    • stdvar
       - (求方差)

    • count
       - (统计向量元素的个数)

    • count_values
       - (统计相同数据值的元素数量)

    • bottomk
       - (样本值第k个最小值)

    • topk
       - (样本值第k个最大值)

    • quantile
       - (统计分位数)

    这些操作符被用于聚合所有标签维度,或者通过without
    或者by
    子句来保留不同的维度。

    例如,如果我们对所有应用程序的http请求总数,我们可以简单地写下

    二元运算符优先级

    在Prometheus系统中,二元运算符优先级从高到低:

    • 1
       – ^

    • 2
       – *, , %

    • 3
       – +, -

    • 4
       – ==, !=, <=, <, >=, >

    • 5
       – and, unless

    • 6
       – or




    Prometheus聚合函数

    abs( )

    abs(v instant-vector)
    将瞬时值转换为绝对值

    absent()

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

    absent(nonexistent{job="myjob"})

    absent(sum(nonexistent{job="myjob"}))


    ceil()

    ceil(v instant-vector)
    是一个向上舍入为最接近的整数

    node_load15

    ceil(node_load15)


    floor()

    floor(v instant-vector)
    函数,与ceil()
    函数相反。1.3 为 1 。

    changes()

    对于每个输入时间序列,changes作为即时向量返回其值在给定时间范围内更改的次数。

    查看十分钟内总内存的变化。应该得到0

    changes(node_memory_MemTotal_bytes{instance="10.67.xx.xx:9100"}[10m])


    查看十分钟服务器进程总数的变化次数

    changes(node_procs_running{instance="10.67.xx.xx:9100"} [10m])


    clamp_max()

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

    查看http的request总数

    prometheus_http_requests_total

    clamp_max(prometheus_http_requests_total,2)


    clamp_min()

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

    查看http的request总数

    prometheus_http_requests_total

    clamp_min(prometheus_http_requests_total,2)

    clamp_min(prometheus_http_requests_total,8)


    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=
    度量指标:差值
    查询过去10小时的cpu_load变化

    delta(node_load15[10h])


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

    deriv()

    deriv(v range-vector)
    函数,计算一个范围向量v中各个时间序列二阶导数,使用简单线性回归

    deriv
    二阶导数返回值类型只能是gauges

    exp()

    exp(v instant-vector)
    函数,输入一个瞬时向量, 返回各个样本值的e指数值,即为e^N
    次方。
    如下所示:

    holt_winters()

    holt_winters(v range-vector, sf scalar, tf scalar)`` 函数基于区间向量 v,生成时间序列数据平滑值。平滑因子
    sf越低, 对旧数据的重视程度越高。趋势因子
    tf越高,对数据的趋势的考虑就越多。其中:
    0< sf, tf <=1`
    holt_winters 仅适用于 Gauge 类型的时间序列

    hour()

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

    idelta()

    idelta(v range-vector)
    函数,输入一个范围向量,返回key: value = 度量指标:每最后两个样本值差值。
    前面我们介绍了delta,两者的差别在于:delta=last-first
     而 idelta=last - last-1

    实验数据如下

    increase()

    increase(v range-vector)

    函数, 输入一个范围向量,返回:key:value =
     度量指标:last值-first值,自动调整单调性,如:服务实例重启,则计数器重置。与delta()
    不同之处在于delta
    是求差值,而increase
    返回最后一个减第一个值,可为正为负

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

    rate

    rate(v range-vector)``函数, 输入:范围向量,输出:
    key: value =`不带有度量指标,且只有标签列表:(last值-first值)/时间差s

    irate

    irate(v range-vector)
    函数, 输入:范围向量,输出:key: value =
     度量指标:(last值-last前一个值)/时间戳差值。它是基于最后两个数据点,自动调整单调性, 如:服务实例重启,则计数器重置。

    irate 只能用于绘制快速变化的计数器,在长期趋势分析或者告警中更推荐使用 rate 函数。因为使用 irate 函数时,速率的简短变化会重置 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_label
    的值,通过 separator 作为连接符写入到一个新的标签 dst_label
     中。可以有多个 src_label
     标签。

    例如,以下表达式返回的时间序列多了一个 newlabel 标签,标签值为 :"node_test和10.67.36.79:9100"

    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函数,输入:瞬时向量,输出:key: value = 度量指标:值(要替换的内容:首先,针对src_label标签,对该标签值进行regex正则表达式匹配。如果不能匹配的度量指标,则不发生任何改变;否则,如果匹配,则把dst_label标签的标签纸替换为replacement


    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 中所有样本数据的二进制对数。特殊情况同上。

    log10()

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

    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 秒后的值。它基于简单线性回归的方式,对时间窗口内的样本数据进行统计,从而可以对时间序列的变化趋势做出预测。该函数的返回结果不带有度量指标,只有标签列表。

    例如,基于 2 小时的样本数据,来预测主机可用磁盘空间的是否在 24 个小时候被占满,可以使用如下表达式:

    predict_linear(node_filesystem_free{job="node"}[2h], 24 * 3600)


    resets()

    resets(v range-vector)
    的参数是一个区间向量。对于每个时间序列,它都返回一个计数器重置的次数。两个连续样本之间的值的减少被认为是一次计数器重置。

    这个函数一般只用在计数器类型的时间序列上。

    round()

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

    scalar()

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

    sort()

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

    sort_desc()

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

    sqrt()

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

    time()

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

    timestamp()

    timestamp(v instant-vector)
    函数返回向量 v 中的每个样本的时间戳(从 1970-01-01 到现在的秒数)。

    该函数从 Prometheus 2.0 版本开始引入。

    vector()

    vector(s scalar)
    函数将标量 s 作为没有标签的向量返回,即返回结果为:key: value= {}, 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(scalar, range-vector)
       : 区间向量内每个度量指标的样本数据值分位数,φ-quantile (0 ≤ φ ≤ 1)。

    • stddev_over_time(range-vector)
       : 区间向量内每个度量指标的总体标准差。

    • stdvar_over_time(range-vector)
       : 区间向量内每个度量指标的总体标准方差。


    即使区间向量内的值分布不均匀,它们在聚合时的权重也是相同的。





    写在最后


    最后,如果你想了解更多关于prometheus监控系统的信息:

    请参考这篇文章:Prometheus 入门--你想了解的都在这里

    或者直接浏览官网:

    Prometheus:     

        http://www.prometheus.io

    Grafana:     
        http://www.prometheus.io
    Prometheus下载:      
        https://prometheus.io/download/
    计算函数:  
        https://prometheus.io/docs/prometheus/latest/querying/basics/
    Grafana插件下载:    
        https://grafana.com/grafana/plugins







    ----如果有疑问,请添加作者微信----

    (腾讯大大暂未开放评论功能)







    文章转载自一元殿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论