Skip to content

OpenTelemetry 学习计划(Python)

一、学习目标

掌握 OpenTelemetry 的核心概念、架构设计和 Python SDK 的使用,能够在实际项目中实现分布式追踪(Traces)、指标(Metrics)和日志(Logs)的采集、导出与可视化。


二、学习路线总览

阶段1: 基础概念        (2-3天)
阶段2: Traces 深入     (3-4天)
阶段3: Metrics 深入    (2-3天)
阶段4: Logs 深入       (1-2天)
阶段5: Context 传播    (2-3天)
阶段6: 导出与后端集成   (2-3天)
阶段7: 自动检测        (2-3天)
阶段8: 实战项目        (3-5天)
阶段9: 生产最佳实践     (2-3天)

三、详细学习计划

阶段 1:基础概念与架构(2-3天)

1.1 可观测性基础

  • 什么是可观测性(Observability):与传统监控的区别
  • 三大支柱:Traces(追踪)、Metrics(指标)、Logs(日志)
  • 为什么需要 OpenTelemetry:厂商中立、统一标准、CNCF 项目

1.2 OpenTelemetry 架构

  • 整体架构:API → SDK → Exporter → Collector → Backend
  • 核心组件
    • API:定义数据类型和操作的接口(与厂商无关)
    • SDK:API 的具体实现,负责数据采集和处理
    • Exporter:将数据导出到后端系统(Jaeger、Zipkin、OTLP 等)
    • Collector:独立的数据收集/处理/导出服务
  • OTLP 协议:OpenTelemetry Protocol,统一的数据传输协议

1.3 Python SDK 安装与基本配置

bash
# 核心包
pip install opentelemetry-api
pip install opentelemetry-sdk

# 常用导出器
pip install opentelemetry-exporter-otlp
pip install opentelemetry-exporter-jaeger
pip install opentelemetry-exporter-prometheus

# 自动检测
pip install opentelemetry-distro
pip install opentelemetry-instrumentation

1.4 学习资源


阶段 2:Traces 深入(3-4天)

2.1 核心概念

  • Trace:一次完整请求的调用链路
  • Span:调用链中的一个操作单元
  • SpanContext:Span 的上下文信息(trace_id, span_id, trace_flags)
  • Span 之间的关系:Parent-Child、Link
  • SpanKind:CLIENT, SERVER, PRODUCER, CONSUMER, INTERNAL

2.2 TracerProvider 与 Tracer

python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    BatchSpanProcessor,
    SimpleSpanProcessor,
    ConsoleSpanExporter,
)
from opentelemetry.sdk.resources import Resource

# 创建 Resource(标识服务信息)
resource = Resource.create({
    "service.name": "my-service",
    "service.version": "1.0.0",
    "deployment.environment": "development",
})

# 创建 TracerProvider
provider = TracerProvider(resource=resource)

# 添加 SpanProcessor + Exporter
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)

# 设置全局 TracerProvider
trace.set_tracer_provider(provider)

# 获取 Tracer
tracer = trace.get_tracer("my.tracer.name", "0.1.0")

2.3 创建和管理 Span

python
# 基本用法 - 使用上下文管理器
with tracer.start_as_current_span("operation-name") as span:
    span.set_attribute("http.method", "GET")
    span.set_attribute("http.url", "https://example.com")
    # 执行操作...

# 嵌套 Span(自动建立父子关系)
with tracer.start_as_current_span("parent") as parent_span:
    with tracer.start_as_current_span("child") as child_span:
        child_span.set_attribute("key", "value")

# 添加事件(Events)
with tracer.start_as_current_span("operation") as span:
    span.add_event("cache.miss", {"cache.key": "user:123"})

# 记录异常
with tracer.start_as_current_span("operation") as span:
    try:
        risky_operation()
    except Exception as e:
        span.set_status(trace.StatusCode.ERROR, str(e))
        span.record_exception(e)
        raise

2.4 Span 属性(Attributes)

  • 语义约定(Semantic Conventions):标准化的属性命名
    • HTTP:http.method, http.status_code, http.url
    • 数据库:db.system, db.statement, db.name
    • RPC:rpc.system, rpc.method, rpc.service
  • 自定义属性:业务相关的键值对

