← 中文资源

简体中文版本

OpenTelemetry FastAPI 链路追踪

为 FastAPI 接入 OpenTelemetry 追踪:自动埋点捕获路由 span,业务步骤创建子 span,批量导出器把数据送 OTLP 采集器。

阅读英文原文

示例说明

instrument_app 一行代码给全部路由加上框架级 span:URL、状态码、耗时自动记录。业务内部再用 start_as_current_span 叠加语义化子 span——库存预留、结账流程各自成节点,瀑布图里能看到每一步的占比。BatchSpanProcessor 攒批导出把追踪开销压到最低,异步上下文自动维持父子关系。

技术要点

  • 自动埋点覆盖框架层路由 span
  • 业务子 span 附加语义化属性
  • 批量处理器摊薄导出开销

代码解读

provider 配置服务名资源与 OTLP gRPC 导出器;reserve_stock 用上下文管理器圈定 span 范围并写入 SKU 与数量属性;checkout 的 span 记录路由模板而非具体值防止基数爆炸。instrument_app 放在应用定义完成后执行。

使用建议

span 属性值避免放用户级高基数字段。采样按流量预算配置。导出器故障不应拖垮业务,批处理器的队列上限要设置。

代码示例

from fastapi import FastAPI

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor

provider = TracerProvider(
    resource=Resource.create({'service.name': 'inventory-api'}),
)
provider.add_span_processor(
    BatchSpanProcessor(OTLPSpanExporter(endpoint='collector:4317', insecure=True))
)
trace.set_tracer_provider(provider)

tracer = trace.get_tracer(__name__)
app = FastAPI()


async def reserve_stock(sku: str, qty: int) -> bool:
    with tracer.start_as_current_span('inventory.reserve') as span:
        span.set_attribute('inventory.sku', sku)
        span.set_attribute('inventory.quantity', qty)
        return qty < 100


@app.get('/checkout/{sku}')
async def checkout(sku: str, qty: int = 1):
    with tracer.start_as_current_span('checkout.flow') as span:
        span.set_attribute('http.route', '/checkout/{sku}')
        reserved = await reserve_stock(sku, qty)
        return {'sku': sku, 'reserved': reserved}


FastAPIInstrumentor.instrument_app(app)