

Integrating OpenTelemetry with FastAPI in Python For Observability
Monitoring and analyzing your apps' performance is critical for ensuring dependability in production scenarios. OpenTelemetry (OTEL) is a contemporary, open-source framework that enables you to gather and export telemetry data (traces, metrics, and logs) to various backends, including Jaeger, Zipkin, and cloud platforms.
This post will show how to combine OpenTelemetry with a basic FastAPI application to begin tracking incoming request traces. We'll keep things simple by allowing basic observability features.
Prerequisites
Before we begin, ensure you have the following:
- A basic FastAPI app (if you don’t, refer to this guide on setting up FastAPI or clone the GitHub repo).
- Python 3.8+.
- Poetry for dependency management.
Step 1: Installing OpenTelemetry Packages
We need to install some OpenTelemetry packages to set up our tracing infrastructure. Activate your Poetry environment and install these packages with the following command:
poetry add opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp \
opentelemetry-instrumentation-fastapi
This command installs:
- opentelemetry-api: Core API for OpenTelemetry, providing a foundation for tracing.
- opentelemetry-sdk: The implementation of OpenTelemetry APIs, enabling trace creation and processing.
- opentelemetry-exporter-otlp: The OpenTelemetry protocol exporter sends telemetry data to an OpenTelemetry Collector.
- opentelemetry-instrumentation-fastapi: Automatically instruments FastAPI applications to capture traces.
Step 2: Basic FastAPI Setup
Here’s a basic FastAPI app to start:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
This simple application will be our foundation for adding OpenTelemetry. Run it with:
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 1
When you visit localhost:8000, you’ll see:

Step 3: Setting Up an OpenTelemetry Collector
To export telemetry data, we need an OpenTelemetry Collector. You can run the collector locally (e.g., using Docker or another container service) or deploy it in your production environment.
Run the Collector Locally:
- You can use the OpenTelemetry Collector image from Docker Hub.
- Set it up to listen on port 4317, which our app will use to send traces.
For example, if you’re using Docker:
docker run --name otel-collector -p 4317:4317 -v $(pwd)/otel-config.yaml:/etc/otel/config.yaml otel/opentelemetry-collector --config /etc/otel/config.yaml
Replace otel-config.yaml with your preferred configuration for the collector.
Step 4: Integrating OpenTelemetry with FastAPI
To enable OpenTelemetry tracing, we’ll need to set up a global tracer in our FastAPI app.
4.1) Create a tracer.py File:
In this file, we’ll initialize an OpenTelemetry tracer to capture and export traces for each request made to our FastAPI app.
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.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import ConsoleSpanExporter # Optional for debugging
SERVICE_NAME = 'fastapi'
OTLP_COLLECTOR_ENDPOINT = ""
# Initialize OpenTelemetry Tracer globally
def initialize_tracer():
# Create a resource for trace identification with service info
resource = Resource.create({"service.name": SERVICE_NAME})
# Set up the TracerProvider, the root of all tracing
tracer_provider = TracerProvider(resource=resource)
# Configure the OTLP Exporter to send traces to the OpenTelemetry Collector
otlp_exporter = OTLPSpanExporter(endpoint=OTLP_COLLECTOR_ENDPOINT)
span_processor = BatchSpanProcessor(otlp_exporter)
tracer_provider.add_span_processor(span_processor)
# Optional: Add a ConsoleSpanExporter for local debugging
console_processor = BatchSpanProcessor(ConsoleSpanExporter())
tracer_provider.add_span_processor(console_processor)
# Set the global TracerProvider
trace.set_tracer_provider(tracer_provider)
# Initialize the tracer when the module loads
initialize_tracer()
# Function to get the global OpenTelemetry Tracer
def get_tracer():
return trace.get_tracer(SERVICE_NAME)
Explanation of Code:
- Service Name: We set SERVICE_NAME to identify the service sending traces.
- Resource: Defines metadata about the service (e.g., name), making it easy to track where traces come from.
- TracerProvider: The central object responsible for creating and managing tracers. We initialize it with our service metadata.
- OTLPSpanExporter: An exporter that sends collected traces to the OpenTelemetry Collector over HTTP. We configure it with the OTLP_COLLECTOR_ENDPOINT, pointing to our collector.
- BatchSpanProcessor: Ensures spans are batched before export, optimizing network calls.
- ConsoleSpanExporter (Optional): Exports spans to the console, applicable for local debugging.
4.2) Modify the FastAPI App to Use OpenTelemetry:
Now, we’ll add OpenTelemetry instrumentation to our FastAPI app. Open your main.py file and update it as follows:
from fastapi import FastAPI
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from tracer import initialize_tracer
# Initialize the tracer
initialize_tracer()
app = FastAPI()
# Instrument FastAPI with OpenTelemetry
FastAPIInstrumentor.instrument_app(app)
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
Explanation of Code:
- initialize_tracer(): Initializes the global tracer when the app starts.
- FastAPIInstrumentor.instrument_app(app): Automatically instruments the FastAPI app to capture traces for all requests. This will monitor each route's request/response lifecycle and send trace data to the OpenTelemetry Collector.
Step 5: Running the FastAPI App
With everything configured, start your FastAPI app with:
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 1
Testing the Traces
- Open a browser or use curl to test the FastAPI endpoint:
curl
- You should see the response:
{"message": "Hello, World!"}
- Your terminal should show the following:

Conclusion
That is it! You have successfully incorporated OpenTelemetry into your FastAPI program, and traces may now be sent to an OpenTelemetry collector. This configuration provides basic observability, allowing you to track requests across your system and troubleshoot problems in distributed systems.
As your application grows, you may add more OpenTelemetry exporters, metrics, and logs to improve observability.