【资料图】
读前提示:
本文字数较多且紧凑,最好预留15min一次性看完,好营养,易吸收。
promQL详解Prometheus提供了内置的数据查询语言PromQL(全称为Prometheus Query Language),支持用户进行实时的数据查询及聚合操作。PromQL基本介绍Prometheus基于指标名称(metrics name)以及附属的标签集(labelset)唯一定义一条时间序列:指标名称代表着监控目标上某类可测量属性的基本特征标识标签则是这个基本特征上再次细分的多个可测量维度时间序列数据:按照时间顺序记录系统、设备状态变化的数据,每个数据称为一个样本:数据采集以特定的时间周期进行,因而,随着时间流逝,将这些样本数据记录下来,将生成一个离散的样本数据序列该序列也称为向量(Vector);而将多个序列放在同一个坐标系内(以时间为横轴,以序列为纵轴),将形成一个由数据点组成的矩阵Prometheus数据模型Prometheus中,每个时间序列都由指标名称(Metric Name)和标签(Label)来唯一标识,格式为“{指标名称:通常用于描述系统上要测定的某个特征;例如,http_requests_total表示接收到的HTTP请求总数;支持使用字母、数字、下划线和冒号,且必须能匹配RE2规范的正则表达式;标签:键值型数据,附加在指标名称之上,从而让指标能够支持多纬度特征;可选项;例如,http_requests_total{method=GET}和http_requests_total{method=POST}代表着两个不同的时间序列;标签名称可使用字母、数字和下划线,且必须能匹配RE2规范的正则表达式;以“_ _”为前缀的名称为Prometheus系统预留使用指标名称及标签使用注意事项指标名称和标签的特定组合代表着一个时间序列;指标名称相同,但标签不同的组合分别代表着不同的时间序列不同的指标名称自然更是代表着不同的时间序列promQL的数据类型PromQL的表达式中支持4种数据类型:即时向量(Instant Vector):特定或全部的时间序列集合上,具有相同时间戳的一组样本值称为即时向量;范围向量(Range Vector):特定或全部的时间序列集合上,在指定的同一时间范围内的所有样本值;标量(Scalar):一个浮点型的数据值;字符串(String):支持使用单引号、双引号或反引号进行引用,但反引号中不会对转义字符进行转义数据类型演示先看个例子,后边会详细讲解:即时向量,例如:node_cpu_seconds_total{job="nodes"},返回同一时间一组样本值范围向量,例如:node_cpu_seconds_total{job="nodes"}[1m],返回1min内的所有样本值标量,例如:irate(node_cpu_seconds_total{job="nodes"}[1m]),返回一个浮点型的数据值字符串,例如:node_cpu_seconds_total{job="nodes"},"nodes"就是字符串类型。向量表达式使用要点表达式的返回值类型亦是即时向量、范围向量、标量或字符串四种类型之一,但是,有些使用场景要求表达式返回值必须满足特定的条件,例如:需要将返回值绘制成图形时,仅支持即时向量类型的数据对于诸如rate一类的速率函数来说,其要求使用的却又必须是范围向量型的数据由于范围向量型数据不能用于表达式浏览器中图形绘制功能,若使用,浏览器会返回“Error executing query: invalid expression type "range vector" for range query, must be Scalar or instant Vector”一类的错误:匹配器匹配器用于定义标签过滤条件,目前支持以下四种匹配操作符:=:选择与提供的字符串完全相同的标签!+:选择与提供的字符串不相同的标签=~:选择正则表达式与提供的字符串(或子字符串)相匹配的标签!~:选择正则表达式与提供的字符串(或子字符串)不匹配的标签。注意事项:匹配到空标签值的匹配器时,所有未定义该标签的时间序列同样符合条件正则表达式将执行完全锚定机制,它需要匹配指定标签的整个值向量选择器至少要包含一个指标名称,或者至少有一个不会匹配到空字符串的匹配器使用"__name__"作为标签名称,还能够对指标名称进行过滤,例:{name=~"http_request.*"}即时向量选择器即时向量选择器由两部分组成指标名称:用于限定特定指标下的时间序列,即负责过滤指标;可选;匹配器(Matcher):或称为标签选择器,用于过滤时间序列上的标签;定义在{}之中;可选;定义即时向量选择器时,以上两个部分应该至少给出一个;于是,这将存在以下三种组合:仅给定指标名称,或在标签名称上使用了空值的匹配器,例如node_cpu_seconds_total和node_cpu_seconds_total{}相等仅给定匹配器,返回所有符合给定匹配器的所有时间的即使样本,例如:{job="nodes"}指标名称和匹配器的组合,返回符合条件的所有时间序列上的即时样本,例如上边的node_cpu_seconds_total{job="nodes"}范围向量选择器同即时向量选择器的唯一不同之处在于,范围向量选择器需要在表达式后紧跟一个方括号[ ]来表达需在时间时序上返回的样本所处的时间范围;时间范围:以当前时间为基准时间点,指向过去一个特定的时间长度;例如[5m]便是指过去5分钟之内;时间格式:一个整数后紧跟一个时间单位,例如“5m”中的“m”即是时间单位;可用的时间单位有ms(毫秒)、s(秒)、m(分钟)、h(小时)、d(天)、w(周)和y(年); 必须使用整数时间,且能够将多个不同级别的单位进行串联组合,以时间单位由大到小为顺序,例如1h30m,但不能使用1.5h; 需要注意的是,范围向量选择器返回的是一定时间范围内的数据样本,虽然不同时间序列的数据抓取时间点相同,但它们的时间戳并不会严格对齐;多个Target上的数据抓取需要分散在抓取时间点前后一定的时间范围内,以均衡Prometheus Server的负载;因而,Prometheus在趋势上准确,但并非绝对精准。偏移量修改器默认情况下,即时向量选择器和范围向量选择器都以当前时间为基准时间点,而偏移量修改器能够修改该基准;偏移量修改器的使用方法是紧跟在选择器表达式之后使用“offset”关键字指定,例如:“http_requests_total offset 5m”,表示获取以http_requests_total为指标名称的所有时间序列在过去5分钟之时的即时样本“http_requests_total[5m] offset 1d”,表示获取距此刻1天时间之前的5分钟之内的所有样本PromQL的指标类型PromQL有四个指标类型,它们主要由Prometheus的客户端库使用:Counter:计数器,单调递增,除非重置(例如服务器或进程重启)Gauge:仪表盘,可增可减的数据Histogram:直方图,将时间范围内的数据划分成不同的时间段,并各自评估其样本个数及样本值之和,因而可计算出分位数可用于分析因异常值而引起的平均值过大的问题分位数计算要使用专用的histogram_quantile函数Summary:类似于Histogram,但客户端会直接计算并上报分位数Counter通常,Counter的总数并没有直接作用,而是需要借助于rate、topk、increase和irate等函数来生成样本数据的变化状况(增长率):rate(http_requests_total[2h]),获取2小内,该指标下各时间序列上的http总请求数的增长速率;topk(3, http_requests_total),获取该指标下http请求总数排名前3的时间序列;irate(http_requests_total[2h]),高灵敏度函数,用于计算指标的瞬时速率;基于样本范围内的最后两个样本进行计算,相较于rate函数来说,irate更适用于短期时间范围内的变化速率分析;GaugeGauge用于存储其值可增可减的指标的样本数据,常用于进行求和、取平均值、最小值、最大值等聚合计算;也会经常结合PromQL的predict_linear和delta函数使用:predict_linear(v range-vector, t, scalar)函数可以预测时间序列v在t秒后的值,它通过线性回归的方式来预测样本数据的Gauge变化趋势;predict_linear(node_sockstat_TCP_inuse{node_port="9100"}[2h],4*3600)根据近两小时的数据,预测出接下来4小时的tcp socket的活跃连接数delta(v range-vector)函数计算范围向量中每个时间序列元素的第一个值与最后一个值之差,从而展示不同时间点上的样本值的差值;delta(node_netstat_Tcp_CurrEstab{node_port="9100"}[2h]),返回该服务器活跃状态的TCP连接数与2小时之前的差异;HistogramHistogram是一种对数据分布情况的图形表示,由一系列高度不等的长条图(bar)或线段表示,用于展示单个测度的值的分布:它一般用横轴表示某个指标维度的数据取值区间,用纵轴表示样本统计的频率或频数,从而能够以二维图的形式展现数值的分布状况为了构建Histogram,首先需要将值的范围进行分段,即将所有值的整个可用范围分成一系列连续、相邻(相邻处可以是等同值)但不重叠的间隔,而后统计每个间隔中有多少值从统计学的角度看,分位数不能被聚合,也不能进行算术运算对于Prometheus来说,Histogram会在一段时间范围内对数据进行采样(通常是请求持续时长或响应大小等),并将其计入可配置的bucket(存储桶)中Histogram事先将特定测度可能的取值范围分隔为多个样本空间,并通过对落入bucket内的观测值进行计数以及求和操作与常规方式略有不同的是,Prometheus取值间隔的划分采用的是累积(Cumulative)区间间隔机制,即每个bucket中的样本均包含了其前面所有bucket中的样本,因而也称为累积直方图:可降低Histogram的维护成本支持粗略计算样本值的分位数单独提供了_sum和_count指标,从而支持计算平均值Histogram类型的每个指标有一个基础指标名称,它会提供多个时间序列:_bucket{le=""}:观测桶的上边界(upper inclusive bound),即样本统计区间,最大区间(包含所有样本)的名称为_bucket{le="+Inf"}; _sum:所有样本观测值的总和; _count :总的观测次数,它自身本质上是一个Counter类型的指标;累积间隔机制生成的样本数据需要额外使用内置的histogram_quantile()函数即可根据Histogram指标来计算相应的分位数(quantile),即某个bucket的样本数在所有样本数中占据的比例:histogram_quantile()函数在计算分位数时会假定每个区间内的样本满足线性分布状态,因而它的结果仅是一个预估值,并不完全准确;预估的准确度取决于bucket区间划分的粒度;粒度越大,准确度越低;Summary指标类型是客户端库的特性,而Histogram在客户端仅是简单的桶划分和分桶计数,分位数计算由Prometheus Server基于样本数据进行估算,因而其结果未必准确,甚至不合理的bucket划分会导致较大的误差;Summary是一种类似于Histogram的指标类型,但它在客户端于一段时间内(默认为10分钟)的每个采样点进行统计,计算并存储了分位数数值,Server端直接抓取相应值即可;但Summary不支持sum或avg一类的聚合运算,而且其分位数由客户端计算并生成,Server端无法获取客户端未定义的分位数,而Histogram可通过PromQL任意定义,有着较好的灵活性;对于每个指标,Summary以指标名称为前缀,生成如下几个个指标序列:{quantile="<φ>"},其中φ是分位点,其取值范围是(0 ≤φ≤ 1);计数器类型指标;如下是几种典型的常用分位点;0、0.25、0.5、0.75和1几个分位点;0.5、0.9和0.99几个分位点;0.01、0.05、0.5、0.9和0.99几个分位点;_sum,抓取到的所有样本值之和;_count,抓取到的所有样本总Prometheus的聚合函数聚合表达式PromQL中的聚合操作语法格式可采用如下面两种格式之一:([parameter,] ) [without|by (ignore:定义匹配检测时要忽略的标签;on:定义匹配检测时只使用的标签;举例有这样一组数据:ignoring( ) on( )
method_code:http_errors:rate5m{method="get", code="500"} 24method_code:http_errors:rate5m{method="get", code="404"} 30method_code:http_errors:rate5m{method="put", code="501"} 3method_code:http_errors:rate5m{method="post", code="500"} 6method_code:http_errors:rate5m{method="post", code="404"} 21method:http_requests:rate5m{method="get"} 600method:http_requests:rate5m{method="del"} 34method:http_requests:rate5m{method="post"} 120运算表达式:
method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m如果不加 ignoring(code) 的话,左边将无法匹配到右边的结果,因为两边向量没有完全一致的标签,此时是这种情况:
#左边method_code:http_errors:rate5m{method="get", code="500"} 24method_code:http_errors:rate5m{method="post", code="500"} 6#右边method:http_requests:rate5m{method="get"} 600method:http_requests:rate5m{method="del"} 34method:http_requests:rate5m{method="post"} 120只有将code标签忽略,成为这种情况:
#左边method_code:http_errors:rate5m{method="get"} 24method_code:http_errors:rate5m{method="post"} 6#右边method:http_requests:rate5m{method="get"} 600method:http_requests:rate5m{method="del"} 34method:http_requests:rate5m{method="post"} 120这时左边和右边就有一模一样的标签组合,所以完成了1对1匹配。最终结果:
{method="get"} 0.04 // 24 / 600 {method="post"} 0.05 // 6 / 120向量一对多/多对一匹配“一”侧的每个元素,可与“多”侧的多个元素进行匹配;必须使用group_left或group_right明确指定哪侧为“多”侧;匹配表达式语法:
ignore:定义匹配检测时要忽略的标签;on:定义匹配检测时只使用的标签;举例还是这样一组数据:ignoring( ) group_left( ) ignoring( ) group_right( ) on( ) group_left( ) on( ) group_right( )
method_code:http_errors:rate5m{method="get", code="500"} 24method_code:http_errors:rate5m{method="get", code="404"} 30method_code:http_errors:rate5m{method="put", code="501"} 3method_code:http_errors:rate5m{method="post", code="500"} 6method_code:http_errors:rate5m{method="post", code="404"} 21method:http_requests:rate5m{method="get"} 600method:http_requests:rate5m{method="del"} 34method:http_requests:rate5m{method="post"} 120运算表达式:
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m此时的数据是这样的:
#左边:method_code:http_errors:rate5m{method="get", code="500"} 24method_code:http_errors:rate5m{method="get", code="404"} 30method_code:http_errors:rate5m{method="put", code="501"} 3method_code:http_errors:rate5m{method="post", code="500"} 6method_code:http_errors:rate5m{method="post", code="404"} 21#右边method:http_requests:rate5m{method="get"} 600method:http_requests:rate5m{method="del"} 34method:http_requests:rate5m{method="post"} 120因为忽略的code标签,最终结果:
{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至此,promQL聚合语句基本总结完毕,后续会prometheus的自动发现,以及relabel等常用功能进行演示,欢迎关注。
> 官方文档:https://prometheus.io/docs/prometheus/latest/querying/operators/#vector-matching
关键词:
Copyright 2015-2023 非洲地质网版权所有 备案号:沪ICP备2022005074号-8 联系邮箱:58 55 97 3@qq.com