「Prometheus」- 数据查询:PromQL(=> PROMETHEUS/Querying)

简单示例(Examples)

Querying examples | Prometheus

基本查询

http_requests_total
http_requests_total{job="apiserver", handler="/api/comments"}

# 五分钟内的结果
# 注意:这些数据无法直接图形化显示,但是能够在表达式浏览器中进行查看;
http_requests_total{job="apiserver", handler="/api/comments"}[5m]


# 通过 RE2 表达式匹配
http_requests_total{job=~".*server"}
http_requests_total{status!~"4.."}

嵌套查询

即子查询,对指标使用函数进行进一步处理:

rate(http_requests_total[5m])[30m:1m]

函数、运算符……

类似如下形式:

# 计算 HTTP Request 总数:
sum by (job) (
  rate(http_requests_total[5m])
)

# 计算 CPU 使用最多的前三个进程
topk(3, sum by (app, proc) (rate(instance_cpu_time_ns[5m])))

概念术语(Basics)

Querying basics | Prometheus

PromQL 用于数据查询,允许用户选择和过滤数据。通过查询得到的数据,既能进行图形化显示,也能通过 HTTP API 返回给外部系统。

表达式语言数据类型

在 PromQL 中,表达式可计算为四种类型之一:
1)Instant vector:一组时间序列,每个时间序列包含一个样本,都共享相同的时间戳
2)Range vector:一组时间序列,其中包含每个时间序列随时间变化的一系列数据点
3)Scalar:浮点型数值;
4)String:字符串,当前未使用;

根据用例(例如,当图形与显示表达式的输出时),这些类型中只有一些是合法的(作为用户指定表达式的结果)。例如,返回即时向量的表达式是唯一可以直接绘制图形的类型。

字面量

字符串类型,通过单引号、双引号、反引号引用,并能使用特殊字符。
浮点数类型,即我们常见的浮点数类型表达格式;

Time-Series Selectors

Instant vector selectors:

http_requests_total # 通过名称直接匹配;
http_requests_total{job="prometheus",group="canary"} # 通过名字及标签进行匹配;

// ---------------------------------------------------------------------------- // 支持 =、!=、=~、!~ 进行匹配

http_requests_total{environment=~"staging|testing|development",method!="GET"} 

env=~"foo" 与 env=~"^foo$" 等价;

{job=~".*"}              # Bad!,原因是这将匹配不包含 Job 的指标;
{job=~".+"}              # Good!
{job=~".*",method="get"} # Good!

// ---------------------------------------------------------------------------- // 也能通过指标名称进行匹配

{__name__=~"job:.*"}
on{}                     # Bad!,原因是 on 是关键字(bool, on, ignoring, group_left, group_right)
{__name__="on"}          # Good!

Range Vector Selectors:

# 选择五分钟内的 http_requests_total{job="prometheus"} 指标;
http_requests_total{job="prometheus"}[5m]

Time Durations:

ms - milliseconds
s - seconds
m - minutes
h - hours
d - days - assuming a day has always 24h
w - weeks - assuming a week has always 7d
y - years - assuming a year has always 365d

# 时间范围可以结合使用

# 时间范围的示例:
5h
1h30m
5m
10s

Offset modifier:

http_requests_total offset 5m # 过去五分钟的 http_requests_total 指标,注意不是过去五分钟内;

# offset 要紧跟 selector
sum(http_requests_total{method="GET"} offset 5m) // GOOD.
sum(http_requests_total{method="GET"}) offset 5m // INVALID.

# 在 Range Vectors 中,也能够使用
rate(http_requests_total[5m] offset 1w)  # 一周前,五分钟内的 http_requests_total 指标;
rate(http_requests_total[5m] offset -1w) # 时间向后

@ modifier

# 返回特定时间点的指标
http_requests_total @ 1609746000
sum(http_requests_total{method="GET"} @ 1609746000) // GOOD. 必须紧跟 Selector

rate(http_requests_total[5m] @ 1609746000) # 在这个时间点,五分钟内的频率(向前的五分钟?)

# 基于 @ 所述时间的偏移量。如下两种写法等价:
http_requests_total @ 1609746000 offset 5m
http_requests_total offset 5m @ 1609746000

# 能够使用 start() 或 end() 作为时间值,将被分别解析为执行时的时间开始和结束
http_requests_total @ start()
rate(http_requests_total[5m] @ end())

Subquery

是针对给定的 Range 和 Resolution 的即时查询,其结果是 Range Vector

<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]

<resolution> 是可选的,默认为执行时间间隔(evaluation interval)

Comments

# This is a comment

运算符号(Operators)

Operators | Prometheus

1)二元运算符
2)向量匹配;
3)聚合操作;

针对运算符的使用方法,这里仅简单记录。在后续使用过程中,我们再进一步查阅相关文档;

函数运算(Functions)

Query functions | Prometheus

函数用于对指标进行操作

针对函数的使用方法,这里仅简单记录。在后续使用过程中,我们再进一步查阅相关文档;

调试接口(HTTP API)

HTTP API | Prometheus

通过 HTTP API 接口,允许我们查看 Prom 的相关内容。

针对 HTTP API 的使用方法,这里简单记录,在后面的使用过程中,我们再深入查看。

问题陷阱

过期问题

当运行查询时,独立于 实际当前时间序列数据 来选择 采样数据的时间戳。这主要是为了支持聚合(sum、avg 等)等情况,其中多个聚合时间序列在时间上不完全对齐。由于它们的独立性,Prometheus 需要为每个相关的时间序列在这些时间戳上分配一个值。实现方式是,简单地获取此时间戳之前的最新样本

针对已存在指标,如果 Scrape 和 Rule 不再返回指标,将别标记为 Stale 状态。如果 Target 被删除,相关指标也被标记为 Stale 状态。
如果继续喂入指标,则将从 Stale 变为 Normal 状态。

针对 Stale 状态,查询将不会返回这些数据。

如果采样时间戳前五分钟没有样本,那么时间段内不会有数据。Graph 也不会显示相关数据。这实际上意味着时间序列在其最新收集的样本超过 5 分钟或被标记为过时之后从图表中“消失”。

对于在其抓取中包含时间戳的时间序列,不会标记过时。在这种情况下,只会应用 5 分钟的阈值。

避免慢查询和重载

先对查询进行测试,当结果合理(最多几百个)后,然后再进行图形化的构建。否则,建议先通过 Record Rule 生成数据,而不是每次都进行查询。

聚合很多数据也是非常消耗时间的,应该预先处理,这中情况类似于关系数据库。

常见问题处理

查询包含某个标签的指标(How to display all metrics that don’t have a specific label):

{__name__=~".+",container=""}

查询全部指标(How to get all metric names from Prometheus server filtered by a particular label):

curl -XGET -G 'http://localhost:9090/api/v1/label/__name__/values' \
    --data-urlencode 'match[]={__name__=~".+", job!="prometheus"}'