CalcGuide · 技术博客主页 / 一页纸学习计划
🟠

Metrics / Logs / Traces 三支柱与 OpenTelemetry 采集

分类:工程技术 · 路径:docs/topics/metrics-logs-traces/README.md

#observability#opentelemetry#metrics#logs#traces#otlp#prometheus

用 1~2 周从三支柱定义到能用 OpenTelemetry SDK + Collector 串联多语言服务

父主题

可观测性与 SRE:从 SLI/SLO 到事故响应与混沌工程

子主题(0)

Metrics / Logs / Traces 三支柱与 OpenTelemetry 采集

0. 元信息

1. 学习路线

三支柱定义(Metrics / Logs / Traces)
  → 高基数 / 低基数 / wide events
  → OpenTelemetry 数据模型(Resource / Instrumentation / Span / Metric / Log)
  → OTel SDK 自动注入与手动埋点(Python / Go / Node 任选两门)
  → OTel Collector 架构(Receiver / Processor / Exporter)
  → W3C Trace Context 上下文传播
  → 采样策略(head / tail / ratio)
  → 与 Prometheus / Loki / Tempo / Grafana 联动

2. 阶段周数分配(34 周,每天 1.52 小时)

精简子主题按”概念 → 采集 → 上下文 → 后端”四段推进。

阶段主题周数备注
1三支柱定义与数据模型0.5 周Metrics / Logs / Traces + 高/低基数
2OpenTelemetry SDK1 周Resource / Instrumentation / Span
3OTel Collector 架构0.5 周Receiver / Processor / Exporter
4上下文与采样0.5 周W3C Trace Context + 采样策略
5后端对接1 周Prometheus / Loki / Tempo / Grafana
6综合项目(全链路追踪 demo)1 周含 README + 复盘

选 3 周方案时把第 4/5 阶段压成 0.5 周。每周留 0.5 天复盘。

3. 九阶段表

阶段核心知识实践产出可观察学会标准
1三支柱定义一份对比表能解释「多少 / 为什么 / 哪里」
2高基数 vs 低基数一个 Prometheus 指标反例能说清 user_id 作 label 的代价
3OTel 数据模型Resource / Span / Metric / Log 四件套示例能解释 Context Propagation
4OTel SDK 自动注入Python opentelemetry-instrument Flask Demo一键埋点
5OTel SDK 手动埋点写一个 @trace 装饰器 / tracer.start_as_current_span自定义 Span
6OTel Collectorreceivers / processors / exporters 配置串联两语言
7Trace Contexttraceparent跨服务 traceid 串联
8采样策略head + tail sampling控制成本
9三向跳转Grafana 联动 Prometheus / Loki / Tempo用 traceid 反查日志与指标

关键陷阱:把 Metrics 当 Logs;Trace 全采样;不调 Collector batch 撑爆内存;忽略 Context Propagation;高基数 label 撑爆 TSDB。

4. 第一周任务

任务当天交付
Day 1装 Docker / Compose / Python / Go;自检环境清单
Day 2起一个 Prometheus + Grafana + Alertmanager Compose 栈Compose YAML + 看板
Day 3写最小 Flask / FastAPI 服务,暴露 /metrics(prometheus_client)Python 服务 + RED 指标
Day 4client_golang 写 Go 服务指标Go 服务指标
Day 5装 OTel Collector,配置 OTLP receiver;接入 Python / Go SDKCollector 配置 + 双语言 SDK
Day 6接入 Loki;写结构化日志;用 Grafana 查日志Loki 数据源 + 日志查询
Day 7步骤 A:跑通「最小可观测闭环」(指标 + 日志 + Trace + Grafana + Alertmanager);步骤 B:补齐 4 类边界(抓取失败 / Collector 重启 / 日志丢 / traceid 断链)闭环 Compose + 故障记录

5. 阶段通用验收

  1. 不看答案独立重写 OTel Collector 配置;
  2. 用自己的话解释 Metrics / Logs / Traces 各自回答什么问题;
  3. 画一张图:服务 → SDK → Collector → 后端 → Grafana;
  4. 测试正常路径、Collector 重启、抓取失败、日志丢、traceid 断链;
  5. 至少准备 3 组自定义数据;
  6. 记录 P50/P95/P99、错误率、饱和度、SLI 命中率;
  7. 能修改既有服务加 OTel、加告警。

6. 最终验收

7. 综合项目

实现「多语言三支柱 Demo」:Python API + Go Worker + Node 前端,OTel SDK 接入,OTel Collector 串联,输出到 Prometheus / Loki / Tempo,Grafana 看板三向跳转。成果合入父主题首选综合项目。

