PromQL聚合操作【合并查询】
聚合操作使用语法:
<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
sum (求和) min (最小值) max (最大值) avg (平均值) stddev (标准差) stdvar (标准差异) count (计数) count_values (对value进行计数) bottomk (后n条时序) topk (前n条时序) quantile (分布统计)
例子:匹配出 linux CPU 使用率大于80%
100 -avg(irate(node_cpu_seconds_total{owner="devops",envtype=~"product",mode="idle"}[5m])) by (instance)* 100 > 80
Counter 只增不减的计数器
Counter类型的指标其工作方式和计数器一样,只增不减 (除非系统发生重置) , 常见的监控指标,如http_requests_total,node_cpu都是Counter类型的监控指标 , 一般在定义Counter类型指标的名称时推荐使用_total作为后缀。
例如: 通过rate() 函数获取HTTP请求量的增长率
rate(http_requests_total[5m])
查询当前系统中,访问量前十的HTTP地址
topk(10, http_reqursts_total)
Gauge 可增可减的仪表盘
Gauge类型的指标侧重于反应系统的当前状态,常见指标如:node_memory_MemFree(主机当前空闲的内容大小)、node_memory_MemAvailable(可用内存大小)
直接查看当前系统状态 node_memory_MemFree 对于Gauge类型的监控指标,通过PromQL内置函数delta()可以获取样本在一段时间返回内的变化情况 计算CPU温度在两个小时内的差异 delta(cpu_temp_celsius{host="zeus"}[2h]) 还可以使用deriv()计算样本的线性回归模型,还可用predict_linear()对数据的变化趋势进行预测 预测系统磁盘空间在4个小时之后的剩余情况: predict_linear(node_filesystem_free{job="node"}[1h], 4 * 3600)
PromQL 操作符
数学运算符: + (加法) - (减法) * (乘法) 1/ (除法) % (求余) ^ (幂运算)
布尔运算符: == (相等) != (不相等) > (大于) < (小于) >= (大于等于) <= (小于等于)
集合运算符: and(并且) or(或者) inless(排除)
匹配模式: =(等于) !=(不等于)
时间范围单位: s - 秒 m - 分钟 h - 小时 d - 天 w - 周 y - 年
操作符优先级和小学做算术题一样,先乘除再加减,先大括号再小括号
类似MySQL的查询结果做运算
查询 rate irate
该函数用来计算某个指标在最近的一个区间时间内的变化率
比如说 Prometheus没15秒采集一次数据,一分钟采集四次数据,计算逻辑如下:
rate : 1m内,找到这四个采集点,然后用该区间最后一个采集点与第一个采集点的value差,除以这两个采集点的时间差(s),相当于求出每一秒的平均数据
irate:该函数与rate函数不同的是,它是用区间内的最后一个采集点与倒数第二个采集点的value差,除以这两个采集点的时间差
联合查询 多对一 & 一对多
多对一和一对多两种匹配模式指的是 一侧 的每一个向量元素可以与 多侧 的 多个 元素匹配的情况,在这种情况下,必须用 group 修饰符
group_left 或者 group_right 来确定哪一个向量具有更高的基数,充当多的角色
<vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr> <vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr> <vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr> <vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>
多对一和一对多两种模式一定是出现在操作符两侧表达式返回的向量标签不一致的情况。因此需要使用 ignoring 和 on 修饰符来排除或者限定匹配的标签列表。
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
该表达式中,左向量 method_code:http_errors:rate5m 包含两个标签 method 和 code。而右向量 method:http_requests:rate5m 中只包含一个标签 method,因此匹配时需要使用 ignoring 限定匹配的标签为 code。 在限定匹配标签后,右向量中的元素可能匹配到多个左向量中的元素 因此该表达式的匹配模式为多对一,需要使用 group 修饰符 group_left 指定左向量具有更好的基数。
计算结果 {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
一个具体的例子 参考:https://blog.csdn.net/lwlfox/article/details/103858180
有查询语句1(得到温度传感器的名称):
node_hwmon_sensor_label{instance="192.168.1.100", label=~"core_.*"}
得到结果:
node_hwmon_sensor_label{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", label="core_0", sensor="temp2"} 1 node_hwmon_sensor_label{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", label="core_1", sensor="temp3"} 1 node_hwmon_sensor_label{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", label="core_2", sensor="temp4"} 1 node_hwmon_sensor_label{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", label="core_3", sensor="temp5"} 1
有查询语句2(得到温度传感器的温度值):
node_hwmon_temp_celsius{instance="192.168.1.100", chip=~".+core.+"}
得到结果:
node_hwmon_temp_celsius{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", sensor="temp1"} 37 node_hwmon_temp_celsius{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", sensor="temp2"} 34 node_hwmon_temp_celsius{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", sensor="temp3"} 37 node_hwmon_temp_celsius{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", sensor="temp4"} 35 node_hwmon_temp_celsius{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", sensor="temp5"} 34
遇到的问题是:在查询语句2中得到的结果没有标识此温度传感器叫什么名字,对应到哪个核心CPU上,此名字在查询语句1中可以得到,
所以,目标就是通过一行查询语言,得到温度的同时,也可以得到此传感器对应到哪个CPU核心上。这两个结果中,可以通过sensor="tempX"进行关联,则有如下语句:
0 * node_hwmon_sensor_label{instance="192.168.1.100", label=~"core_.*"} + on (sensor) group_left(node_hwmon_temp_celsius) node_hwmon_temp_celsius{instance="192.168.1.100", chip=~".+core.+"}
得到结果:
{chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", label="core_0", sensor="temp2"} 33 {chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", label="core_1", sensor="temp3"} 36 {chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", label="core_2", sensor="temp4"} 35 {chip="platform_coretemp_0", instance="192.168.1.100", job="node-development", label="core_3", sensor="temp5"} 34
聚合操作
stddev (标准差) stdvar (标准差异) count (计数) count_values (对 value 进行计数) bottomk (样本值最小的 k 个元素) topk (样本值最大的k个元素) quantile (分布统计)
内置的聚合操作符可以将瞬时的表达式返回的样本数据进行聚合,形成一个具有较少样本值的新的时间序列
这些操作符被用于聚合所有标签维度,或者通过without 或者 by 自语句来保留不同的维度
without
用于从计算结果中移除列举的标签,而保留其它标签。by
则正好相反,结果向量中只保留列出的标签,其余标签则移除。通过 without 和 by 可以按照样本的问题对数据进行聚合。
例如: sum(http_requests_total) without (instance) 等价于 sum(http_requests_total) by (application, group)
count_values 用于时间序列中每一个样本值出现的次数,count_values 会为每一个唯一的样本值输出一个时间序列,并且每一个时间序列包括一个额外的标签。
例如:统计同版本的二进制文件数量 count_values("version", build_version) 返回结果如下: {count="641"} 1 {count="3226"} 2 {count="644"} 4