Prometheus数据查询DSL语言PromQL


原文链接: Prometheus数据查询DSL语言PromQL

PromQL内置函数 - prometheus-book
第2章 探索PromQL
PromQL (Prometheus Query Language) 是 Prometheus 自己开发的数据查询 DSL 语言,语言表现力非常丰富,内置函数很多,在日常数据可视化以及rule 告警中都会使用到它。

在页面 http://localhost:9090/graph 中,输入下面的查询语句,查看结果,例如:

http_requests_total{code="200"}

prometheus一些术语

prometheus的metrics分为四类(counter,gauge,histogram,summary)详情(metrics-type),metrics_name的命令也应该符合一定的规范:metrics-name,METRIC AND LABEL NAMING

metrics_name : 也就是指标名,通常我们都会用如http_request_total等进行查询;
metrics_label :指标的标签,也就是metrics_name{label-1=”a”,label-2=”b”}这种;
metrics_value : 通常用指标名+标签查出来一个值,该值根据metrics的类型可能为浮点数,也可能为整数。
0,基础查询

也就是使用metrics_name+metrics_label的组合进行查询,这种查询的效率的基础是你要知道明确知道相应的name和label,如果有错误拼写,则可能数据无法展示,prometheus的查询工具能帮我们模糊匹配出所有的metrics_name。可以使用label进行筛选。
如果只记得部分metrics_name,那么可以使用内置的label:{name=~"metrics_name_you_remember:.*"}这样去匹配出来你想要的标签。
1,正则匹配查询

prometheus里面用的最多的查询可能就是正则匹配了。经常配合grafana的变量(variable)一起使用。比如:
sum(irate(node_disk_reads_completed{device!~"dm-."}[5m])),这里面的device!~"dm-.",后面
引号内的dm-.*就是不匹配dm-前缀的所有metrics_name。如果要匹配的话使用=~。这样要注意,如果是或
的话要用(regrex_A|regrex_B),用小括号加|。
2,常用的操作符和函数

prometheus支持常用的操作符:+,-,*,/,>=,<,>,....等

count是对查询的结果数量进行总和+; 而sum是对查询出来的value进行总和+;

它也支持比如topk,bottomk,min,max等等。

Prometheus表达式或子表达式可以评估为一下四种类型之一:

即时向量(Instant vector) - 包含每个时间序列单个样品的一组时间序列,共享相同的时间戳
范围向量(Range vector) - 包含一个范围内数据点的一组时间序列
标量(Scalar) - 一个简单的数字浮点值
字符串(String) - 一个简单的字符串值;当前未使用

字符串和数字

字符串: 在查询语句中,字符串往往作为查询条件 labels 的值,和 Golang 字符串语法一致,可以使用 "", '', 或者 `` , 格式如:

"this is a string"
'these are unescaped: \n \ \t'
these are not unescaped: \n ' " \t

正数,浮点数: 表达式中可以使用正数或浮点数,例如:

3
-2.4

查询结果类型

PromQL 查询结果主要有 3 种类型:

瞬时数据 (Instant vector): 包含一组时序,每个时序只有一个点,例如:http_requests_total
区间数据 (Range vector): 包含一组时序,每个时序有多个点,例如:http_requests_total[5m]
纯量数据 (Scalar): 纯量只有一个数字,没有时序,例如:count(http_requests_total)

查询条件

Prometheus 存储的是时序数据,而它的时序是由名字和一组标签构成的,其实名字也可以写出标签的形式,例如 http_requests_total 等价于 {name="http_requests_total"}。

一个简单的查询相当于是对各种标签的筛选,例如:

http_requests_total{code="200"} // 表示查询名字为 http_requests_total,code 为 "200" 的数据

查询条件支持正则匹配,例如:

http_requests_total{code!="200"} // 表示查询 code 不为 "200" 的数据
http_requests_total{code=~"2.."} // 表示查询 code 为 "2xx" 的数据
http_requests_total{code!~"2.."} // 表示查询 code 不为 "2xx" 的数据

操作符

Prometheus 查询语句中,支持常见的各种表达式操作符,例如

算术运算符:

