{"id":549,"library":"opentelemetry-instrumentation-fastapi","title":"OpenTelemetry FastAPI Instrumentation","description":"OpenTelemetry FastAPI Instrumentation provides automatic and manual instrumentation for FastAPI web frameworks. It allows for comprehensive application performance monitoring (APM), distributed tracing, and observability by collecting traces and metrics from HTTP requests, database queries, and external API calls with minimal code changes. The library is currently in beta (version 0.61b0) and is part of the broader `opentelemetry-python-contrib` project, which sees frequent updates across its various instrumentations.","status":"active","version":"0.61b0","language":"python","source_language":"en","source_url":"https://github.com/open-telemetry/opentelemetry-python-contrib","tags":["opentelemetry","fastapi","instrumentation","tracing","metrics","observability","apm","asgi"],"install":[{"cmd":"pip install opentelemetry-instrumentation-fastapi opentelemetry-exporter-otlp","lang":"bash","label":"Install core instrumentation and OTLP exporter"}],"dependencies":[{"reason":"The web framework being instrumented.","package":"fastapi","optional":false},{"reason":"Core OpenTelemetry API for defining telemetry.","package":"opentelemetry-api","optional":false},{"reason":"Core OpenTelemetry SDK for processing and exporting telemetry.","package":"opentelemetry-sdk","optional":false},{"reason":"FastAPI is built on the ASGI specification, and this instrumentation builds upon the base ASGI instrumentation.","package":"opentelemetry-instrumentation-asgi","optional":false},{"reason":"Common exporter for sending telemetry data to an OTLP-compatible backend (e.g., Jaeger, Tempo, OpenObserve).","package":"opentelemetry-exporter-otlp","optional":true}],"imports":[{"symbol":"FastAPIInstrumentor","correct":"from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor"}],"quickstart":{"code":"import os\nfrom contextlib import asynccontextmanager\n\nfrom fastapi import FastAPI\nfrom opentelemetry import trace\nfrom opentelemetry.instrumentation.fastapi import FastAPIInstrumentor\nfrom opentelemetry.sdk.resources import Resource\nfrom opentelemetry.sdk.trace import TracerProvider\nfrom opentelemetry.sdk.trace.export import BatchSpanProcessor\nfrom opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter\n\n# Configure OpenTelemetry SDK\n# It is recommended to initialize OpenTelemetry within FastAPI's lifespan events\n# when using multi-process servers (e.g., uvicorn --workers > 1 or gunicorn).\n# For simple single-process development, top-level initialization is sufficient.\n\ndef setup_tracing():\n    resource = Resource.create(attributes={\n        \"service.name\": os.environ.get(\"OTEL_SERVICE_NAME\", \"my-fastapi-app\")\n    })\n    tracer_provider = TracerProvider(resource=resource)\n    \n    # Use OTLP HTTP exporter for traces\n    # OTLP endpoint can be configured via environment variable OTEL_EXPORTER_OTLP_ENDPOINT\n    # Default is http://localhost:4318/v1/traces for HTTP\n    otlp_exporter = OTLPSpanExporter(\n        endpoint=os.environ.get(\"OTEL_EXPORTER_OTLP_ENDPOINT\", \"http://localhost:4318/v1/traces\")\n    )\n    span_processor = BatchSpanProcessor(otlp_exporter)\n    tracer_provider.add_span_processor(span_processor)\n    trace.set_tracer_provider(tracer_provider)\n\n    print(\"OpenTelemetry tracing initialized.\")\n\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n    # Startup logic: Initialize OpenTelemetry\n    setup_tracing()\n    FastAPIInstrumentor.instrument_app(app)\n    yield\n    # Shutdown logic: Flush and shutdown exporter\n    provider = trace.get_tracer_provider()\n    if hasattr(provider, 'shutdown'):\n        provider.shutdown()\n    print(\"OpenTelemetry tracing shutdown.\")\n\n# Initialize FastAPI app with lifespan events\napp = FastAPI(lifespan=lifespan)\n\n@app.get(\"/hello\")\nasync def read_root():\n    return {\"message\": \"Hello, World!\"}\n\n@app.get(\"/items/{item_id}\")\nasync def read_item(item_id: int):\n    return {\"item_id\": item_id, \"message\": \"Item fetched\"}\n\n# To run this application:\n# 1. Save it as main.py\n# 2. Run from your terminal:\n#    OTEL_EXPORTER_OTLP_ENDPOINT=\"http://localhost:4318/v1/traces\" OTEL_SERVICE_NAME=\"my-fastapi-app\" uvicorn main:app --port 8000 --reload --lifespan on\n#    Note: For production, omit --reload and manage workers via gunicorn post_fork hooks if using multiple workers.\n# 3. Access in browser: http://localhost:8000/hello or http://localhost:8000/items/123","lang":"python","description":"This quickstart demonstrates how to set up OpenTelemetry instrumentation for a FastAPI application. It initializes a `TracerProvider` with an `OTLPSpanExporter` to send traces to an OTLP-compatible backend. The `FastAPIInstrumentor.instrument_app(app)` call automatically creates spans for incoming HTTP requests. The OpenTelemetry setup is integrated using FastAPI's `lifespan` events for proper initialization and shutdown, especially crucial for multi-process environments like uvicorn with multiple workers. Make sure an OTLP collector is running at the specified endpoint."},"warnings":[{"fix":"Always check the `CHANGELOG.md` in the `opentelemetry-python-contrib` repository before upgrading to new beta versions. Pin your dependency versions to avoid unexpected changes.","message":"The `opentelemetry-instrumentation-fastapi` library is currently in beta (indicated by the `b0` suffix in the version). This means its API and behavior might be subject to breaking changes in future releases before reaching a stable `1.0.0` version.","severity":"gotcha","affected_versions":"0.x.xb0"},{"fix":"Ensure your project uses FastAPI version 0.92.0 or newer. Upgrade FastAPI if necessary (`pip install \"fastapi>=0.92.0\"`).","message":"Support for FastAPI versions earlier than 0.92 has been dropped. Using older FastAPI versions will lead to `FastAPIInstrumentor` failing to properly instrument your application or causing unexpected errors.","severity":"breaking","affected_versions":"<0.60b0"},{"fix":"Initialize OpenTelemetry SDK and `FastAPIInstrumentor.instrument_app()` within FastAPI's `lifespan` event handlers or within Gunicorn's `post_fork` hook. This ensures each worker process has its own isolated and correctly initialized OpenTelemetry components. Avoid `uvicorn --reload` when reliable tracing is required.","message":"When running FastAPI with `uvicorn --reload` (development mode) or with multiple worker processes (e.g., `uvicorn --workers N` or `gunicorn` with `uvicorn.workers.UvicornWorker`), OpenTelemetry SDK initialization can cause issues due to Python's process forking model. Background threads and shared resources from the parent process are not correctly replicated in child workers.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure `FastAPIInstrumentor.instrument_app(app)` is called early in your application's startup, typically immediately after `app = FastAPI()` or within a `lifespan` event. If using `opentelemetry-bootstrap`, ensure `initialize()` is called before importing FastAPI.","message":"The order of instrumentation is critical. `FastAPIInstrumentor.instrument_app(app)` must be called after the FastAPI application instance (`app`) has been created but before the application starts processing requests. Improper ordering can lead to incomplete tracing or errors.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Regularly consult the official OpenTelemetry semantic conventions for HTTP and other relevant signals. Update your observability backend to the latest versions to ensure proper interpretation of attributes. If using custom parsers, adjust them accordingly.","message":"OpenTelemetry semantic conventions, which define naming for attributes and spans, can evolve. For example, `aws.region` was changed to `cloud.region`. This can affect how your telemetry data is displayed in older or un-updated observability backends.","severity":"gotcha","affected_versions":"All versions (due to evolving standards)"},{"fix":"Ensure `fastapi` is included in your project's dependencies and installed (e.g., `pip install fastapi`).","message":"The `opentelemetry-instrumentation-fastapi` library requires `fastapi` as a peer dependency. This means `fastapi` must be explicitly installed in your project environment for the instrumentation to function. A `ModuleNotFoundError: No module named 'fastapi'` indicates that the `fastapi` package is missing.","severity":"breaking","affected_versions":"All versions"},{"fix":"Ensure FastAPI is installed in your project's environment using `pip install fastapi` (or `pip install \"fastapi[all]\"` for full features). If using a virtual environment or Docker, verify it's correctly activated/configured.","message":"The `fastapi` package must be installed for `opentelemetry-instrumentation-fastapi` to function. This error occurs when FastAPI is not found in the Python environment.","severity":"breaking","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T15:00:00.787Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Install the necessary packages: `pip install opentelemetry-instrumentation-fastapi opentelemetry-instrumentation-asgi`.","cause":"The `opentelemetry-instrumentation-fastapi` package or its underlying dependencies (like `opentelemetry-instrumentation-asgi`) are not installed in the current Python environment.","error":"ModuleNotFoundError: No module named 'opentelemetry.instrumentation.fastapi'"},{"fix":"For development, avoid `--reload` or initialize OpenTelemetry within FastAPI's lifespan events in each worker. For production with multiple workers, use Gunicorn with Uvicorn workers and initialize OpenTelemetry within Gunicorn's `post_fork` hook or FastAPI's lifespan events in the worker process.","cause":"`uvicorn --reload` and `uvicorn --workers N` modes create child processes, which can cause OpenTelemetry SDK initialization in the parent process to not correctly propagate or lead to conflicts in the children, breaking instrumentation.","error":"OpenTelemetry traces not appearing when running FastAPI with uvicorn --reload or --workers N"},{"fix":"Ensure that `FastAPIInstrumentor.instrument_app(app)` is called immediately after the FastAPI app is defined, or ensure `opentelemetry.instrumentation.auto_instrumentation.initialize()` is called *before* importing `fastapi` or creating the `FastAPI` app instance.","cause":"The `FastAPIInstrumentor.instrument_app(app)` call or `opentelemetry.instrumentation.auto_instrumentation.initialize()` is being executed after the FastAPI application instance (`app`) has already been created or imported, preventing the instrumentation from correctly patching the framework's internal components.","error":"OpenTelemetry FastAPI not instrumenting / traces not showing up (no Python error)"},{"fix":"Verify the `OTEL_EXPORTER_OTLP_ENDPOINT` (or `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`) environment variable is correctly set, including the protocol (e.g., `http://localhost:4318` for HTTP, `grpc://localhost:4317` for gRPC). Ensure the OpenTelemetry Collector or tracing backend is running and reachable at the specified address and port.","cause":"The OpenTelemetry exporter is misconfigured, often due to an incorrect OTLP endpoint URL, using the wrong port for HTTP vs. gRPC protocols, or the OpenTelemetry Collector/backend not running or being inaccessible.","error":"OpenTelemetry FastAPI traces not sent to collector / OTLP exporter connection refused"}],"ecosystem":"pypi","meta_description":null,"install_score":0,"install_tag":"stale","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}