示例说明
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)