2.5 SpanProcessor 详解

  • SimpleSpanProcessor:同步导出,适合开发调试
  • BatchSpanProcessor:批量异步导出,适合生产环境
    • 配置参数:max_queue_size, max_export_batch_size, schedule_delay_millis

2.6 采样策略(Sampling)

python
from opentelemetry.sdk.trace.sampling import (
    ALWAYS_ON,
    ALWAYS_OFF,
    TraceIdRatioBased,
    ParentBased,
)

# 始终采样
provider = TracerProvider(sampler=ALWAYS_ON)

# 按比例采样(10%)
provider = TracerProvider(sampler=TraceIdRatioBased(0.1))

# 基于父 Span 决策的采样
provider = TracerProvider(
    sampler=ParentBased(root=TraceIdRatioBased(0.5))
)

2.7 练习项目

  • 手动为一个 Flask/FastAPI 应用添加 Trace
  • 实现跨服务的分布式追踪
  • 使用 ConsoleExporter 观察 Span 输出结构

阶段 3:Metrics 深入(2-3天)

3.1 核心概念

  • Meter:创建指标的入口
  • Instrument(仪器)类型
    • Counter:只增不减的计数器(如请求总数)
    • UpDownCounter:可增可减的计数器(如当前活跃连接数)
    • Histogram:分布统计(如请求耗时分布)
    • Gauge:瞬时值(如 CPU 使用率、内存占用)
    • ObservableCounter / ObservableGauge:异步回调式指标

3.2 MeterProvider 与 Meter

python
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import (
    PeriodicExportingMetricReader,
    ConsoleMetricExporter,
)

# 创建 MetricReader
reader = PeriodicExportingMetricReader(
    ConsoleMetricExporter(),
    export_interval_millis=5000,
)

# 创建 MeterProvider
provider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(provider)

# 获取 Meter
meter = metrics.get_meter("my.meter.name", "0.1.0")

3.3 使用各类 Instrument

python
# Counter
request_counter = meter.create_counter(
    name="http.server.request.count",
    description="Total number of HTTP requests",
    unit="1",
)
request_counter.add(1, {"http.method": "GET", "http.route": "/api/users"})

# Histogram
request_duration = meter.create_histogram(
    name="http.server.request.duration",
    description="HTTP request duration",
    unit="ms",
)
request_duration.record(150.5, {"http.method": "POST"})

# UpDownCounter
active_connections = meter.create_up_down_counter(
    name="http.server.active_connections",
    description="Number of active connections",
)
active_connections.add(1)   # 连接建立
active_connections.add(-1)  # 连接关闭

# Observable Gauge(异步回调)
def cpu_usage_callback(options):
    import psutil
    yield metrics.Observation(psutil.cpu_percent())

meter.create_observable_gauge(
    name="system.cpu.usage",
    callbacks=[cpu_usage_callback],
    description="CPU usage percentage",
)

3.4 Views(视图)

  • 自定义聚合方式
  • 过滤和重命名指标
  • 配置 Histogram 的 bucket 边界

3.5 练习项目

  • 为 Web 应用添加请求计数、延迟分布等指标
  • 使用 Prometheus Exporter 导出指标并可视化

阶段 4:Logs 深入(1-2天)

4.1 核心概念

  • LogRecord:一条日志记录
  • LoggerProvider:创建 Logger 的工厂
  • LogRecordProcessor:处理日志的管道
  • 与 Python logging 模块的集成

4.2 集成 Python logging

python
import logging
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import (
    BatchLogRecordProcessor,
    ConsoleLogExporter,
)

# 创建 LoggerProvider
logger_provider = LoggerProvider()
set_logger_provider(logger_provider)

# 添加处理器
logger_provider.add_log_record_processor(
    BatchLogRecordProcessor(ConsoleLogExporter())
)

# 创建 LoggingHandler 并添加到 Python logger
handler = LoggingHandler(
    level=logging.NOTSET,
    logger_provider=logger_provider,
)

logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.INFO)

# 正常使用 Python logging,自动关联 Trace 上下文
logger = logging.getLogger(__name__)
logger.info("User logged in", extra={"user.id": "12345"})

