Prometheus查询语法总结

1.Prometheus监控语法说明

本文档主要分为两部分,分别讲解PromQL和Grafana的基础使用,在阅读PromQL部分时,建议不要联想Grafana中要怎么使用这些查询表达式,又是怎么根据查询结果绘图的,因为PromQL对于Grafana来说和SQL并没有区别,都是查询出结果,然后根据各种指定配置进行绘图,所以阅读和理解PromQL部分,应关注查询结果是什么样的,不要关注这些结果在Grafana中是怎么绘图的。

2.PromQL语法介绍

Prometheus通过指标名称(metrics name)以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而label则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤,聚合,统计从而产生新的计算后的一条时间序列。PromQL是Prometheus内置的数据查询语言,其提供对时间序列数据丰富的查询,聚合以及逻辑运算能力的支持。并且被广泛应用在Prometheus的日常应用当中,包括对数据查询、可视化、告警处理当中。可以这么说,PromQL是Prometheus所有应用场景的基础,理解和掌握PromQL是Prometheus入门的第一课。

2.1 基本用法

2.1.1 查询时间序列

当Prometheus通过Exporter采集到相应的监控指标样本数据后,我们就可以通过PromQL对监控样本数据进行查询。
当我们直接使用监控指标名称查询时,可以查询该指标下的所有时间序列。如:

prometheus_http_requests_total

等同于:

prometheus_http_requests_total{}

该表达式会返回指标名称为prometheus_http_requests_total的所有时间序列:

prometheus_http_requests_total{code="200",handler="alerts",instance="localhost:9090",job="prometheus",method="get"}= (20889@1518096812.326) 
prometheus_http_requests_total{code="200",handler="graph",instance="localhost:9090",job="prometheus",method="get"}= (21287@1518096812.326)

PromQL还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。

  • PromQL支持使用 = 和 != 两种完全匹配模式:
  • 通过使用 label=value 可以选择那些标签满足表达式定义的时间序列;
  • 反之使用 label!=value 则可以根据标签匹配排除时间序列;
    例如,如果我们只需要查询所有prometheus_http_requests_total时间序列中满足标签instance为localhost:9090的时间 序列,则可以使用如下表达式:
prometheus_http_requests_total{instance="localhost:9090"}

反之使用 instance!=“localhost:9090” 则可以排除这些时间序列:

prometheus_http_requests_total{instance!="localhost:9090"}
  • PromQL还可以支持使用正则表达式作为匹配条件,多个表达式之间使用 | 进行分离:
  • 使用 label=~regx 表示选择那些标签符合正则表达式定义的时间序列;
  • 反之使用 label!~regx 进行排除;
    例如,如果想查询多个环节下的时间序列序列可以使用如下表达式:
prometheus_http_requests_total{environment=~"staging|testing|development",method!="GET"}

排除用法

prometheus_http_requests_total{environment!~"staging|testing|development",method!="GET"}

2.1.2范围查询

直接通过类似于PromQL表达式httprequeststotal查询时间序列时,返回值中只会包含该时间序列中的最新的一个样本值,这样的返回结果我们称之为瞬时向量。而相应的这样的表达式称之为__瞬时向量表达式。
而如果我们想过去一段时间范围内的样本数据时,我们则需要使用区间向量表达式。区间向量表达式和瞬时向量表达式之间的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器 [] 进行定义。 例如,通过以下表达式可以选择最近5分钟内的所有样本数据:

prometheus_http_requests_total{}[5m]

该表达式将会返回查询到的时间序列中最近5分钟的所有样本数据:

prometheus_http_requests_total{code="200",handler="alerts",instance="localhost:9090",job="prometheus",method="get"}=[ 
	1@1518096812.326
	1@1518096817.326
	1@1518096822.326
	1@1518096827.326
	1@1518096832.326
	1@1518096837.325
] 
prometheus_http_requests_total{code="200",handler="graph",instance="localhost:9090",job="prometheus",method="get"}=[ 
	4@1518096812.326
	4@1518096817.326
	4@1518096822.326
	4@1518096827.326 
	4@1518096832.326
	4@1518096837.325
]

通过区间向量表达式查询到的结果我们称为区间向量。 除了使用m表示分钟以外,PromQL的时间范围选择器支持其它时间单位:

  • s - 秒
  • m - 分钟
  • h - 小时
  • d - 天
  • w - 周
  • y - 年

2.1.3时间位移操作

在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准:

prometheus_http_requests_total{} # 瞬时向量表达式,选择当前最新的数据
prometheus_http_requests_total{}[5m] # 区间向量表达式,选择以当前时间为基准,5分钟内的数据

而如果我们想查询,5分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢? 这个时候我们就可以使用位移操作,位移操作的关键字为offset。 可以使用offset时间位移操作:

prometheus_http_requests_total{} offset 5m
prometheus_http_requests_total{}[1d] offset 1d

2.1.4使用聚合操作

一般来说,如果描述样本特征的标签(label)在并非唯一的情况下,通过PromQL查询数据,会返回多条满足这些特征维度的时间序列。而PromQL提供的聚合操作可以用来对这些时间序列进行处理,形成一条新的时间序列:

# 查询系统所有http请求的总量
sum(prometheus_http_requests_total)

# 按照mode计算主机CPU的平均使用时间
avg(node_cpu_seconds_total) by (mode)

# 按照主机查询各个主机的CPU使用率
sum(sum(irate(node_cpu_seconds_total{mode!='idle'}[5m])) / sum(irate(node_cpu_ seconds_total [5m]))) by (instance) 