本主题贡献

三支柱只有通过 OTel SDK + Collector 用同一个 traceid 串起来,才能在 Grafana 中做三向跳转。本子主题负责讲清”Metrics 多少 / Logs 为什么 / Traces 哪里”在 OTel 数据模型(Resource / Span / Metric / Log)下的对应实体,避免把 metrics 当 logs、把 trace 全采样撑爆后端,并把 W3C Trace Context 跨服务传播当成 Span 拼接的物理基础。

3 职责

  1. 用 OTel SDK(Python / Go / Node 任两门)做自动注入 + 手动埋点,把业务 span + attribute 写进自定义代码。
  2. 用 OTel Collector 的 receivers / processors / exporters,把 OTLP 数据分流到 Prometheus / Loki / Tempo。
  3. 用 W3C Trace Context(traceparent / tracestate)做跨服务 traceid 串联,并用 tail sampling 控制成本。

4 交付物

  1. 一份 OTel Collector 配置(otlp receiver + batch / tail_sampling processor + prometheusremotewrite / loki / otlphttp exporters),含 memory_limiter 防 OOM。
  2. 一份 Python + Go 双语言服务(OTel SDK 自动注入 + 手动 span),traceid 在 Grafana 中贯通,附 FlaskInstrumentor / client_golang 接入示例。
  3. 一份 tail sampling 策略(head 1% + tail 100% 错误/慢),含 batch / memory 调优前后对比与 sampler 决策日志。
  4. 一份 Grafana 三向跳转看板(metric → trace via traceID → log via Loki label),含 tracesToLogsV2 + tracesToMetrics 配置。

3 指标

  1. traceid 跨服务贯通率 100%(任意业务请求 traceid 在 metrics / logs / traces 三处命中)。
  2. 采样后存储 Span 数 ≤ 全采样 5%(tail sampling 后样本数 / 全采样样本数)。
  3. Collector batch / memory 调优后 OOM 0 次(重启日志 + memory limiter 指标)。

OpenTelemetry DocumentationPrometheus DocumentationGrafana DocumentationCharity Majors: Observability Engineering。复制前核对 LICENSE。

8. 推荐资料

OpenTelemetry DocumentationPrometheus DocumentationGrafana DocumentationCharity Majors: Observability Engineering。复制前核对 LICENSE。

9. 学习资料汇聚(v0.3 自包含)

9.1 背景与动机

可观测性最早是控制论术语。2010 年代初分布式系统复杂度上升,Twitter、Uber、LinkedIn 把内部监控平台逐步开源。2014 年 Prometheus 借鉴 Borgmon 思路发布。2017 年 OpenTelemetry 把 Metrics / Logs / Traces 三件套合并到同一 SDK 与协议。今天 OTel 已是 CNCF GA 项目,被绝大多数后端框架默认集成。

9.2 概念地图

flowchart LR
  Service[微服务] --> SDK[OTel SDK]
  SDK --> Auto[自动埋点]
  SDK --> Manual[手动埋点]
  SDK --> Exporter[OTLP Exporter]
  Exporter --> Collector[OTel Collector]
  Collector --> Prom[Prometheus]
  Collector --> Loki[(Loki)]
  Collector --> Tempo[(Tempo)]
  Prom --> Grafana
  Loki --> Grafana
  Tempo --> Grafana
  Context[W3C Trace Context] -.traceparent.-> Service

9.3 基础知识讲解

9.3.1 论文 / 规范

资料用法
OpenTelemetry Specification数据模型与协议
W3C Trace Context Level 1traceparent / tracestate
OpenMetricsPrometheus 暴露格式
Prometheus 查询规范PromQL

9.3.2 书

用法
Charity Majors et al., Observability Engineering(O’Reilly, 2022)三支柱与 wide events
Brendan Gregg, Systems Performance(2nd ed., 2020)性能方法

9.3.3 博客 / 文档

资料用法
OpenTelemetry Blog实战
Grafana BlogLoki / Tempo
Charity Majors可观测工程
Honeycomb Blogwide events

9.3.4 人物

人物关注点
Charity MajorsHoneycomb / 可观测
Björn RabensteinPrometheus
Frederic BranczykPrometheus / OpenMetrics
Bryan BorehamGrafana Pyroscope / Faro

9.3.5 方法

9.3.6 重点训练材料

9.4 经典问题与经典案例

