Prometheus Prometheus

Prometheus 数据模型:指标、标签与指标类型

Prometheus 中时间序列究竟是什么,以及目标用来暴露它们的纯文本格式。

9 min 初级

Prometheus 的每个部分 —— 抓取、存储、PromQL、告警 —— 都运行在同一个底层结构之上:一个时间序列,由名称和一组标签标识,由一串带时间戳的值构成。本指南介绍这个结构,以及目标用来暴露它的纯文本格式。

时间序列是名称、一组标签和一串样本

指标名称描述正在度量的东西:http_requests_total、process_open_fds、node_memory_available_bytes。单独来看,指标名称还不是单个时间序列,而是一个家族,由标签把它细分成各个独立的序列。标签是附加到指标上的键值对:method="GET"、status="500"、path="/api/users"。指标名称加上一组特定的标签值的组合,恰好标识一个时间序列。

http_requests_total{method="GET", status="200", path="/api/users"}
http_requests_total{method="GET", status="500", path="/api/users"}
http_requests_total{method="POST", status="200", path="/api/orders"}

这是共享一个指标名称的三个不同的时间序列。Prometheus 也会自动附加它自己的标签,标识序列来自哪个目标和 job,这些是在应用自己选择暴露的任何标签之上添加的。

样本是序列中的一个点:一个 64 位毫秒时间戳(通常是抓取的那一刻)与一个 64 位浮点值配对。序列是随着时间、每次抓取一个而累积的这些样本的持续流。

四种指标类型

Prometheus 的客户端库暴露四种指标,每种在你查询时意味着不同的东西:

  • Counter(计数器):一个只会增加(或在重启时重置为零)的值,比如已处理请求的累计总数。你几乎从不读取计数器的原始值;你对它计算变化速率,PromQL 指南会介绍。
  • Gauge(仪表):一个可以上升或下降的值,比如当前的内存使用量或进行中的请求数。与计数器不同,直接读取它。
  • Histogram(直方图):将观测值(请求耗时、响应大小)采样到可配置的桶中,并在其旁边暴露一个计数和总和,使得之后可以根据已存储的桶数据计算分位数(比如”95 分位延迟”)。
  • Summary(摘要):与直方图类似,但在观测时于客户端计算分位数,而不是从桶计算。查询更便宜,但摘要的分位数无法像直方图桶那样跨实例聚合,这就是为什么对于你要跨集群队列聚合的任何内容,直方图是更常见的选择。

一种原生直方图类型,比较旧的分桶形式更高效地存储全分辨率的直方图数据,已经开发了一段时间;在依赖它之前,请查阅当前的 Prometheus 文档了解它目前的成熟度,因为它具体被官方支持到什么程度,在最近几个版本中一直在变化。

暴露格式

为了让 Prometheus 抓取目标,目标会通过 HTTP 以纯文本形式提供它当前的值,采用一种特定的、刻意简单的布局:

# HELP http_requests_total Total number of HTTP requests handled.
# TYPE http_requests_total counter
http_requests_total{method="GET", status="200"} 8420
http_requests_total{method="GET", status="500"} 12

# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 27

# HELP 和 # TYPE 行是提供文档和指标类型的注释;其他每个非注释行是一个序列的当前值,由指标名称、花括号中的标签以及值本身构成。因为这永远只是一个快照,每个序列一行,显示它此刻的值,所以抓取响应中没有历史;历史只有在 Prometheus 对同一个序列反复抓取并存储了每次结果之后才存在。

这种格式的简单性是刻意的:它被设计为即使没有客户端库也很容易生成,这正是让几乎任何东西都有现实可能输出 Prometheus 指标的原因,而不仅仅是有官方库支持的软件。

亲自看看

因为抓取只是一个 HTTP GET,所以你可以直接在浏览器中或用 curl 查看任何目标的当前指标,不需要 Prometheus 服务器:

curl http://localhost:9100/metrics   # a node_exporter instance, for example

这个输出正是 Prometheus 自己在每次抓取时收到的内容,这使它成为一个真正有用的首个排障步骤:如果某个目标在 Prometheus 中没有正确显示,直接检查它的原始 /metrics 输出,就能告诉你问题出在目标,还是 Prometheus 自己抓取配置中的某处。

标签来自哪里,以及它们之后为什么重要

目标自己的标签(哪个端点、哪个方法、哪个状态码)来自应用或 exporter 如何自行插桩。Prometheus 在其上添加它自己的标签,标识序列所抓取自的 job 和具体实例。这些标签合在一起,是 PromQL 的聚合和过滤所操作的对象,让你可以针对同一份底层数据询问”所有实例的错误率”或”仅这一个路径的请求速率”,这正是本系列下一篇指南所要介绍的内容。

热门指南