# 指标采集与观测

> 基于 Prometheus、OpenTelemetry Collector、Grafana 三份真实源码，把「系统到底在干什么」这件事从头讲透——数据模型、时序存储内核、查询引擎、统一管道、链路追踪、可视化与工程实践。

- 作者：David（道雾轩）
- 最后更新：2026-08-03
- 原文：https://daiw.org/manual/observability
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 指标采集与观测

系统出问题时，最怕的不是报错，而是**一片漆黑，不知道发生了什么**。可观测性（Observability）就是给系统装上仪表盘和黑匣子——让运行中的系统能够**自证**“我现在在干什么、刚才发生了什么”。

这个专栏不停留在“怎么用 Prometheus 配个告警”，而是**打开三个主流项目的真实源码**，看这套体系到底怎么造出来的。

## 三个主角，一条链条

本专栏基于三份真实源码，它们恰好构成可观测性的**完整链条**：

| 项目 | 版本 | 在链条里的位置 |
| --- | --- | --- |
| **Prometheus** | v3.13.1 | 采集 + 存储 + 查询（指标支柱的事实标准） |
| **OpenTelemetry Collector** | v0.156.0 | 统一管道（三大支柱的通用中转站） |
| **Grafana** | v13.1.0 | 观测端（可视化、探索、告警） |

数据从被埋点产生，经采集、管道、存储、查询，最后变成你屏幕上那条曲线——**这条路上的每一站，我们都会打开源码看个究竟**。

## 这个专栏怎么写

<Callout type="info">
  **源码优先**——凡有结论，尽量给出**真实的文件路径 + 类型名 + 关键函数**，而不是泛泛而谈“原理大概是这样”。

  - **讲真实的实现** —— 比如 TSDB 的磁盘格式，我们直接读 `tsdb/docs/format/` 里的官方规范和 `tsdb/` 的实现，而不是复述二手博客。
  - **讲设计的取舍** —— 每个设计背后都有权衡（为什么 Prometheus 选 pull 而非 push？为什么 Collector 的管道是个 DAG？），取舍比结论更值得学。
  - **一章一专题** —— 每篇聚焦一个问题，读完能答上“这块为什么存在、怎么和别的块协作”。
</Callout>

## 路线图

全 **10 个部分、53 章**：