支持的算术运算符有 +,-,*,/,%,^, 例如 http_requests_total * 2 表示将 http_requests_total 所有数据 double 一倍。

比较运算符:

支持的比较运算符有 ==,!=,>,<,>=,<=, 例如 http_requests_total > 100 表示 http_requests_total 结果中大于 100 的数据。

逻辑运算符:

支持的逻辑运算符有 and,or,unless, 例如 http_requests_total == 5 or http_requests_total == 2 表示 http_requests_total 结果中等于 5 或者 2 的数据。

聚合运算符:

支持的聚合运算符有 sum,min,max,avg,stddev,stdvar,count,count_values,bottomk,topk,quantile,, 例如 max(http_requests_total) 表示 http_requests_total 结果中最大的数据。

注意,和四则运算类型,Prometheus 的运算符也有优先级,它们遵从(^)> (*, /, %) > (+, -) > (==, !=, <=, <, >=, >) > (and, unless) > (or) 的原则。
内置函数

Prometheus 内置不少函数,方便查询以及数据格式化,例如将结果由浮点数转为整数的 floor 和 ceil,

floor(avg(http_requests_total{code="200"}))
ceil(avg(http_requests_total{code="200"}))

查看 http_requests_total 5分钟内,平均每秒数据

rate(http_requests_total[5m])

基本查询对比

假设当前时间为 2017/5/22 14:48:30

查询当前所有数据 往前推10s

// PromQL
http_requests_total

// MySQL
SELECT * from http_requests_total WHERE created_at BETWEEN 1495435700 AND 1495435710;

我们查询 MySQL 数据的时候,需要将当前时间向前推一定间隔,比如这里的 10s (Prometheus 数据抓取间隔),这样才能确保查询到数据,而 PromQL 自动帮我们实现了这个逻辑。

条件查询

// PromQL
http_requests_total{code="200", handler="query"}

// MySQL
SELECT * from http_requests_total WHERE code="200" AND handler="query" AND created_at BETWEEN 1495435700 AND 1495435710;

模糊查询: code 为 2xx 的数据

// PromQL
http_requests_total{code~="2xx"}

// MySQL
SELECT * from http_requests_total WHERE code LIKE "%2%" AND created_at BETWEEN 1495435700 AND 1495435710;

比较查询: value 大于 100 的数据

// PromQL
http_requests_total > 100

// MySQL
SELECT * from http_requests_total WHERE value > 100 AND created_at BETWEEN 1495435700 AND 1495435710;

范围区间查询: 过去 5 分钟数据

// PromQL
http_requests_total[5m]

// MySQL
SELECT * from http_requests_total WHERE created_at BETWEEN 1495435410 AND 1495435710;

聚合, 统计高级查询

count 查询: 统计当前记录总数

// PromQL
count(http_requests_total)

// MySQL
SELECT COUNT(*) from http_requests_total WHERE created_at BETWEEN 1495435700 AND 1495435710;

sum 查询: 统计当前数据总值

// PromQL
sum(http_requests_total)

// MySQL
SELECT SUM(value) from http_requests_total WHERE created_at BETWEEN 1495435700 AND 1495435710;

avg 查询: 统计当前数据平均值

// PromQL
avg(http_requests_total)

// MySQL
SELECT AVG(value) from http_requests_total WHERE created_at BETWEEN 1495435700 AND 1495435710;

top 查询: 查询最靠前的 3 个值

// PromQL
topk(3, http_requests_total)

// MySQL
SELECT * from http_requests_total WHERE created_at BETWEEN 1495435700 AND 1495435710 ORDER BY value DESC LIMIT 3;

irate 查询,过去 5 分钟平均每秒数值

// PromQL
irate(http_requests_total[5m])

// MySQL
SELECT code, handler, instance, job, method, SUM(value)/300 AS value from http_requests_total WHERE created_at BETWEEN 1495435700 AND 1495435710 GROUP BY code, handler, instance, job, method;

总结

通过以上一些示例可以看出,在常用查询和统计方面,PromQL 比 MySQL 简单和丰富很多,而且查询性能也高不少。

`