ASGI Instrumentation for OpenTelemetry
This library provides ASGI middleware to automatically instrument ASGI applications (such as FastAPI, Starlette, Django-channels, or Quart) for OpenTelemetry. It enables tracing and metrics collection for HTTP requests, tracking request timing and attributes. The library is currently in beta (v0.61b0) and is part of the `opentelemetry-python-contrib` repository, with new versions typically released on a monthly cadence.
Warnings
- gotcha The `opentelemetry-instrumentation-asgi` package is currently in beta. While actively developed, its API and behavior may change before a stable `1.0` release. It is not generally recommended for production environments where stability is critical.
- breaking Starting with version `0.61b0`, `SpanAttributes` were replaced with semantic convention constants. Directly referencing `SpanAttributes` might lead to `AttributeError` or incorrect attribute names.
- gotcha When using pre-fork servers like Gunicorn with multiple workers, OpenTelemetry's automatic metric generation might break. This is due to how child processes handle background threads and locks. Tracing usually remains functional, and Uvicorn with multiple workers is supported for both traces and metrics.
- gotcha To capture HTTP request and response headers as span attributes, specific environment variables must be set (e.g., `OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST`, `OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE`). Headers are case-insensitive.
Install
-
pip install opentelemetry-instrumentation-asgi opentelemetry-sdk -
pip install 'opentelemetry-instrumentation-asgi[fastapi]' # For FastAPI specific dependencies
Imports
- OpenTelemetryMiddleware
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
Quickstart
import os
import uvicorn
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
# Configure OpenTelemetry SDK
resource = Resource.create({"service.name": "my-asgi-app"})
provider = TracerProvider(resource=resource)
processor = SimpleSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
# Define a simple ASGI application
async def hello_world_app(scope, receive, send):
assert scope['type'] == 'http'
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
(b'content-type', b'text/plain'),
],
})
await send({
'type': 'http.response.body',
'body': b'Hello, OpenTelemetry World!'
})
# Instrument the ASGI application
instrumented_app = OpenTelemetryMiddleware(hello_world_app)
# To run this example:
# 1. Save as 'app.py'
# 2. Run: uvicorn app:instrumented_app --port 8000
# 3. Access http://localhost:8000/ in your browser.
# You will see trace output in the console where uvicorn is running.
# Note: This is an embedded example. In a real application, you would typically
# apply the middleware to your framework's app instance (e.g., FastAPI, Starlette).
# For example, for FastAPI:
# from fastapi import FastAPI
# app = FastAPI()
# app.add_middleware(OpenTelemetryMiddleware)