Appearance
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 installopentelemetry-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=trueDon'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.pybash
opentelemetry-instrument uvicorn main:appbash
opentelemetry-instrument flask runbash
opentelemetry-instrument python manage.py runserver --noreloadDjango'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.