Skip to content

Python ​

Automatic traces, metrics and logs for Django, Flask, FastAPI, requests, httpx, SQLAlchemy, psycopg, Redis, Celery and more, with no code changes.

Prerequisites

An OpenTelemetry Stream and an ingest key for that Stream. See OpenTelemetry → Prerequisites.

1. Install ​

bash
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install

opentelemetry-bootstrap looks at installed packages and installs the matching instrumentation.

2. Configure ​

bash
OTEL_SERVICE_NAME=checkout-api
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT=https://ws.latency.app/v1/ingest
OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer%20lit_XXXXXXXXXXX
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true

Don't skip the protocol

Python sends over gRPC unless told otherwise, and our ingest only accepts HTTP. Keep OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf.

Only sending traces? Add OTEL_METRICS_EXPORTER=none and OTEL_LOGS_EXPORTER=none.

3. Run ​

Put opentelemetry-instrument in front of the usual start command:

bash
opentelemetry-instrument python app.py
bash
opentelemetry-instrument uvicorn main:app
bash
opentelemetry-instrument flask run
bash
opentelemetry-instrument python manage.py runserver --noreload

Django's auto-reloader starts the app in a second process that skips instrumentation, so use --noreload in development.

4. Check it's working ​

Make a few requests to the app, then open Telemetry in the Console, pick the Stream and choose Traces. Traces show up within seconds. Metrics follow within a minute.

Custom spans ​

python
from opentelemetry import trace

tracer = trace.get_tracer("checkout")

with tracer.start_as_current_span("charge-card") as span:
    span.set_attribute("order.id", order.id)
    charge_card(order)

Custom metrics ​

python
from opentelemetry import metrics

meter = metrics.get_meter("checkout")
orders = meter.create_counter("orders.placed")
duration = meter.create_histogram("checkout.duration", unit="ms")

orders.add(1, {"plan": "pro"})
duration.record(182, {"route": "/pay"})

Logs ​

Everything logged with Python's standard logging module goes to the Stream's logs, linked to the surrounding trace. Nothing else to set up.

© 2026 Latency Labs LLC