SuperAPI AI 工具集

opentelemetry

部署与运维

查看项目

更新于 10-15 09:53

技能介绍

用途

本知识库面向 OpenTelemetry(OTel)在 Python 中的实践,索引了 traces、metrics、日志与 trace 关联、分布式传播等主题。参考资料侧重记录各类“坑”,权威参考位于 https://opentelemetry-python.readthedocs.io 与 https://opentelemetry.io/docs/。

适用时机包括:需要分布式追踪的新 Python 服务;为 FastAPI / Celery / 异步 Python 添加 OTel;需要传播器接线的自定义传输(AMQP、ZMQ、Kafka);OTLP 导出器 / Collector / AWS ADOT 配置;审计现有埋点的缺口或反模式;日志与 trace 关联;生产环境采样策略选择。

生产快速上手配方

多数 Python 服务可从此起步再迭代:

  • 初始化:opentelemetry-bootstrap -a install 加 opentelemetry-instrument 包装器
  • Resource:设置 service.name、service.version、deployment.environment
  • Sampler:ParentBased(TraceIdRatioBased(0.1)),即 10% 头部采样
  • Exporter:OTLP gRPC 指向本地 Collector 的 localhost:4317
  • Processor:BatchSpanProcessor 使用默认调优(突发流量时提高 OTEL_BSP_MAX_QUEUE_SIZE=8192)
  • 关闭:在 lifespan / atexit / SIGTERM 中注册 provider.shutdown()

随后按实际需要升级:自定义业务 span 使用手动 tracer.start_as_current_span();非 HTTP 传输使用自定义传播器;AWS 部署使用 ADOT 发行版加 X-Ray ID 生成器;高吞吐调优 BSP 队列大小与导出超时;仅保留错误使用 Collector 端尾部采样。

自动与手动埋点矩阵

  • HTTP 框架:自动,如 FastAPI、Django、Flask
  • 数据库客户端:自动,如 SQLAlchemy、psycopg2、asyncpg
  • HTTP 客户端:自动,如 httpx、requests、aiohttp
  • 消息队列:自动,如 Celery、Kafka
  • 缓存:自动,如 redis、memcached
  • 业务逻辑:手动,如订单处理、支付流程
  • 自定义传输:手动,如 AMQP 载荷、ZMQ 事件

组合模式:opentelemetry-instrument 包装应用实现自动埋点;在路由/处理器内部使用手动 span 记录业务逻辑。

关键框架陷阱

  • Celery:在 fork 之后通过 @worker_process_init.connect 初始化 OTel。BatchSpanProcessor 线程无法在 fork() 后存活,否则导出会静默失败。
  • SQLAlchemy async:向 instrumentor 传入 engine.sync_engine,而非异步 engine。
  • FastAPI:在 lifespan 清理中注册 provider.shutdown(),否则每次重启都会丢失最后一批 span。
  • HTTP 状态 / Span Status:仅 5xx 映射为 StatusCode.ERROR。4xx 属于客户端错误,保持 UNSET。业务拒绝(如支付被拒)使用 add_event,而非 ERROR。

自定义传输传播(骨架)

针对 AMQP、ZMQ、自定义 socket:生产端注入、消费端提取,使用 W3C TraceContext 格式。

# Producer
from opentelemetry.propagate import inject
headers = {}; inject(headers)
message.payload["_trace_context"] = headers

# Consumer
from opentelemetry.propagate import extract
from opentelemetry import context, trace
ctx = extract(carrier=message.payload.get("_trace_context", {}))
token = context.attach(ctx)
try:
    with trace.get_tracer(__name__).start_as_current_span("process"):
        handle(message)
finally:
    context.detach(token)

采样决策树

  • ParentBased(TraceIdRatioBased(rate)):正确的默认选择。尊重上游决策,仅对根 span 应用委托。若不用 ParentBased,下游服务会重新掷骰,导致 trace 断裂。
  • Collector 端尾部采样:需要在采样常规流量的同时保留 100% 错误/慢 trace 时使用。需要 trace-ID 亲和性(前置 loadbalancing exporter)。
  • 规模化混合方案:SDK 头部采样 10-20%,Collector 端尾部采样保留错误/慢请求。
  • 环境变量快捷方式:OTEL_TRACES_SAMPLER=parentbased_traceidratio,OTEL_TRACES_SAMPLER_ARG=0.1。

参考索引

  • async-context-propagation.md:contextvars 机制、asyncio 任务传播、线程边界陷阱、TracedThreadPoolExecutor、fork+BSP 丢失、Python 3.12+ 改进(调试上下文缺失/断裂时优先阅读)
  • instrumentation-patterns.md:自动埋点设置、FastAPI/Celery/SQLAlchemy 模式、traced_async 装饰器、TracedClass mixin、敏感参数脱敏、错误处理
  • exporters-and-backends.md:OTLP gRPC 与 HTTP、BSP 调优、传播格式、自定义 SpanProcessor、多后端 Collector YAML
  • aws-deployment.md:ADOT 发行版、X-Ray ID 生成器与传播器、带 memory_limiter 顺序的 ECS sidecar、IAM 列表、Lambda 层、何时不用 Collector、X-Ray SDK 迁移
  • production-checklist.md:运维 do/don't 规则、资源检测样板、信号成熟度、版本固定策略

三大支柱关联

将 trace_id / span_id / service_name 注入每条标准库日志记录:

from opentelemetry.instrumentation.logging import LoggingInstrumentor
LoggingInstrumentor().instrument(set_logging_format=True)
# 或环境变量:OTEL_PYTHON_LOG_CORRELATION=true

指标方面:MeterProvider 加 Counter/Histogram/UpDownCounter/ObservableGauge。与 TracerProvider 共享 Resource,保证服务身份一致。

OTLP 日志导出方面:Logs SDK(opentelemetry._logs,前导下划线表示实验性)。当前生产环境建议使用 LoggingInstrumentor 桥接,并通过现有日志管道发送。

官方文档

  • Python SDK:https://opentelemetry-python.readthedocs.io/
  • 规范:https://opentelemetry.io/docs/specs/otel/
  • 全部埋点索引:https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation
  • Collector contrib:https://github.com/open-telemetry/opentelemetry-collector-contrib
  • 发布说明(升级前务必查看):https://github.com/open-telemetry/opentelemetry-python/releases