OpenTelemetry Python FastAPI Tracing

Trace FastAPI request flows with OpenTelemetry, creating spans for routes and internal steps, then exporting OTLP batches to a collector.

PythonFastapiResilience

Code

snippet
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)