4.3 日志与 Trace 的关联

  • 日志自动携带 trace_idspan_id
  • 在 Jaeger/Grafana 中实现日志与 Trace 的联动查看

4.4 练习项目

  • 将现有应用的日志接入 OpenTelemetry
  • 验证日志与 Trace 的关联效果

阶段 5:Context 传播机制(2-3天)

5.1 核心概念

  • Context:存储当前 Span 等信息的不可变容器
  • Propagator:在进程间传递 Context 的机制
  • W3C TraceContext:标准的传播格式(traceparent, tracestate 头)
  • W3C Baggage:跨服务传递业务数据

5.2 传播器配置

python
from opentelemetry.propagate import set_global_textmap
from opentelemetry.propagators.composite import CompositeTextMapPropagator
from opentelemetry.propagate import inject, extract
from opentelemetry.trace.propagation import TraceContextTextMapPropagator
from opentelemetry.baggage.propagation import W3CBaggagePropagator

# 设置全局传播器
set_global_textmap(
    CompositeTextMapPropagator([
        TraceContextTextMapPropagator(),
        W3CBaggagePropagator(),
    ])
)

5.3 手动注入/提取 Context

python
from opentelemetry.propagate import inject, extract
from opentelemetry import context, baggage

# 注入(发送端):将 Context 写入 HTTP 头
headers = {}
inject(headers)
# headers 现在包含 traceparent 等头信息
# requests.get("http://downstream/api", headers=headers)

# 提取(接收端):从 HTTP 头恢复 Context
ctx = extract(incoming_headers)
with tracer.start_as_current_span("handle-request", context=ctx):
    pass

# Baggage 使用
ctx = baggage.set_baggage("user.id", "12345")
context.attach(ctx)

5.4 深入理解

  • context.attach()context.detach() 的作用
  • token 机制防止 Context 泄漏
  • 异步场景下的 Context 传播(asyncio)

5.5 练习项目

  • 实现两个微服务之间的 Context 传播
  • 使用 Baggage 传递业务信息(如用户 ID、租户 ID)

阶段 6:导出与后端集成(2-3天)

6.1 OTLP Exporter

python
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter

# gRPC 方式
trace_exporter = OTLPSpanExporter(
    endpoint="localhost:4317",
    insecure=True,
)

# HTTP 方式
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
trace_exporter = OTLPSpanExporter(
    endpoint="http://localhost:4318/v1/traces",
)

6.2 OpenTelemetry Collector

  • 架构:Receivers → Processors → Exporters
  • 部署方式:Agent 模式 vs Gateway 模式
  • 配置文件示例
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
  memory_limiter:
    check_interval: 1s
    limit_mib: 512

exporters:
  jaeger:
    endpoint: jaeger:14250
    tls:
      insecure: true
  prometheus:
    endpoint: 0.0.0.0:8889

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch, memory_limiter]
      exporters: [jaeger]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [prometheus]

6.3 后端可视化系统

系统支持信号特点
JaegerTracesCNCF 项目,专注分布式追踪
ZipkinTraces轻量级追踪系统
PrometheusMetrics拉取模式指标采集
GrafanaAll统一可视化面板
Grafana TempoTraces高性能追踪后端
Grafana LokiLogs日志聚合系统
LangfuseTracesLLM 应用专用可观测性

6.4 练习项目

  • 使用 Docker Compose 搭建 Collector + Jaeger + Prometheus + Grafana
  • 配置 Collector 的 Pipeline

阶段 7:自动检测(Automatic Instrumentation)(2-3天)

7.1 原理

  • Monkey Patching:在运行时修改库的代码
  • opentelemetry-instrumentation 提供的自动检测框架

7.2 常用 Instrumentation 库

bash
# Web 框架
pip install opentelemetry-instrumentation-flask
pip install opentelemetry-instrumentation-fastapi
pip install opentelemetry-instrumentation-django

# HTTP 客户端
pip install opentelemetry-instrumentation-requests
pip install opentelemetry-instrumentation-httpx
pip install opentelemetry-instrumentation-aiohttp-client

# 数据库
pip install opentelemetry-instrumentation-sqlalchemy
pip install opentelemetry-instrumentation-redis
pip install opentelemetry-instrumentation-pymongo
pip install opentelemetry-instrumentation-psycopg2