#问题最简答案
1三支柱谁先先 Metrics,再 Logs,最后 Traces
2高基数怎么避免label 用低基数(status / method)
3Trace 采样策略head 1% + tail 100%
4traceid 怎么传播W3C Trace Context traceparent
5Collector batch 怎么调看 memory / batch_size / timeout
6Prometheus 高基数代价TSDB 索引膨胀
7结构化日志怎么写JSON + trace_id / span_id
8Grafana 三向跳转traceID 变量
9OTel SDK 怎么选语言Python opentelemetry-distro
10业务 span 怎么写tracer.start_as_current_span + attributes

9.5 学习难点

难点为什么会卡突破路径
高基数 vs 低基数label 选错看 Prometheus 文档 + 反例
Context 传播跨服务断链用 W3C Trace Context + 自动注入
Tail sampling资源消耗用 OTel Collector tail_sampling processor
Collector 调优batch / memory / retry看官方 tuning 文档

9.6 技术标准与接口

9.6.1 Entity

名称版本组织状态
OpenTelemetry1.xCNCFGA
OTel CollectorcontribCNCFGA
Prometheus2.x社区活跃
Grafana10.xGrafana Labs活跃
Loki2.xGrafana Labs活跃
Tempo2.xGrafana Labs活跃

9.6.2 Scope

三支柱覆盖可观测的不同维度;OTel 是跨语言 SDK 与协议;Prometheus / Loki / Tempo 是开源后端。

9.6.3 Structure

OTel SDK 接口:MeterProviderTracerProviderLoggerProvider。OTel Collector 配置:receivers / processors / exporters。Prometheus 数据模型:metric + label。

9.6.4 Ecosystem

监控:Prometheus / Datadog;日志:Loki / ELK;Trace:Tempo / Jaeger;告警:Alertmanager / PagerDuty。

9.6.5 Depth Tiers

层级能力
L0知道三支柱
L1能读懂 OTel 配置
L2能装 Collector + SDK + 后端
L3能调优 + 多语言串联
L4能设计可观测平台

本子主题目标:L3

9.6.6 Source

10. 常见误区

11. 所有知识点分类(统一规则)

  1. 编程语言;2. 数据结构与算法;3. 计算机基础;4. 工程技术;5. Web 与后端;6. 前端与客户端;7. 数据与人工智能;8. 项目与职业能力;9. 安全与可靠性。

本计划归属:工程技术 主 + 安全与可靠性 辅。

代码块 1:OTel Collector 配置

# otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 5s
    send_batch_size: 1024
  tail_sampling:
    decision_wait: 10s
    policies:
      - name: errors
        type: status_code
        status_code: { status_codes: [ERROR] }
      - name: slow
        type: latency
        latency: { threshold_ms: 500 }

exporters:
  prometheusremotewrite:
    endpoint: http://prometheus:9090/api/v1/write
  otlphttp/tempo:
    endpoint: http://tempo:4317
    tls: { insecure: true }
  loki:
    endpoint: http://loki:3100/loki/api/v1/push

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [tail_sampling, batch]
      exporters: [otlphttp/tempo]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [prometheusremotewrite]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [loki]

代码块 2:Python OTel 自动注入

# api.py
from flask import Flask
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

app = Flask(__name__)
FlaskInstrumentor().instrument_app(app)
RequestsInstrumentor().instrument()

@app.get("/")
def hello():
    return "hello"

# 启动: opentelemetry-instrument python api.py
# 或手动: tracer = trace.get_tracer(__name__)
#        with tracer.start_as_current_span("manual"):
#            ...

代码块 3:W3C Trace Context 头

GET /api HTTP/1.1
Host: api.example.com
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
tracestate: congo=t61rcWkgMzE

traceparent 格式:{version}-{trace_id}-{parent_span_id}-{flags}。flags 01 表示采样,00 表示不采样。

代码块 4:三向跳转 Grafana 看板

{
  "title": "SLO Overview",
  "panels": [
    {
      "title": "Error Budget",
      "targets": [{ "expr": "sum(rate(http_requests_total{job=\"api\",status=~\"5..\"}[5m])) / sum(rate(http_requests_total{job=\"api\"}[5m]))" }]
    },
    {
      "title": "Trace from this point",
      "type": "traces",
      "targets": [{ "query": "{ service.name = \"$service\" && status = error }", "queryType": "traceql" }]
    },
    {
      "title": "Logs",
      "type": "logs",
      "targets": [{ "expr": "{job=\"api\"} |= \"$trace_id\"" }]
    }
  ]
}

直接依赖(1)

查看知识图谱