| 部分 | 主题 | 核心问题 |
| --- | --- | --- |
| **[0](https://daiw.org/manual/observability/why-observability)** | 导论与全景 | 可观测性是什么、三大支柱、一条指标的一生 |
| **[1](https://daiw.org/manual/observability/prometheus-architecture)** | Prometheus：数据模型与采集 | 指标长什么样、怎么被抓回来 |
| **[2](https://daiw.org/manual/observability/metrics-methodology)** | 指标体系：RED、USE 与黄金信号 | **该定义哪些指标**、怎么命名、合理范围是多少 |
| **[3](https://daiw.org/manual/observability/tsdb-overview)** | TSDB：时序存储内核 | 海量时序数据怎么存得下、查得快 |
| **[4](https://daiw.org/manual/observability/promql-model)** | PromQL：查询引擎与实战 | 怎么从数据里问出答案 |
| **[5](https://daiw.org/manual/observability/alerting-rules)** | 告警工程 | **什么时候该叫醒你**、阈值怎么定、怎么不被淹没 |
| **[6](https://daiw.org/manual/observability/otel-overview)** | OpenTelemetry Collector：统一管道 | 三大支柱怎么被同一条管道运送 |
| **[7](https://daiw.org/manual/observability/traces-basics)** | 链路追踪与日志支柱 | 一个请求怎么被串起来 |
| **[8](https://daiw.org/manual/observability/grafana-datasource)** | Grafana：观测端 | 数据怎么变成能看懂的东西 |
| **[9](https://daiw.org/manual/observability/cardinality)** | 工程实践与收尾 | 基数爆炸、成本、落地路径、全专栏回顾 |

<Callout type="info">
  **本专栏两条腿走路**：一条是**源码**（打开三个项目看实现），另一条是**实战**——[第 2 部分](https://daiw.org/manual/observability/metrics-methodology)讲**怎么定义指标**（RED / USE / 黄金信号方法论、命名规范、**[常见指标的合理范围](https://daiw.org/manual/observability/metric-ranges)**），[第 5 部分](https://daiw.org/manual/observability/alerting-rules)讲**怎么告警**（[阈值怎么定](https://daiw.org/manual/observability/alert-thresholds)、[SLO 燃烧率](https://daiw.org/manual/observability/slo-burn-rate)、[如何不被告警淹没](https://daiw.org/manual/observability/alerting-philosophy)）。**懂原理是为了做对决策**，这两部分就是决策本身。
</Callout>

## 适合谁读

写过服务、配过监控、但想知道**盒子里到底怎么回事**的人。你不需要精通 Go——源码片段都会配上人话解释；但如果你能读 Go，收获会更大。

准备好了就开始。👉 [为什么需要可观测性](https://daiw.org/manual/observability/why-observability)。

## 本专栏篇目

- [指标采集与观测](https://daiw.org/manual/observability.md): 基于 Prometheus、OpenTelemetry Collector、Grafana 三份真实源码，把「系统到底在干什么」这件事从头讲透——数据模型、时序存储内核、查询引擎、统一管道、链路追踪、可视化与工程实践。

### 第 0 部分 · 导论与全景

- [为什么需要可观测性 · 从「监控」到「自证」](https://daiw.org/manual/observability/why-observability.md): 可观测性和监控不是同义词。这一章讲清两者的分野——监控回答「你预先想到要问的问题」，可观测性回答「你没想到的问题」，以及为什么分布式系统把后者从奢侈品变成了必需品。
- [三大支柱 · Metrics、Logs、Traces](https://daiw.org/manual/observability/three-pillars.md): 可观测性的三大支柱各自回答不同的问题、各有不同的代价曲线。这一章讲清指标、日志、追踪的本质分工——为什么是这三样、它们的成本模型有何根本不同，以及「三支柱」说法本身的争议。
- [一条指标的一生 · 从埋点到那条曲线](https://daiw.org/manual/observability/data-journey.md): 用一个具体的指标走完全程——从代码里的一行埋点，经暴露、服务发现、抓取、存储、查询，到 Grafana 上那条曲线，以及告警怎么被触发。这张全景图就是整个专栏的路线索引。
- [三个主角与分工 · Prometheus、OTel Collector、Grafana](https://daiw.org/manual/observability/the-three-projects.md): 本专栏基于三份真实源码。这一章介绍它们各自是什么、在链条里占哪一段、为什么恰好是这三个——以及一个关键区分：OpenTelemetry 是标准，Collector 只是它的一个实现。
- [怎么读这三份源码 · 不迷路的方法](https://daiw.org/manual/observability/reading-the-source.md): 三份源码加起来一万七千多个文件，通读是不可能的。这一章给一套可操作的读法：先读仓库自带的文档（它们都带 AGENTS.md 和架构文档）、从 cmd/ 找入口、盯住 Go 的接口、拿测试当用法手册，以及顺着数据流而不是目录树读。

### 第 1 部分 · Prometheus:数据模型与采集

- [第 1 部分导论 · Prometheus 架构总览](https://daiw.org/manual/observability/prometheus-architecture.md): 打开 Prometheus 的整体骨架——它由哪几块组成、各块怎么接线、以及贯穿其设计的两个根本选择：pull 模型和「单机自足」。这一章给出后续所有章节的坐标系。
- [数据模型 · 指标名 + 标签 = 一条时间序列](https://daiw.org/manual/observability/data-model.md): Prometheus 的数据模型简单到只有一句话，却撑起了整个生态。这一章讲清 series 的定义、标签为什么是维度的载体，以及一个惊人的源码细节——Prometheus 为省内存写了三套 Labels 实现，由构建标签选择。
- [四种指标类型 · 以及怎么选](https://daiw.org/manual/observability/metric-types.md): counter、gauge、histogram、summary —— 四种类型对应四种度量语义。这一章讲清各自适用什么、命名约定，并重点拆解那个最经典的实战决策：histogram 还是 summary（答案几乎总是 histogram，原因是可聚合性）。
- [暴露格式 · /metrics 与 OpenMetrics](https://daiw.org/manual/observability/exposition-format.md): 指标怎么从进程里吐出来？一个纯文本的 HTTP 端点。这一章讲清这个「简单到近乎粗糙」的格式为什么赢了、OpenMetrics 标准化了什么，以及 Prometheus 源码里其实有三套解析器。
- [服务发现 · 去抓谁](https://daiw.org/manual/observability/service-discovery.md): 容器来来去去，不可能手工维护目标列表。这一章读 discovery/ ——一个只有一个方法的接口撑起了 30 种服务发现实现，以及「推送全量而非增量」这个反直觉却极聪明的契约设计。
- [relabeling · Prometheus 出了名的强大与烧脑](https://daiw.org/manual/observability/relabeling.md): relabeling 是「发现的目标」和「实际抓的目标」之间那台可编程的机器。这一章读 model/relabel 的 11 种 action、讲清那个统一的四步流水线心智模型，以及两个 relabel 阶段的关键区别——它同时也是控制基数最有力的工具。
- [抓取循环 · 心跳所在](https://daiw.org/manual/observability/scrape-loop.md): scrapeLoop 是 Prometheus 的心脏。这一章读 scrape/ 源码：用哈希把目标打散避免惊群、自动附加的 8 个元指标（排查采集问题的第一现场）、sample_limit 的自保、以及那个精妙的 staleness 标记。

### 第 2 部分 · 指标体系:RED、USE 与黄金信号

- [第 2 部分导论 · 别拍脑袋定指标](https://daiw.org/manual/observability/metrics-methodology.md): 大多数团队的监控是「想到什么加什么」，结果是几百个没人看的面板和答不上关键问题的仪表盘。这一章讲清为什么需要方法论，并给出三大方法论（RED/USE/黄金信号）的分工与选择依据。
- [RED 方法 · 服务只需要三个指标](https://daiw.org/manual/observability/red-method.md): Rate、Errors、Duration —— 三个指标就能覆盖一个服务的健康。这一章讲清 RED 为什么完备、每个信号的埋点与 PromQL 写法（可直接抄）、以及三个高频陷阱：错误率的分母、延迟必须用分位数、以及为什么不要看平均值。
- [USE 方法 · 资源的三个信号，精髓在饱和度](https://daiw.org/manual/observability/use-method.md): Utilization、Saturation、Errors —— Brendan Gregg 的资源监控方法论。这一章讲清三者的区别、为什么「饱和度」才是精髓（使用率 100% 不一定有问题，饱和度 > 0 一定有），并给出 CPU/内存/磁盘/连接池的具体 PromQL。
- [四大黄金信号 · 以及三套方法论的关系](https://daiw.org/manual/observability/four-golden-signals.md): Google SRE 的 Latency、Traffic、Errors、Saturation。这一章讲清它和 RED/USE 的关系（它其实是 RED + 饱和度）、它独有的两个洞见——「成功请求和失败请求的延迟要分开看」以及「饱和度要看趋势和预测」。
- [怎么定义指标 · 命名、标签与基数红线](https://daiw.org/manual/observability/defining-metrics.md): 知道该测什么之后，怎么把它定义好？这一章给可执行的规则：命名规范（单位后缀是硬要求）、标签设计的取舍，以及那条必须守住的基数红线——含一个能让你立刻算出「这个指标要花多少钱」的公式。
- [常见指标的合理范围 · 多少算正常](https://daiw.org/manual/observability/metric-ranges.md): 「P99 多少算正常？」「CPU 到多少该慌？」这一章给出一批可作起点的参考锚点——延迟的数量级直觉、可用性几个九的真实含义、各类资源的经验区间、直方图桶推荐，以及最重要的：怎么用 SLO 和历史基线定出你自己的数字。

### 第 3 部分 · TSDB:时序存储内核

- [第 3 部分导论 · TSDB 总览](https://daiw.org/manual/observability/tsdb-overview.md): Prometheus 里硬核程度数一数二的部分。这一章讲清 TSDB 要解决的两个难题（存得下、查得快）、它的 Head + Block 两段式结构，以及为什么「时序数据的特殊性」允许它做常规数据库做不到的极端优化。
- [Head 与 WAL · 内存里的数据怎么不丢](https://daiw.org/manual/observability/head-and-wal.md): 新数据先进内存的 Head，靠 WAL 防丢。这一章读 head.go 和 WAL 格式规范：为什么 WAL 的页式编码借鉴了 LevelDB、m-map 怎么让「在内存里」变成一件不那么贵的事，以及 Head 切块与截断的时机。
- [chunk 编码 · Gorilla 压缩的位级魔法](https://daiw.org/manual/observability/chunk-encoding.md): 16 字节怎么压成 1~2 字节？这一章读 chunkenc/xor.go 的真实位级实现——delta-of-delta 编码时间戳（等间距时只花 1 个 bit！）、XOR 编码浮点值，以及这套算法为什么如此贴合时序数据的性格。
- [索引格式 · 倒排索引与符号表](https://daiw.org/manual/observability/index-format.md): 几百万条 series 里怎么瞬间挑出匹配的？这一章读官方的 index 磁盘格式规范：符号表怎么靠去重把索引压小、postings（倒排表）为什么要单调递增，以及多个标签匹配器如何靠交集求解。
- [块与压实 · 为什么要合并，合并到多大](https://daiw.org/manual/observability/blocks-compaction.md): block 每 2 小时生一个，一天 12 个，一个月 360 个——查询要打开几百个目录？这一章讲 LeveledCompactor 的指数分层压实、压实带来的三重收益，以及 tombstone 怎么在不可变的世界里实现删除。
- [查询路径 · 数据怎么被读出来](https://daiw.org/manual/observability/query-path.md): 一次查询要同时读内存的 Head 和磁盘的多个 block，还要把结果合并成一条连续的 series。这一章读 storage.Querier 接口和 SeriesSet 的惰性迭代模型，并讲清 native histograms 与远程写这两个扩展，收尾第 3 部分。

### 第 4 部分 · PromQL:查询引擎与实战

- [第 4 部分导论 · PromQL 的数据模型](https://daiw.org/manual/observability/promql-model.md): PromQL 不是 SQL，它的心智模型是「向量」。这一章讲清即时向量与区间向量的区别——这个区分是理解整门语言的钥匙，也是 90% 报错的来源——以及 lookback 这个隐形但关键的机制。
- [解析与执行 · PromQL 引擎怎么跑](https://daiw.org/manual/observability/promql-engine.md): 从一行文本到一组结果，中间发生了什么？这一章读 promql/parser 的 yacc 语法与 AST、engine.go 的求值模型，以及那个保护你不被自己的查询打死的 MaxSamples 闸门。
- [rate 的真相 · 它其实在外推](https://daiw.org/manual/observability/promql-rate.md): rate（） 是最常用的 PromQL 函数，也是最被误解的。这一章读 functions.go 里 extrapolatedRate 的真实实现——它会外推到窗口边界、会猜测 counter 的零点、于是 increase（） 能给出 1.5 个这种非整数结果。以及那些真正该记住的实战规则。
- [聚合与向量匹配 · by/without 与那些一对多](https://daiw.org/manual/observability/promql-aggregation.md): sum by （job） 里的 by 到底在干什么？两个指标相除时标签怎么配对？这一章讲清聚合的「丢标签」本质、向量匹配的一对一/多对一规则，以及 on/ignoring/group_left 这几个最让人头疼的关键字。
- [直方图查询 · histogram_quantile 的真相](https://daiw.org/manual/observability/promql-histograms.md): P99 是算出来的还是猜出来的？这一章读 quantile.go 的真实实现与注释——桶内线性插值的假设、落在最高桶时返回第二高桶上界的怪规则、以及那些返回 NaN 的特殊情况。附一套可直接抄的正确写法。
- [查询性能与陷阱 · 别写垮 Prometheus](https://daiw.org/manual/observability/promql-performance.md): 一个查询的成本由什么决定？这一章给出成本模型（选中的 series 数 × 每条的点数 × 求值次数）、几个高成本反模式（子查询、正则、大窗口），以及一套排查慢查询的实战工具与方法。

### 第 5 部分 · 告警工程

- [第 5 部分导论 · 告警规则怎么工作](https://daiw.org/manual/observability/alerting-rules.md): 告警不是「查询结果为真就发通知」那么简单。这一章读 rules/alerting.go:Inactive→Pending→Firing 三态机、for 子句（holdDuration）为什么是防抖的关键、keep_firing_for 解决什么，以及那个你能直接查询的 ALERTS 指标。
- [recording rules · 预聚合与命名规范](https://daiw.org/manual/observability/recording-rules.md): 把昂贵的查询预先算好存成新 series。这一章讲 recording rules 的价值（查询提速几个数量级 + 降基数）、那个被低估的官方命名规范 level：metric：operations，以及什么该做成规则、什么不该。
- [阈值怎么定 · 从拍脑袋到有依据](https://daiw.org/manual/observability/alert-thresholds.md): 「CPU > 80% 告警」这种阈值从哪来？通常是拍的。这一章给出定阈值的四种正当方法（SLO 倒推、历史基线、容量推算、趋势预测）、静态阈值的三个失效场景，以及一套可执行的决策流程。
- [SLO 与燃烧率告警 · 从根上解决阈值问题](https://daiw.org/manual/observability/slo-burn-rate.md): 错误预算把「可靠性」变成一种可以花的预算。这一章讲清 SLI/SLO/错误预算三件套、燃烧率（burn rate）的定义与那张经典的多窗口告警表，以及为什么它同时解决了误报、漏报和低流量三个难题——附可直接抄的规则。
- [Alertmanager · 从告警到通知](https://daiw.org/manual/observability/alertmanager.md): Prometheus 只管产生告警，把它变成「一条恰当的通知」是 Alertmanager 的活。这一章讲清它的四个核心机制——分组、抑制、静默、去重，以及为什么「分组」是防止通知风暴的关键。
- [告警哲学 · 少即是多](https://daiw.org/manual/observability/alerting-philosophy.md): 告警系统真正的失败模式不是「漏报」，而是「太吵以至于没人看」。这一章讲告警疲劳的机制、每条告警都该通过的检验、如何用 ALERTS 指标做告警质量审计，以及一个反直觉的结论：删掉告警通常比加告警更能提升可靠性。

### 第 6 部分 · OpenTelemetry Collector:统一管道

- [第 6 部分导论 · OpenTelemetry 与 Collector](https://daiw.org/manual/observability/otel-overview.md): OTel 最大的价值不是任何一个软件，而是「标准」——它让埋点和后端解耦。这一章讲清 OTel 的三层（标准/SDK/Collector）、Collector 存在的 N×M 理由，以及它和 Prometheus 是什么关系（不是竞品）。
- [Collector 架构 · 管道其实是一张图](https://daiw.org/manual/observability/collector-architecture.md): receiver → processor → exporter 是教科书说法，但源码里管道是一张 DAG，靠拓扑排序构建。这一章读 service/internal/graph，讲清五类组件、图的构建流程，以及那个体现工程功力的细节——反拓扑序启动、拓扑序停止。
- [pdata · 数据在管道里长什么样](https://daiw.org/manual/observability/pdata.md): 所有进入 Collector 的数据都被转成 pdata。这一章读 pdata/README 的设计自述——为什么底层直接是 OTLP protobuf 结构、为什么 API 刻意避免可变共享，以及 delta vs cumulative 这个会咬人的语义差异。
- [consumer 与背压 · MutatesData 的精妙](https://daiw.org/manual/observability/consumer-backpressure.md): 组件间怎么传数据？一个只有两个方法的接口。这一章读 consumer 与 fanoutconsumer 源码，看那个 MutatesData 契约怎么让「扇出时只给要改数据的人复制」，以及背压——Collector 最难也最重要的工程问题。
- [配置与部署形态 · confmap 与 agent/gateway](https://daiw.org/manual/observability/collector-config.md): Collector 的配置能从文件、环境变量、HTTP、甚至内联 YAML 来——这一章读 confmap 的 provider 机制，以及那个真正影响架构的决策：Collector 该部署成 agent（每节点一个）还是 gateway（集中一层），还是两者都要。
- [自定义组件 · 怎么扩展 Collector](https://daiw.org/manual/observability/custom-components.md): 几百个社区组件都是同一个模子刻出来的。这一章讲 Factory + Component 生命周期这套扩展契约、写一个 processor 要注意什么（尤其是 MutatesData 这个坑），以及用 OCB 组装自己的发行版。

### 第 7 部分 · 追踪与日志支柱

- [第 7 部分导论 · 追踪的本质](https://daiw.org/manual/observability/traces-basics.md): 一个请求穿过十几个服务，怎么把它串成一条完整的路径？这一章讲清 trace/span 的数据模型、SpanKind 为什么重要、以及那个让整件事得以成立的机制——上下文传播。
- [采样 · 头部还是尾部](https://daiw.org/manual/observability/sampling.md): 追踪的成本随流量线性增长，所以必须采样。这一章讲清头部采样与尾部采样的根本取舍——前者便宜但会漏掉出问题的那条，后者能「只留有意思的」但代价高昂，以及为什么尾采样必须在 gateway 且必然有状态。
- [exemplar · 三支柱之间那座桥](https://daiw.org/manual/observability/exemplars.md): 从一条指标曲线，一键跳到那一刻的某条真实 trace——exemplar 是可观测性里最巧妙的设计之一。这一章讲它怎么工作、为什么它「用聚合的便宜换到了个案的入口」，以及三支柱关联的完整图景。
- [日志支柱 · 最老也最被低估的那根](https://daiw.org/manual/observability/logs-pillar.md): 日志是最古老、最好上手、也最容易失控的支柱。这一章讲结构化日志为什么是分水岭、Loki「只索引标签」的思路为什么和 Prometheus 同源、日志分级的实用判据，以及日志与其他两根支柱的关系。

### 第 8 部分 · Grafana:观测端

- [第 8 部分导论 · Grafana 与数据源抽象](https://daiw.org/manual/observability/grafana-datasource.md): Grafana 自己不存任何数据，它凭什么能一统可视化？答案是数据源抽象。这一章读 pkg/plugins 的插件接口，讲清 QueryData 这个统一契约、后端插件为什么是独立进程，以及 Grafana 在链条里的真正位置。
- [看板与查询 · 怎么做一个有用的看板](https://daiw.org/manual/observability/grafana-dashboards.md): 大多数看板是装饰品。这一章讲让看板真正有用的几件事：变量与模板（一个看板服务所有服务）、看板即代码、以及那个决定成败的原则——看板的结构应该长得像排障的思路。
- [Explore 与关联 · 桥在 UI 上落地](https://daiw.org/manual/observability/grafana-explore.md): 前面讲的所有「桥」——exemplar、trace_id 关联——最终要在界面上变成一次点击。这一章讲 Explore 为什么和看板互补、数据源关联怎么配，以及那个把整个专栏串起来的画面：一次真实排障的完整点击路径。

### 第 9 部分 · 工程实践与收尾

- [第 9 部分导论 · 基数爆炸，头号杀手](https://daiw.org/manual/observability/cardinality.md): 可观测性事故里，最常见的不是「没数据」，而是「数据太多把自己压垮了」。这一章把前面散落各处的基数线索收拢成一套完整的战术：怎么发现、怎么定位、怎么急救、怎么根治。
- [成本与取舍 · 算清这笔账](https://daiw.org/manual/observability/cost-control.md): 可观测性的账单常常失控，因为没人算过它。这一章给一套可执行的成本模型（指标/日志/追踪各自怎么算）、四个降本杠杆的性价比排序，以及那个必须有人回答的问题——这份数据值它的价钱吗？
- [落地与收尾 · 从零到一，以及全专栏回顾](https://daiw.org/manual/observability/observability-recap.md): 五十三章的技术，落地时该按什么顺序？这一章给一条从零开始的路径、一份可执行的检查清单，并回顾整个专栏的主线与几条贯穿始终的原则——为这个专栏画上句号。