# 消息队列
pip install opentelemetry-instrumentation-celery
pip install opentelemetry-instrumentation-kafka-python

# gRPC
pip install opentelemetry-instrumentation-grpc

# 其他
pip install opentelemetry-instrumentation-logging

7.3 使用方式

python
# 方式一:编程式
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor

FastAPIInstrumentor.instrument_app(app)
RequestsInstrumentor().instrument()
SQLAlchemyInstrumentor().instrument(engine=engine)

# 方式二:命令行自动检测(零代码侵入)
# opentelemetry-instrument python app.py

7.4 自定义 Instrumentation

python
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from wrapt import wrap_function_wrapper

class MyLibraryInstrumentor(BaseInstrumentor):
    def instrumentation_dependencies(self):
        return ["my-library >= 1.0"]

    def _instrument(self, **kwargs):
        tracer_provider = kwargs.get("tracer_provider")
        tracer = trace.get_tracer(__name__, tracer_provider=tracer_provider)

        def _wrapper(wrapped, instance, args, kwargs):
            with tracer.start_as_current_span("my_library.operation"):
                return wrapped(*args, **kwargs)

        wrap_function_wrapper("my_library", "Client.call", _wrapper)

    def _uninstrument(self, **kwargs):
        pass

7.5 练习项目

  • 对 FastAPI + SQLAlchemy + Redis 应用进行全链路自动检测
  • 编写自定义 Instrumentor

阶段 8:实战项目(3-5天)

8.1 项目:可观测的微服务应用

架构

Client → API Gateway (FastAPI)
            ├── User Service (FastAPI)
            │       └── PostgreSQL
            ├── Order Service (FastAPI)
            │       └── Redis + PostgreSQL
            └── Notification Service (FastAPI)
                    └── Celery + RabbitMQ

实现要求

  1. 所有服务使用 OpenTelemetry 进行 Traces + Metrics + Logs 采集
  2. 使用 OTLP 导出到 Collector
  3. Collector 将数据分发到 Jaeger(Traces)+ Prometheus(Metrics)+ Loki(Logs)
  4. Grafana 统一展示面板
  5. 实现跨服务的 Context 传播
  6. 自定义业务指标(订单量、用户注册数等)

8.2 项目:LLM 应用可观测性

架构

Client → FastAPI
           ├── LLM Agent(多步骤推理)
           │     ├── Prompt 管理
           │     ├── Tool 调用
           │     └── LLM API 调用
           └── 向量数据库(RAG)

实现要求

  1. 追踪 LLM 调用链路(包括 Token 使用量、延迟、模型参数)
  2. 追踪 Agent 的多步骤推理过程
  3. 追踪 RAG 检索过程
  4. 记录 Prompt 和 Completion 内容
  5. 集成 Langfuse 进行 LLM 专用可观测性

阶段 9:生产最佳实践(2-3天)

9.1 性能优化

  • 采样策略选择:生产环境使用 ParentBased(TraceIdRatioBased) 避免全量采集
  • BatchProcessor 调优:合理配置 max_queue_sizeexport_timeout_millis
  • 属性数量控制:避免高基数(high cardinality)属性
  • 内存管理:使用 memory_limiter Processor 防止 OOM

9.2 可靠性保障

  • 优雅关闭:确保 shutdown() 被调用,刷新缓冲区
python
import atexit
from opentelemetry.sdk.trace import TracerProvider

provider = TracerProvider()
atexit.register(provider.shutdown)
  • 错误处理:Exporter 失败不应影响业务逻辑
  • 重试机制:OTLP Exporter 内置重试

9.3 安全考量

  • 敏感数据脱敏:不要在 Span 属性中存储密码、Token 等
  • TLS 加密:生产环境中 OTLP 传输使用 TLS
  • 访问控制:限制 Collector 和后端的访问权限

9.4 环境变量配置

bash
# 通过环境变量配置(零代码修改)
export OTEL_SERVICE_NAME="my-service"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://collector:4317"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_TRACES_SAMPLER="parentbased_traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production,service.version=1.2.3"
export OTEL_LOG_LEVEL="info"
export OTEL_PYTHON_LOG_CORRELATION="true"

