主题
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-instrumentation1.4 学习资源
- 官方文档:https://opentelemetry.io/docs/languages/python/
- 官方规范:https://opentelemetry.io/docs/specs/otel/
- GitHub 仓库:https://github.com/open-telemetry/opentelemetry-python
阶段 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)
raise2.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
- HTTP:
- 自定义属性:业务相关的键值对
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_id和span_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 后端可视化系统
| 系统 | 支持信号 | 特点 |
|---|---|---|
| Jaeger | Traces | CNCF 项目,专注分布式追踪 |
| Zipkin | Traces | 轻量级追踪系统 |
| Prometheus | Metrics | 拉取模式指标采集 |
| Grafana | All | 统一可视化面板 |
| Grafana Tempo | Traces | 高性能追踪后端 |
| Grafana Loki | Logs | 日志聚合系统 |
| Langfuse | Traces | LLM 应用专用可观测性 |
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-logging7.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.py7.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):
pass7.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实现要求:
- 所有服务使用 OpenTelemetry 进行 Traces + Metrics + Logs 采集
- 使用 OTLP 导出到 Collector
- Collector 将数据分发到 Jaeger(Traces)+ Prometheus(Metrics)+ Loki(Logs)
- Grafana 统一展示面板
- 实现跨服务的 Context 传播
- 自定义业务指标(订单量、用户注册数等)
8.2 项目:LLM 应用可观测性
架构:
Client → FastAPI
├── LLM Agent(多步骤推理)
│ ├── Prompt 管理
│ ├── Tool 调用
│ └── LLM API 调用
└── 向量数据库(RAG)实现要求:
- 追踪 LLM 调用链路(包括 Token 使用量、延迟、模型参数)
- 追踪 Agent 的多步骤推理过程
- 追踪 RAG 检索过程
- 记录 Prompt 和 Completion 内容
- 集成 Langfuse 进行 LLM 专用可观测性
阶段 9:生产最佳实践(2-3天)
9.1 性能优化
- 采样策略选择:生产环境使用
ParentBased(TraceIdRatioBased)避免全量采集 - BatchProcessor 调优:合理配置
max_queue_size和export_timeout_millis - 属性数量控制:避免高基数(high cardinality)属性
- 内存管理:使用
memory_limiterProcessor 防止 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 GitHub | https://github.com/open-telemetry/opentelemetry-python |
| Python Contrib GitHub | https://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 | 全栈可观测性平台 |
| Langfuse | LLM 应用专用可观测性 |
| 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/