57、Prometheus-PromQL基础-运算符、聚合、功能函数
1、数据基础
1.1、时间序列
1.1.1、介绍
时间序列数据:按照时间顺序记录系统、设备状态变化的数据,每个数据称为一个样本;
数据采集以特定的时间周期进行,因而,随着时间流逝,将这些样本数据记录下来,将生成一个离散的样本数据序列;
该序列也称为向量(Vector);而将多个序列放在同一个坐标系内(以时间为横轴,以序列为纵轴),将形成一个由数据点组成的矩阵;
1.1.2、离散图
1.2、功能简介
Prometheus基于指标名称(metrics name)以及附属的标签集(labelset)唯一定义一条时间序列。 - 指标名称代表着监控目标上某类可测量属性的基本特征标识。 - 标签则是这个基本特征上再次细分的多个可测量维度。
1.3、数据模型
1.3.1、指标名称、标签介绍
Prometheus中,每个时间序列都由指标名称(Metric Name)和标签(Label)来唯一标识,格式为“<metric name>{<label name>=<label value>, …}”; 指标名称:通常用于描述系统上要测定的某个特征; 例如,http_requests_total表示接收到的HTTP请求总数; 支持使用字母、数字、下划线和冒号,且必须能匹配RE2规范的正则表达式;
标签:键值型数据,附加在指标名称之上,从而让指标能够支持多纬度特征;可选项; 例如,http_requests_total{method=GET}和http_requests_total{method=POST}代表着两个不同的时间序列; 标签名称可使用字母、数字和下划线,且必须能匹配RE2规范的正则表达式;
以“__”为前缀的名称为Prometheus系统预留使用;
1.3.2、Metric Name的表示方式
方式1:http_requests_total{status="200",method="GET"} 方式2【通常用于Prometheus内部】:{__name__="http_requests_total,status="200",method="GET}
1.4、样本数据
1.4.1、样本组成
Prometheus的每个数据样本由两部分组成
float64格式的数据
毫秒精度的时间戳
1.4.2、样本图
1.5、注意事项
指标名称和标签的特定组合代表着一个时间序列;
指标名称相同,但标签不同的组合分别代表着不同的时间序列;
不同的指标名称自然更是代表着不同的时间序列;
PromQL支持基于定义的指标维度进行过滤和聚合更改任何标签值,包括添加或删除标签,都会创建一个新的时间序列
应该尽可能地保持标签的稳定性,否则,则很可能创建新的时间序列,更甚者会生成一个动态的数据环境,并使得监控的数据源难以跟踪,
从而导致建立在该指标之上的图形、告警及记录规则变得无效。
2、查询基础
2.1、PromQL简介
Prometheus提供一个内置的函数式的表达式语言PromQL(Prometheus Query Language),可以使用户实时地查找和聚合时间序列数据。表达式计算结果可以在图表中展示,
也可以在Prometheus表达式浏览器中以表格形式展示,或者作为数据源, 以HTTP API的方式提供给外部系统使用。
注意:默认情况下,他是以当前时间为基准点,来进行数据的获取操作。
2.2、表达式
2.2.1、表达式样式
1、数据类型 instant vector 瞬时数据,在某一时刻,抓取的所有监控项数据。这些度量指标数据放在同一个key中。 range vector 范围数据,在某一个时间段内,抓取的所有监控项数据。
2、数据格式 scalar 标量,一个简单的浮点类型数值 string 字符串,一个之前没有被使用的简单字符串
2.2.2、基于表达式查询的图表
node_filefd_allocated{instance="192.168.10.30:9100"} PromQL的查询操需要针对有限个时间序列上的样本数据进行,挑选出目标时间序列是构建表达式时最为关键的一步,
然后根据挑选出给定指标名称下的所有时间序列或部分时间序列的即时(当前)样本值或至过去某个时间范围内的样本值。
2.3、数据类型
2.3.1、数值
对于数值来说,我们这里主要记住两种类型的数值:字符串和数字。
2.3.2、字符串
字符串可以用单引号,双引号或反引号指定为文字,如果字符串内的特殊符号想要生效,我们可以使用反引号。 "this is a string" 'these are unescaped: n t' `these are not unescaped: n ' " t`
2.3.3、数字
对于数据值的表示,可以使用我们平常时候的书写方法 "[-](digits)[.(digits)]" 2、2.43、-2.43等
2.4、数据选择器
所谓的数据选择器,其实指的是获取实时数据或者历史数据的一种方法
2.4.1、瞬时选择器
瞬时选择器 :获取及时的一组时间序列和单个样本值,根据数据的精确度,可以有以下几种使用方法: 1、根据监控项名称获取最新值。 node_filefd_allocated
2、通过{key=value,}样式获取符合条件的数据值。 node_filefd_allocated{instance="10.0.0.12:9100", job="node_exporter"}
属性解析: 多个条件间可以使用逗号","隔开,每个条件内部可以通过多种符号,表示不同含义=(精确匹配)、!=(不匹配)、=~(正则匹配)、!~(正则不匹配)
如果条件中存在多值,可以使用"|"表示或的意思,env=~"staging|testing|development",条件中必须包含一个与空标签值不匹配的选择器,不能写成{job=~".*"}
3、通过__name__获取批量监控项的值。 {__name__="prometheus_http_requests_total"}、{__name__=~"^prometheus.*"} 注意: 指标 prometheus_http_requests_total 默认情况下,针对的是 localhost:9090 的target,其他无效
2.4.2、范围选择器
范围选择器 工作方式与瞬时向量选择器一样,区别在于时间范围长一些,他主要是在瞬时选择器多了一个[]格式的时间范围后缀,在[]内部可以采用多个单位表示不同的时间范围,
比如s(秒)、m(分)、h(时)、d(日)、w(周)、y(年)。
prometheus_http_requests_total{job="prometheus"}[5m] 属性解析: 这表示过去5分钟内的监控数据值,这些数据一般以表格方式展示,而不是列表方式展示。 注意: 范围向量选择器返回的是一定时间范围内的数据样本,虽然不同时间序列的数据抓取时间点相同,但它们的时间戳并不会严格对齐; - 多个Target上的数据抓取需要分散在抓取时间点前后一定的时间范围内,以均衡Prometheus Server的负载; - 因而,Prometheus在趋势上准确,但并非绝对精准;
2.4.3、偏移修饰符
范围选择器可以获取最近时间段的数据,而对于某个历史时间段中的数据,我们就需要通过offset时间偏移的方式来进行获取了。 prometheus_http_requests_total offset 5m # 往前偏移5分钟 prometheus_http_requests_total{code="200"} offset 5m # 往前偏移5分钟 prometheus_http_requests_total{handler="/metrics"}[5m] offset 3m # 往前偏移3分钟,再取偏移后的,前的5分钟。
注意: offset 与 数据选择器是一个整体,不能分割 offset 偏移的是时间点
2.5、语法格式
2.5.1、算术运算符
算术运算符:+、-、*、/、%、^
2.5.2、比较运算符
比较运算符:==, !=, <=, <, >=, >
2.5.3、逻辑运算符
and、or、unless
2.5.4、运算符优先级
1、 ^ 2、 *, /, % 3、 +, - 4、 ==, !=, <=, <, >=, > 5、 and, unless 6、or
2.5.5、运算符-示例
1、单位换算 node_memory_MemFree_bytes / (1024 * 1024) 2、内存使用率 (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes * 100 3、磁盘使用率 (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) /node_filesystem_size_bytes{mountpoint="/"} * 100 4、阈值判断 (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes > 0.95 prometheus_http_requests_total > bool 1000 注意: 1、对于比较运算符来说,条件成立有结果输出,否则没有结果输出 2、使用bool修改符后,布尔运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果0或者1。从而形成一条新的时间序列。
2.5.6、集合-示例
并集 node_memory_MemTotal_bytes{instance="192.168.10.29:9100"} or node_memory_MemFree_bytes{instance="192.168.10.30:9100" } 交集 node_memory_MemTotal_bytes{instance="192.168.10.29:9100"} and node_memory_MemFree_bytes{instance="192.168.10.30:9100" } 补集 node_memory_MemTotal_bytes{job="node_exporter"} unless node_memory_MemTotal_bytes{instance="192.168.10.30:9100"} 注意: and、or、unless # 主要是针对获取的数据值进行条件选集合用的。 and、or、unless # 对象是一个完整的表达式。
2.6、聚合操作
2.6.1、常用函数的介绍
聚合操作虽然是一个个的功能,但是他们并不是功能函数,仅仅代表对数据进行简单的功能处理。
常见的方法有: sum、min、max、avg、count、count_values(值计数) stddev(标准差)、stdvar(标准差异)、bottomk(最小取样)、topk(最大取样)、quantile(分布统计) 格式: 聚合函数(metric表达式) sum、min、max、avg、count等 聚合函数(描述信息,metric) count_values、bottomk、topk等
我们可以借助于without和by功能获取数据集中的一部分进行统计,格式如下sum(数据选择表达式) without|by (<label list>)
注意: without 表示显示信息的时候,不包括指定的标签列表 by 表示显示信息的时候,仅显示指定的标签
2.6.2、聚合-示例
1、内存总量 sum(node_memory_MemTotal_bytes)
2、确认CPU的总数量 count(node_cpu_seconds_total{mode='system'})
3、获取最大的值 max(prometheus_http_requests_total)
4、分组统计计数 count_values("counts",node_filesystem_size_bytes)
5、获取前5个最大值 topk(5, prometheus_http_requests_total)
6、求和,除了job sum(prometheus_http_requests_total) without (job)
7、求和,仅仅是mode sum(node_cpu_seconds_total) by (mode)
2.7、功能函数
2.7.1、函数简介
默认情况下,prometheus官方默认的功能函数有40个。
2.7.2、计算相关-函数
绝对值 abs() 导数 deriv() 指数 exp() 对数 ln() 二进制对数 log2() 10进制对数 log10() 平方根 sqrt() 向上取整 ceil() 向下取整 floor() 四舍五入 round() 样本差 idelta() 差值 delta() 递增值 increase() 重置次数 resets() 递增率 irate() 变化率 rate() 平滑值 holt_winters() 直方百分位 histogram_quantile() 预测值 predict_linear() 参数 vector() 范围最小值 min_over_time() 范围最大值 max_over_time() 范围平均值 avg_over_time() 范围求和值 sum_over_time() 范围计数值 count_over_time() 范围分位数 quantile_over_time() 范围标准差 stddev_over_time() 范围标准方差 stdvar_over_time()
2.7.3、取样相关-函数
获取样本 absent() 升序 sort() 降序 sort_desc() 变化数 changes() 判断值 scalar() 判断大 clamp_max() 判断小 clamp_min() 范围采样值 absent_over_time()
2.7.4、时间相关-函数
day_of_month() day_of_week() days_in_month() hour() minute() month() time() timestamp() year()
2.7.5、标签相关
标签合并 label_join()
标签替换 labelreplace()
2.7.6、功能函数-示例
1、ceil():向上取整 ceil(node_load15 * 10) 2、increase(): 多值累加 - (last值-last前一个值) 最近1分钟内CPU处于空闲状态时间 increase(node_cpu_seconds_total{cpu="0",mode="idle"}[1m]) 3、irate():查看瞬时变化率 - (last值-last前一个值)/时间戳差值 查看CPU最近5m内最多的增长率 irate(node_cpu_seconds_total{instance="10.0.0.12:9100",mode="idle"}[5m]) 4、rate():平均变化率 - (last值-first值)/时间差s 过去一分钟磁盘读的变化率 rate(node_disk_read_bytes_total[1m]) 一分钟内网卡传输的字节数(MB) rate(node_network_transmit_bytes_total{device="ens33"}[1m]) /1024 /1024 5、histogram_quantile(): 百分取样值 计算过去10m内请求持续时间的第90个百分位数 histogram_quantile(0.9, rate(prometheus_http_request_duration_seconds_bucket[10m])) 6、time(): 获取当前时间值 计算当前系统的运行时间 sum(time() - node_boot_time_seconds) / 3600
2.8、总结
操作符号 - 常用操作:运算符、聚合运算 功能函数 - 转换、计算、统计、时间、标签