Prometheus UI 是 Prometheus 内置的一个可视化管理界面,通过 Prometheus UI 用户能够轻松的了解 Prometheus 当前的配置,监控任务运行状态等。 通过 Graph 面板,用户还能直接使用 PromQL 实时查询监控数据,也可以使用 PromQL 表达式查询特定监控指标的监控数据。如下所示,查询主机cpu负载变化情况,可以使用关键字 node_lcpu 可以查询出 Prometheus 采集到的主机负载的样本数据,这些样本数据按照时间先后顺序展示,形成了主机负载随时间变化的趋势图表:
PromQL 是 Prometheus 自定义的一套强大的数据查询语言,除了使用监控指标作为查询关键字以为,还内置了大量的函数,帮助用户进一步对时序数据进行处理。例如使用 rate()
函数,可以计算在单位时间内样本数据的变化情况即增长率,因此通过该函数我们可以近似的通过 CPU 使用时间计算 CPU 的利用率:
# node_cpu_seconds_total
node_cpu_seconds_total{cpu="0", instance="10.10.1.11:9100", job="node-exporter", mode="idle"}
这时如果要忽略是哪一个 CPU 的,只需要使用 without 表达式,将标签 CPU 去除后聚合数据即可:
# avg without (cpu) (node_cpu_seconds_total)
{instance="10.10.1.11:9100", job="node-exporter", mode="idle"}
PromQL是Prometheus提供的一个函数式的表达式语言
,可以使用户实时地查找和聚合时间序列数据。表达式计算结果可以在图表中展示,也可以在 Prometheus表达式浏览器中以表格形式展示,或者作为数据源以HTTP API的方式提供给外部系统使用。PromQL虽然以QL结尾,但是它不是类似SQL的语言,因为在时间序列上执行计算类型时,SQL语言相对缺乏表达能力。而PromQL语言表达能力非常丰富,可以使用标签
进行任意聚合,还可以使用标签将不同的标签连接到一起进行算术运算操作。内置了时间和数学等很多函数可以使用。
Prometheus–PromQL
Prometheus官网
PromQL表达式或子表达式可以得到四种类型的值
1、瞬时向量 (Instant vector): 一组样本值,所有样本值共享时间序列(时间戳相同)
2、区间向量 (Range vector): 一组一段时间范围类的样本值
3、标量(Scalar) 一个固定的浮点数,-x.y 、n.m格式
4、字符串 (String): 一个字符类型的值,可以使用单引号、双引号、反引号包裹,遵循goalng语法的转义规则
瞬时向量选择器用来选择一组时序在某个采样点
的采样值。最简单的情况就是指定一个度量指标,选择出所有属于该度量指标的时序的当前采样值。
比如下面的表达式:
probe_success <中间的这些都是筛选变量>
probe_success{job="kube-service-http-probe", url="https://help.baidu.com/question?prod_id=1"}
probe_success{job="kube-service-http-probe", url=~".*help.baidu.com.*"}
apiserver_audit_event_total{job=~"kube-apiserver|kube-controller-manager|kube-scheduler",cluster="k8s-sdjw-pro"}
匹配标签值时可以是等于,也可以使用正则表达式。总共有下面几种匹配操作符:
符号 | 含义 |
---|---|
= | 完全相等 |
!= | 不相等 |
=~ | 正则表达式匹配 |
!~ | 正则表达式不匹配 |
区间向量选择器类似于瞬时向量选择器,不同的是它选择的是过去一段时间的采样值
。可以通过在瞬时向量选择器后面添加包含在 [] 里的时长来得到区间向量选择器。比如下面的表达式选出了所有度量指标为 apiserver_request_total 且resource是pod的时序在过去 1 分钟的采样值。
apiserver_request_total{job="kube-apiserver",resource="pods"}[1m]
时长的单位可以是下面几种之一
符号 | 含义 |
---|---|
s | seconds |
m | minutes |
h | hours |
d | days |
w | weeks |
y | years |
前面介绍的选择器默认都是以当前时间为基准时间,偏移修饰器用来调整基准时间
,使其往前偏移一段时间。偏移修饰器紧跟在选择器后面,使用offset来指定要偏移的量。比如下面的表达式选择度量名称为 apiserver_request_total的所有时序在5分钟前的采样值。
apiserver_request_total{job="kube-apiserver",resource="pods"} offset 5m
下面的表达式选择 apiserver_request_total度量指标在1周前的这个时间点过去5分钟的采样值
apiserver_request_total{job="kube-apiserver",resource="pods"} [5m] offset 1w
算术类二元操作符有以下几种:
+:加
-:减
*:乘
/:除
%:求余
^:乘方
二元运算操作符可以在scalar/scalar(标量/标量)、vector/scalar(向量/标量)、和vector/vector(向量/向量)
之间运算。
1.在两个标量之间运算: 得到的结果也是一个标量。
2.在即时向量和标量之间运算: 将运算符应用于这个向量中的每个数据样本的值。 eg: 如果时间序列即时向量乘以2,则结果是另外一个向量,另外一个向量中的值是原始向量的每个样本值乘以2。
3.在两个即时向量之间运算: 运算符会依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行运算,如果没找到匹配元素,则直接丢弃。同时新的时间序列将不会包含指标名称。
比较类二元操作符有以下几种:
== (equal)
!= (not-equal)
> (greater-than)
< (less-than)
>= (greater-or-equal)
<= (less-or-equal)
比较二元运算符被应用于scalar/scalar(标量/标量)、vector/scalar(向量/标量) ,和 vector/vector(向量/向量)之间。比较运算符得到的结果是 bool 布尔类型值,返回1或者0值。
逻辑操作符仅用于向量与向量之间:
and:交集
or:合集
unless:补集
具体运算规则如下:
运算 | 结果 |
---|---|
vector1 and vector2的结果 | 由在vector2里有匹配(标签键值对组合相同)元素的vector1 里的元素组成 |
vector1 or vector2的结果 | 由所有vector1里的元素加上在vector1 里没有匹配(标签键值对组合相同)元素的vector2里的元素组成 |
vector1 unless vector2 的结果 | 由在vector2里没有匹配(标签键值对组合相同)元素的vector1 里的元素组成 |
PromQL 的各类二元操作符运算优先级如下:
^
*, /, %
+, -
==, !=, <=, <, >=, >
and, unless
or
PromQL的聚合操作符用来将向量里的元素聚合得更少。总共有下面这些聚合操作符:
符号 | 含义 |
---|---|
sum | 求和 |
min | 求最小值 |
max | 求最大值 |
avg | 求平均值 |
group | 结果向量中的所有值均为1 |
stddev | 求标准差 |
stdvar | 求方差 |
count | 计数 |
count_values | 对 value(样本之) 进行计个数统计 |
bottomk | 用于对样本值进行排序,样本值最小的 k 个元素 |
topk | 用于对样本值进行排序,样本值最大的k个元素 |
quantile | 分布统计,用于评估数据的分布统计 quantile(φ, express) ,其中 0 ≤ φ ≤ 1 |
注:这些运算符既可以用于聚合所有标签维度
,也可以通过包含without or by
子句来保留不同的维度;这些子句可以在表达式之前或之后使用。
without将从结果中移除选定的tags,by则相反将移除没有选定的tags。
其中count_values, quantile, topk, bottomk需要指定parameter,其他聚合函数不需要。
举例:
quantile(0.95, http_requests_total) ==> 表示找到当前样本数据中的95%中位数
count_values("count",node_memory_MemTotal_bytes) ==> 对value进行统计计数
Prometheus 内置了一些函数来辅助计算,下面介绍一些典型的:
abs() 绝对值
sqrt() 平方根
exp() 指数计算
ln() 自然对数
ceil() 向上取整
floor() 向下取整
round() 四舍五入取
delta() 计算区间向量里每一个时序第一个和最后一个的差值
absent() 判断指标名称或标签是否有值
sort() 排序
changes() 返回区间变量每个样本值变化的次数
increase() 返回区间向量第一个和最后一个样本的增量值
predict_linear 预测时间序列在n秒后的值
一些函数有默认参数,例如year(v=vector(time()) instant-vector). 这意味着有一个参数v是一个即时向量,如果没有提供,它将默认为表达式的值
rate() 计算区间向量 v 在时间窗口内平均每秒增长速率
rate(v range-vector) 计算范围向量中时间序列的每秒平均增长率。单调性的中断(例如由于目标重新启动而导致的计数器重置)会自动调整。此外,计算推断到时间范围的末端,允许错过刮擦或刮擦周期与该范围的时间段的不完美对齐。
例:返回在过去 5 分钟内测量的每秒 HTTP 请求速率,范围向量中的每个时间序列:
rate(http_requests_total{job="api-server"}[5m])
注:rate()只能与counter类型指标一起使用。它最适合警报和缓慢移动计数器的图形。
当rate()与聚合运算符(例如sum())或随时间聚合的函数(任何以 结尾的函数_over_time)结合时,总是先取一个rate(),然后再聚合。否则rate(),当您的目标重新启动时,无法检测到计数器重置。
irate() 计算区间向量的增长率,但是它反应的是瞬时增长率
irate(v range-vector) 计算范围向量中时间序列的每秒瞬时增长率。这是基于最后两个数据点。单调性的中断(例如由于目标重新启动而导致的计数器重置)会自动调整。
例:返回针对范围向量中每个时间序列的两个最近数据点的 HTTP 请求的每秒速率,最多可追溯 5 分钟:
irate(http_requests_total{job="api-server"}[5m])
注:irate仅应在绘制易失性、快速移动的计数器时使用。用于rate警报和缓慢移动的计数器,因为速率的短暂变化可以重置FOR子句,并且完全由罕见峰值组成的图形难以阅读。
当irate()与 聚合运算符(例如sum())或随时间聚合的函数(任何以结尾的函数_over_time)结合时,总是先取一个irate()然后再聚合否则irate()当目标重新启动时,无法检测到计数器重置。
sort()
sort(v instant-vector) 返回按样本值升序排序的向量元素。
sort_desc()
sort_desc(v instant-vector) 与sort()相同,但按降序排序。
sqrt()
sqrt(v instant-vector) 计算v中所有元素的平方根
time()
time() 返回自 1970 年 1 月 1 日 UTC 以来的秒数。请注意,这实际上并不返回当前时间,而是要计算表达式的时间。
timestamp()
timestamp(v instant-vector) 返回给定向量的每个样本的时间戳,作为自 1970 年 1 月 1 日 UTC 以来的秒数(Prometheus 2.0+)
vector()
vector(s scalar) 将标量s作为没有标签的向量返回
minute()
minute(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间的小时分钟,返回值从 0 到 59。
month()
month(v=vector(time()) instant-vector) 以 UTC 格式返回每个给定时间的一年中的月份,返回值从 1 到 12,其中 1 表示一月。
delta()
delta(v range-vector) 计算范围向量中每个时间序列元素的第一个值和最后一个值之间的差,返回具有给定增量和等效标签的即时向量。增量被外推以覆盖范围向量选择器中指定的整个时间范围,因此即使样本值都是整数,也可以获得非整数结果。
注:delta()函数在可视化界面上只能用于仪表盘 例:返回现在和 2 小时前 CPU 温度的差异:
delta(cpu_temp_celsius{host="zeus"}[2h])
label_join()
label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, …)
对于v中的每个时间序列,将连接所有src_labels using的所有值,separator并返回带有dst_label包含连接值的标签的时间序列。此函数中可以有任意数量src_labels。
例:返回一个向量,其中每个时间序列都有一个foo带有添加值的标签a,b,c:
label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")
label_replace()
label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)
对于v中的每个时间序列,将正则表达式regex与标签的值进行匹配src_label。如果匹配,则dst_label返回的时间序列中的标签值将是 的扩展replacement,以及输入中的原始标签。
正则表达式中的捕获组可以用 , 等引用$1。$2如果正则表达式不匹配,则返回时间序列不变。
例:返回带有a:c标签service和a标签值的时间序列foo:
label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")
Because no one remembers the second place, so I will try to be the first!