OpenTelemetry for Python
OpenTelemetry for Python can auto-instrument most popular web frameworks and libraries — so you get rich distributed tracing without modifying your application code. Traces ship to CodeXray over OTLP.
OpenTelemetry ships a command-line wrapper — opentelemetry-instrument — that instruments your Python application on the fly. Point it at your existing run command and traces start flowing, no code changes required.
Before You Begin
You'll need:
- A Python application (Python 3.8+) — any web framework, or a background service
- The URL of your CodeXray collector (e.g.,
https://your-codexray.example.com) - A project API key from the CodeXray UI (Project Settings → API Keys)
Step 1 — Install the OpenTelemetry Packages
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
What these do:
opentelemetry-distro— the OpenTelemetry distribution (SDK + auto-instrumentation runner)opentelemetry-exporter-otlp— the OTLP exporter (HTTP + gRPC)opentelemetry-bootstrap -a install— detects the libraries your project uses and installs matching instrumentation packages for each
Step 2 — Configure via Environment Variables
export OTEL_SERVICE_NAME="your-service-name"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://your-codexray.example.com"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-project-api-key"
export OTEL_METRICS_EXPORTER="none" # traces only for now
| Variable | Purpose |
|---|---|
OTEL_SERVICE_NAME | The name that appears in CodeXray's Applications list |
OTEL_EXPORTER_OTLP_ENDPOINT | Your CodeXray collector URL (no trailing slash) |
OTEL_EXPORTER_OTLP_PROTOCOL | http/protobuf (recommended) or grpc |
OTEL_EXPORTER_OTLP_HEADERS | Authentication — your project API key as x-api-key |
OTEL_RESOURCE_ATTRIBUTES | Optional — add environment, version, etc. |
Step 3 — Run Your Application with opentelemetry-instrument
Prefix your normal start command with opentelemetry-instrument:
Django
opentelemetry-instrument --traces_exporter otlp --metrics_exporter none \
./manage.py runserver --noreload 8000
Flask
opentelemetry-instrument --traces_exporter otlp --metrics_exporter none \
flask run
For production Flask behind gunicorn:
opentelemetry-instrument --traces_exporter otlp --metrics_exporter none \
gunicorn -w 4 myapp:app
FastAPI
opentelemetry-instrument --traces_exporter otlp --metrics_exporter none \
uvicorn myapp:app --host 0.0.0.0 --port 8000
Generic Python services
Any Python entry point works — background workers, cron jobs, CLI tools:
opentelemetry-instrument --traces_exporter otlp --metrics_exporter none \
python your_worker.py
What Gets Instrumented
opentelemetry-bootstrap -a install detects and instruments:
- Web frameworks — Django, Flask, FastAPI, Starlette, Falcon, Pyramid, Tornado, AIOHTTP, Bottle, Sanic
- HTTP clients —
requests,urllib,urllib3,httpx,aiohttp-client - Databases — psycopg2 (Postgres), PyMySQL, MySQL-connector, SQLAlchemy, Django ORM, asyncpg, Redis (
redis,aioredis), MongoDB (pymongo), SQLite3 - Messaging — Kafka (
confluent-kafka,aiokafka), RabbitMQ (pika), AWS SQS - RPC — gRPC (
grpcio) - Task queues — Celery
- Logging — Python
loggingmodule (for log-to-trace correlation)
See the list of instrumentations for the full, ever-growing set.
Running in a Container
Drop the install step into your Dockerfile so the image is ready to run under opentelemetry-instrument:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt \
&& pip install opentelemetry-distro opentelemetry-exporter-otlp \
&& opentelemetry-bootstrap -a install
COPY . .
ENTRYPOINT ["opentelemetry-instrument", "--traces_exporter", "otlp", "--metrics_exporter", "none"]
CMD ["gunicorn", "-w", "4", "myapp:app"]
Then set the OTel env vars at runtime (Pod spec, Docker Compose, or your orchestration of choice).
Additional Resource Attributes
Attach environment, version, and anything else you want on every span:
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production,service.version=2.1.0,service.namespace=payments"
Verifying It's Working
- Start your application with
opentelemetry-instrumentin front of your run command - Make a request (hit an endpoint, trigger a job)
- In CodeXray, open Applications → find your service (by
OTEL_SERVICE_NAME) → Traces tab - Traces should appear within a minute
If nothing appears, check the application logs — the OTel SDK logs connectivity failures and configuration problems explicitly.
Manual Instrumentation (When You Need More)
opentelemetry-instrument covers framework-level spans. For your own business logic, add spans manually:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def process_order(order_id):
with tracer.start_as_current_span("process_order") as span:
span.set_attribute("order.id", order_id)
# ... your logic ...
Custom spans automatically join the surrounding request's trace — no extra configuration needed.
Next Steps
- Advanced Database Monitoring — the next category: engine-level Postgres, MySQL, and MSSQL views
- Overview — the full Traces tab walkthrough
- OpenTelemetry for Java · for Go — instrument your other services
- eBPF-based Tracing — immediate coverage for services you can't instrument