2.1.5标量和字符串

除了使用瞬时向量表达式和区间向量表达式以外,PromQL还直接支持用户使用标量(Scalar)和字符串(String)。

  • 标量(Scalar):一个浮点型的数字值
    标量只有一个数字,没有时序。 例如:
10 

需要注意的是,当使用表达式count(prometheus_http_requests_total),返回的数据类型,依然是瞬时向量。用户可以通过内置函数scalar()将单个瞬时向量转换为标量。

  • 字符串(String):一个简单的字符串值
    直接使用字符串,作为PromQL表达式,则会直接返回字符串。
"this is a string" 
'these are unescaped: \n \\ \t' 
`these are not unescaped: \n ' " \t` 

2.1.6合法的PromQL表达式

所有的PromQL表达式都必须至少包含一个指标名称(例如http_request_total),或者一个不会匹配到空字符串的标签过滤器(例如{code=”200”})。
因此以下两种方式,均为合法的表达式:

prometheus_http_requests_total # 合法
prometheus_http_requests_total{} # 合法
{method="get"} # 合法 

而如下表达式,则不合法:

{job=~".*"} # 不合法 

同时,除了使用 {label=value} 的形式以外,我们还可以使用内置的 name 标签来指定监控指标名称:

{__name__=~"prometheus_http_requests_total"} # 合法
{__name__=~"node_disk_bytes_read|node_disk_bytes_written"} # 合法

2.2PromQL操作符

使用PromQL除了能够方便的按照查询和过滤时间序列以外,PromQL还支持丰富的操作符,用户可以使用这些操作符对进一步的对事件序列进行二次加工。这些操作符包括:数学运算符,逻辑运算符,布尔运算符等等。

2.2.1数学运算

PromQL支持的所有数学运算符如下所示:

    • (加法)
    • (减法)
    • (乘法)
  • / (除法)
  • % (求余)
  • ^ (幂运算)

2.2.2布尔运算

  • Prometheus支持以下布尔运算符如下:
  • == (相等)
  • != (不相等)
  • (大于)

  • < (小于)
  • = (大于等于)

  • <= (小于等于)
  • 使用bool修饰符改变布尔运算符的行为
    布尔运算符的默认行为是对时序数据进行过滤。而在其它的情况下我们可能需要的是真正的布尔结果。例如,只需要 知道当前模块的HTTP请求量是否>=1000,如果大于等于1000则返回1(true)否则返回0(false)。这时可以使 用bool修饰符改变布尔运算的默认行为。 例如:
prometheus_http_requests_total > bool 1000 

使用bool修改符后,布尔运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果 0或者1。从而形成一条新的时间序列。

prometheus_http_requests_total{code="200",handler="query",instance="localhost:9090",job="prometheus",method="get"} 	1 
prometheus_http_requests_total{code="200",handler="query_range",instance="localhost:9090",job="prometheus",method="get"} 	0 

同时需要注意的是,如果是在两个标量之间使用布尔运算,则必须使用bool修饰符

2 == bool 2 # 结果为1

2.2.3使用集合运算符

使用瞬时向量表达式能够获取到一个包含多个时间序列的集合,我们称为瞬时向量。 通过集合运算,可以在两个瞬时向量与瞬时向量之间进行相应的集合操作。
目前,Prometheus支持以下集合运算符:

  • and (并且)
  • or (或者)
  • unless (排除)
    vector1 and vector2 会产生一个由vector1的元素组成的新的向量。该向量包含vector1中完全匹配vector2 中的元素组成。
    vector1 or vector2 会产生一个新的向量,该向量包含vector1中所有的样本数据,以及vector2中没有与 vector1匹配到的样本数据。
    vector1 unless vector2 会产生一个新的向量,新向量中的元素由vector1中没有与vector2匹配的元素组成。

2.2.4操作符优先级

对于复杂类型的表达式,需要了解运算操作的运行优先级。例如,查询主机的CPU使用率,可以使用表达式:

100 * (1 - avg (irate(node_cpu_seconds_total{mode='idle'}[5m])) by(job) ) 

其中irate是PromQL中的内置函数,用于计算区间向量中时间序列每秒的即时增长率。在PromQL操作符中优先级由高到低依次为:

  • ^
  • *, /, %
  • +, -
  • ==, !=, <=, =, >
  • and, unless
  • or

2.2.5PromQL聚合操作

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可以按照样本的问题对数据进行聚合。
例如:

sum(prometheus_http_requests_total) without (instance) 

等价于

sum(prometheus_http_requests_total) by (code,handler,job,method) 

如果只需要计算整个应用的HTTP请求总量,可以直接使用表达式:

sum(prometheus_http_requests_total) 

count_values用于时间序列中每一个样本值出现的次数。count_values会为每一个唯一的样本值输出一个时间序列,并且每一个时间序列包含一个额外的标签。 例如:

count_values("count", prometheus_http_requests_total) 

topk和bottomk则用于对样本值进行排序,返回当前样本值前n位,或者后n位的时间序列。
获取HTTP请求数前5位的时序样本数据,可以使用表达式:

topk(5, prometheus_http_requests_total)

quantile用于计算当前样本数据值的分布情况quantile(φ, express)其中0 ≤ φ ≤ 1。
例如,当φ为0.5时,即表示找到当前样本数据中的中位数:

quantile(0.5, prometheus_http_requests_total)

你可能感兴趣的:(数据监控,prometheus,人工智能,PromQL)