参考链接:https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/promql
探索PromQL
通过PromQL用户可以非常方便地对监控样本数据进行统计分析,PromQL支持常见的运算操作符,同时PromQL中还提供了大量的内置函数可以实现对数据的高级处理。当然在学习PromQL之前,用户还需要了解Prometheus的样本数据模型。PromQL作为Prometheus的核心能力除了实现数据的对外查询和展现,同时告警监控也是依赖PromQL实现。
Metrics类型
Prometheus定义了4中不同的指标类型:
- Counter(计数器):只增不减的计数器,常见的监控指标,如http_requests_total,node_cpu都是Counter类型的监控指标。
- Gauge(仪表盘):可增可减的仪表盘,Gauge类型的指标侧重于反应系统的当前状态。因此这类指标的样本数据可增可减。常见指标如:node_memory_MemFree(主机当前空闲的内容大小)、node_memory_MemAvailable(可用内存大小)都是Gauge类型的监控指标。
- Histogram(直方图):主要用于统计和分享样本的分布情况。Histogram通过histogram_quantile函数是在服务器端计算的分位数。
- Summary(摘要):主要用于统计和分享样本的分布情况。Sumamry的分位数则是直接在客户端计算完成。
初识PromQL
Prometheus通过指标名称(metrics name)以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而label则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤,聚合,统计从而产生新的计算后的一条时间序列。
查询时间序列
PromQL还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。
PromQL支持使用=和!=两种完全匹配模式:
- 通过使用label=value可以选择那些标签满足表达式定义的时间序列
- 反之使用label!=value则可以根据标签匹配排除时间序列
PromQL还可以支持使用正则表达式作为匹配条件,多个表达式之间使用 | 进行分离
- 使用label=~regx表示选择那些标签符合正则表达式定义的时间序列
- 反之使用label!~regx进行排除
例如:如果想查询多个环节下的时间序列可以使用如下表达式:
http_requests_total{environment=~"staging|testing|development",method!="GET"}
范围查询
直接通过类似于PromQL表达式httprequeststotal查询时间序列时,返回值中只会包含时间序列中的最新的一个样本值,这样的返回结果我们称之为瞬时向量。而相应的这样的表达式称之为瞬时向量表达式。
而如果我们想要过去一段时间范围内的样本数据时,我们则需要使用区间向量表达式。区间向量表达式和瞬时向量表达式之间的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器 [] 进行定义。
例如:通过以下表达式可以选择最近5分钟内的所有样本数据:
http_request_total{}[5m]
除了使用m表示分钟以外,PromQL的时间范围选择器支持其他时间单位:
- s - 秒
- m - 分钟
- h - 小时
- d - 天
- w - 周
- y - 年
时间位移操作
在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准:
http_request_total{} # 瞬时向量表达式,选择当前最新的数据 http_request_total{}[5m] # 区间向量表达式,选择以当前时间为基准,5分钟内的数据
而如果我们想查询,5分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢?这个时候我们就可以使用位移操作,位移操作的关键字为offset。
例如:
http_request_total{} offset 5m http_request_total{}[1d] offset 1d
使用聚合操作
一般来说,如果描述样本特征的标签(label)在并非唯一的情况下,通过PromQL查询数据,会返回多条满足这些特征维度的时间序列。而PromQL提供的聚合操作可以用来对这些时间序列进行处理,形成一条新的时间序列:
# 查询系统所有http请求的总量 sum(http_request_total) # 按照mode计算主机CPU的平均使用时间 avg(node_cpu) by (mode) # 按照主机查询各个主机的CPU使用率 sum(sum(irate(node_cpu{mode!='idle'}[5m])) / sum(irate(node_cpu[5m]))) by (instance)
PromQL操作符
使用PromQL除了能够方便的按照查询和过滤时间序列以外,PromQL还支持丰富的操作符,用户可以使用这些操作符进一步对事件序列进行二次加工,这些操作符包括:数学运算符,逻辑运算符,布尔运算等。
数学运算
PromQL支持的所有数学运算符如下所示:
- +(加法)
- - (减法)
- * (乘法)
- / (除法)
- %(求余)
- ^(幂运算)
使用布尔运算过滤时间序列
- ==(相等)
- !=(不相等)
- >(大于)
- <(小于)
- >=(大于等于)
- <=(小于等于)
使用bool修饰符改变布尔运算符的行为
布尔运算符的默认行为是对时序数据进行过滤。而在其它的情况下我们可能需要的是真正的布尔结果。例如,只需要知道当前模块的HTTP请求量是否>=1000,如果大于等于1000则返回1(true)否则返回0(false)。这时可以使用bool修饰符改变布尔运算的默认行为。 例如:
http_requests_total > bool 1000
使用bool修改符后,布尔运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果0或者1。从而形成一条新的时间序列。
使用集合运算符
使用瞬时向量表达式能够获取到一个包含多个时间序列的集合,我们称为瞬时向量。 通过集合运算,可以在两个瞬时向量与瞬时向量之间进行相应的集合操作。目前,Prometheus支持以下集合运算符:
- and(并且)
- or(或者)
- unless(排除)
vector1 and vector2 会产生一个由vector1的元素组成的新的向量。该向量包含vector1中完全匹配vector2中的元素组成。
vector1 or vector2 会产生一个新的向量,该向量包含vector1中所有的样本数据,以及vector2中没有与vector1匹配到的样本数据。
vector1 unless vector2 会产生一个新的向量,新向量中的元素由vector1中没有与vector2匹配的元素组成。
操作符优先级
- ^
- * / %
- + -
- == != <= < >= >
- and unless
- or
PromQL聚合操作
Prometheus还提供了下列内置的聚合操作符,这些操作符作用域瞬时向量。可以将瞬时表达式返回的样本数据进行聚合,形成一个新的时间序列。
- sum(求和)
- min(最小值)
- max(最大值)
- avg(平均值)
- stddev(标准差)
- stdvar(标准差异)
- count(计数)
- count_values(对value进行计数)
- bottomk(后n条时序)
- topk(前n条时序)
- quantile(分布统计)
使用聚合操作的语法如下:
<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
其中只有count_values, quantile, topk, bottomk支持参数(parameter)。
without用于从计算结果中移除列举的标签,而保留其它标签。by则正好相反,结果向量中只保留列出的标签,其余标签则移除。通过without和by可以按照样本的问题对数据进行聚合。