数据查询
数据查询
查询时间序列
当 Prometheus 通过 Exporter 采集到相应的监控指标样本数据后,我们就可以通过 PromQL 对监控样本数据进行查询。当我们直接使用监控指标名称查询时,可以查询该指标下的所有时间序列。如:
http_requests_total
http_requests_total{}
http_requests_total{code="200",handler="alerts",instance="localhost:9090",job="prometheus",method="get"}=(20889@1518096812.326)
http_requests_total{code="200",handler="graph",instance="localhost:9090",job="prometheus",method="get"}=(21287@1518096812.326)
匹配模式
PromQL 还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。PromQL 支持使用 = 和 != 两种完全匹配模式:
- 通过使用 label=value 可以选择那些标签满足表达式定义的时间序列;
- 反之使用 label!=value 则可以根据标签匹配排除时间序列;
例如,如果我们只需要查询所有 http_requests_total 时间序列中满足标签 instance 为 localhost:9090 的时间序列,则可以使用如下表达式:
http_requests_total{instance="localhost:9090"}
# 排除掉这些时间序列
http_requests_total{instance!="localhost:9090"}
除了使用完全匹配的方式对时间序列进行过滤以外,PromQL 还可以支持使用正则表达式作为匹配条件,多个表达式之间使用 |
进行分离:使用 label=~regx 表示选择那些标签符合正则表达式定义的时间序列;反之使用 label!~regx 进行排除。例如,如果想查询多个环节下的时间序列序列可以使用如下表达式:
http_requests_total{environment=~"staging|testing|development",method!="GET"}
范围查询
直接通过类似于 PromQL 表达式 http_requests_total 查询时间序列时,返回值中只会包含该时间序列中的最新的一个样本值,这样的返回结果我们称之为瞬时向量;而相应的这样的表达式称之为瞬时向量表达式。范围向量选择器像瞬时向量选择器一样工作,不同的是它们从时间序列中选择一定时间范围内的数据。在语法上,范围持续时间附加在向量选择器末尾的方括号([])中。
时间持续的值以数字表示,其后跟以下时间单位:
- s - 秒
- m - 分钟
- h - 小时
- d - 天
- w - 周
- y - 年
在此示例中,我们选择在过去 1 分钟内为 metric 为 prometheus_http_requests_total 且 job 标签设置为 prometheus 的所有时间序列记录的元素值:
prometheus_http_requests_total{job="prometheus"}[1m]
偏移修改器
偏移修改器允许更改查询中各个瞬时和范围向量的时间偏移。例如,以下表达式返回相对于当前查询时间 5 分钟前 metric 为 http_requests_total 的元素值:
http_requests_total offset 5m
# 偏移修改器始终需要跟随在选择器之后
sum(http_requests_total{method="GET"} offset 5m) // GOOD.
sum(http_requests_total{method="GET"}) offset 5m // INVALID.
# 也适用于范围向量
rate(http_requests_total[5m] offset 1w)
聚合操作
一般来说,如果描述样本特征的标签(label)在并非唯一的情况下,通过 PromQL 查询数据,会返回多条满足这些特征维度的时间序列。而 PromQL 提供的聚合操作可以用来对这些时间序列进行处理,形成一条新的时间序列:
# 查询系统所有http请求的总量
sum(http_request_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)
标量和字符串
除了使用瞬时向量表达式和区间向量表达式以外,PromQL 还直接支持用户使用标量(Scalar)和字符串(String)。
标量
标量只有一个数字,没有时序。例如:
10
需要注意的是,当使用表达式 count(http_requests_total),返回的数据类型,依然是瞬时向量。用户可以通过内置函数 scalar() 将单个瞬时向量转换为标量。
字符串
直接使用字符串,作为 PromQL 表达式,则会直接返回字符串。
"this is a string"
'these are unescaped: \n \\ \t'
`these are not unescaped: \n ' " \t`
子查询
子查询允许您在给定范围和分辨率内运行瞬时查询。子查询的结果是范围向量。
语法:<instant_query> '[' <range> ':' [<resolution>] ']' [ offset <duration> ]
,<resolution>
可缺省。
查询优化
陈旧性
运行查询时,选择采样数据(独立于实际当前时间序列)的时间戳。这主要是为了支持聚合(总和,平均等)这样的情况,其中多个聚合时间序列在时间上不完全对齐。由于它们的独立性,Prometheus 需要在每个相关时间序列的时间戳上分配值。它只需在此时间戳之前采用最新的样本即可。
如果目标抓取或规则评估不再返回先前存在的时间序列的样本,则该时间序列将被标记为陈旧。如果目标被移除,之前很快就会将其先前返回的时间序列标记为陈旧。如果在时间序列标记为过时后在采样时间戳处计算查询,则不会为该时间系列返回任何值。如果随后在该时间序列中摄取新样本,它们将照常返回。
如果在采样时间戳前 5 分钟未找到任何样本(默认情况下),则此时间点不返回该时间序列的值。这实际上意味着时间序列在其最新收集的样本超过 5 分钟或者标记为陈旧之后从图表“消失”。对于在其刮擦中包含时间戳的时间序列,不会标记陈旧性。在这种情况下,仅应用 5 分钟的阈值。
避免慢查询和重载
如果查询需要对大量数据进行操作,则绘制图表可能会超时或使服务器或浏览器过载。因此,在构建对未知数据的查询时,始终在 Prometheus 表达式浏览器的表格视图中开始构建查询,直到结果集看起来合理(最多数百个,而不是数千个时间序列)。只有在您充分过滤或汇总数据后,才能切换到图表模式。如果表达式仍然需要很长时间来绘制图形,请通过记录规则 预先记录它。
这与 Prometheus 的查询语言尤其相关,其中像 api_http_requests_total 这样的简单 metric 选择器可以扩展到具有不同标签的数千个时间序列。还要注意,即使输出只是少量的时间序列,聚合在许多时间序列上的表达式也会在服务器上产生负载。这类似于在关系数据库中对列的所有值求和的速度很慢,即使输出值只是一个数字。