9.5 监控告警

  • 基于 Metrics 配置 Prometheus AlertManager 告警规则
  • 基于 Trace 延迟和错误率配置告警
  • 使用 Grafana 构建 SLO 仪表板

四、推荐学习资源

官方资源

资源链接
OpenTelemetry 官方文档https://opentelemetry.io/docs/
Python SDK 文档https://opentelemetry.io/docs/languages/python/
Python SDK GitHubhttps://github.com/open-telemetry/opentelemetry-python
Python Contrib GitHubhttps://github.com/open-telemetry/opentelemetry-python-contrib
语义约定https://opentelemetry.io/docs/specs/semconv/
OTLP 规范https://opentelemetry.io/docs/specs/otlp/

书籍与课程

资源说明
《Cloud-Native Observability with OpenTelemetry》系统讲解 OTel 理论与实践
《Observability Engineering》可观测性工程方法论
OpenTelemetry Bootcamp(YouTube)官方视频教程

工具与平台

工具用途
Jaeger分布式追踪可视化
Grafana + Tempo + Loki + Prometheus全栈可观测性平台
LangfuseLLM 应用专用可观测性
SigNoz开源 APM(原生支持 OTel)

五、学习检查清单

阶段 1:基础概念 ✅

  • [ ] 能解释 Traces、Metrics、Logs 三大信号的区别和关系
  • [ ] 能画出 OpenTelemetry 的整体架构图
  • [ ] 能解释 API 和 SDK 分离设计的意义
  • [ ] 成功安装并运行第一个 OpenTelemetry Python 示例

阶段 2:Traces ✅

  • [ ] 能创建 TracerProvider 并配置 Resource
  • [ ] 能使用 Tracer 创建嵌套 Span
  • [ ] 能为 Span 添加 Attributes、Events、Status
  • [ ] 能正确处理 Span 中的异常
  • [ ] 理解 BatchSpanProcessor 和 SimpleSpanProcessor 的区别
  • [ ] 能配置不同的采样策略

阶段 3:Metrics ✅

  • [ ] 能区分 Counter、Histogram、Gauge 等 Instrument 类型
  • [ ] 能创建并使用同步和异步 Instrument
  • [ ] 能配置 PeriodicExportingMetricReader

阶段 4:Logs ✅

  • [ ] 能将 Python logging 与 OpenTelemetry 集成
  • [ ] 能实现日志与 Trace 的自动关联

阶段 5:Context 传播 ✅

  • [ ] 能解释 W3C TraceContext 的格式
  • [ ] 能手动注入和提取 Context
  • [ ] 能使用 Baggage 传递跨服务数据

阶段 6:导出与后端 ✅

  • [ ] 能配置 OTLP Exporter(gRPC 和 HTTP)
  • [ ] 能部署和配置 OpenTelemetry Collector
  • [ ] 能搭建完整的可观测性后端栈

阶段 7:自动检测 ✅

  • [ ] 能使用 Instrumentation 库自动检测常用框架
  • [ ] 能编写自定义 Instrumentor
  • [ ] 能使用命令行方式零代码接入

阶段 8:实战 ✅

  • [ ] 完成微服务可观测性项目
  • [ ] 能在 Grafana 中构建监控面板

阶段 9:生产实践 ✅

  • [ ] 能通过环境变量配置 OpenTelemetry
  • [ ] 理解性能优化和安全最佳实践
  • [ ] 能设计生产级别的可观测性方案

六、每阶段建议学习笔记文件

learnNote/opentelemetry/
├── 0_learn_plan.md              ← 本文件
├── 1_basic_concepts.md          ← 基础概念与架构
├── 2_traces.md                  ← Traces 深入
├── 3_metrics.md                 ← Metrics 深入
├── 4_logs.md                    ← Logs 深入
├── 5_context_propagation.md     ← Context 传播
├── 6_exporters_and_backends.md  ← 导出与后端集成
├── 7_auto_instrumentation.md    ← 自动检测
├── 8_practice_project.md        ← 实战项目
├── 9_best_practices.md          ← 生产最佳实践
└── examples/                    ← 代码示例
    ├── basic_trace.py
    ├── basic_metrics.py
    ├── basic_logs.py
    ├── context_propagation.py
    └── full_stack_example/