Python
The opentelemetry-instrument launcher
starts the OpenTelemetry SDK and patches Django, Flask, FastAPI, requests, httpx,
SQLAlchemy, psycopg, Redis, Celery and
other libraries
before your code runs.
Use this page when you run a Python service and want it in FuseScope.
| Signal | Status | What is sent |
|---|---|---|
| Traces | Stable | Spans for requests, HTTP calls, database and messaging. |
| Metrics | Stable | HTTP server/client metrics, plus what your code records. |
| Logs | Development | Records from the standard logging module, with trace IDs. |
Prerequisites
Section titled “Prerequisites”- Python 3.10 or later.
- A virtual environment with your app’s dependencies installed.
- A FuseScope collector you can reach on port 4317 or 4318. See OTLP.
Install and run
Section titled “Install and run”-
Install the distro and the OTLP exporter, then let
opentelemetry-bootstrapadd the instrumentation packages for the libraries it finds installed:Terminal window pip install opentelemetry-distro opentelemetry-exporter-otlpopentelemetry-bootstrap -a installRun
opentelemetry-bootstrapwith no arguments to only list what it would install, for example to add them torequirements.txt. -
Configure the SDK:
Terminal window export OTEL_SERVICE_NAME=checkoutexport OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=production,service.version=1.4.2export OTEL_EXPORTER_OTLP_ENDPOINT=http://fusescope-collector.example.com:4318export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobufexport OTEL_TRACES_EXPORTER=otlpexport OTEL_METRICS_EXPORTER=otlpexport OTEL_LOGS_EXPORTER=otlp -
Prefix your usual command with
opentelemetry-instrument:Terminal window opentelemetry-instrument python app.py
To skip some libraries, set OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, for example
redis,kafka. Every setting is in the
configuration reference.
Web servers and workers
Section titled “Web servers and workers”| Server | Command |
|---|---|
| Django dev server | opentelemetry-instrument python manage.py runserver --noreload |
| Flask dev server | Run with use_reloader=False; the reloader breaks instrumentation. |
| Uvicorn, one process | opentelemetry-instrument uvicorn main:app |
| Gunicorn + Uvicorn workers | opentelemetry-instrument gunicorn --workers 4 --worker-class uvicorn.workers.UvicornWorker main:app |
| Gunicorn, sync workers | Initialise in post_fork, below. |
Pre-fork servers start the SDK in the parent and then fork, which can break metric export
in the workers. With Gunicorn, initialise OpenTelemetry in each worker instead, and start
Gunicorn without opentelemetry-instrument:
from opentelemetry.instrumentation.auto_instrumentation import initialize
def post_fork(server, worker): initialize()gunicorn --config gunicorn.conf.py --workers 4 app:appEach worker gets its own service.instance.id, so don’t set one in
OTEL_RESOURCE_ATTRIBUTES. Details are in
troubleshooting.
Send to FuseScope
Section titled “Send to FuseScope”OTEL_EXPORTER_OTLP_ENDPOINT=http://fusescope-collector.example.com:4317OTEL_EXPORTER_OTLP_PROTOCOL=grpcThe http:// scheme tells the gRPC exporter to use plain text.
OTEL_EXPORTER_OTLP_ENDPOINT=http://fusescope-collector.example.com:4318OTEL_EXPORTER_OTLP_PROTOCOL=http/protobufBehind the chart ingress, use https://otlp.example.com. See
from outside the cluster.
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318OTEL_EXPORTER_OTLP_PROTOCOL=http/protobufRun the collector with Docker, on a VM or in Kubernetes.
Docker
Section titled “Docker”Run opentelemetry-bootstrap after your dependencies are installed, so it sees them:
FROM python:3.12-slimWORKDIR /appCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txt \ opentelemetry-distro opentelemetry-exporter-otlp \ && opentelemetry-bootstrap -a installCOPY . .CMD ["opentelemetry-instrument", "gunicorn", "--workers", "4", "--worker-class", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000", "main:app"]docker run \ -e OTEL_SERVICE_NAME=checkout \ -e OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=production \ -e OTEL_EXPORTER_OTLP_ENDPOINT=http://fusescope-collector.example.com:4318 \ -e OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \ -e OTEL_LOGS_EXPORTER=otlp \ checkout:latestKubernetes
Section titled “Kubernetes”Set the variables in the pod spec. The downward API adds the pod name and namespace:
env: - name: OTEL_SERVICE_NAME value: checkout - name: OTEL_EXPORTER_OTLP_ENDPOINT value: http://fusescope-otel-collector.fusescope.svc.cluster.local:4318 - name: OTEL_EXPORTER_OTLP_PROTOCOL value: http/protobuf - name: OTEL_LOGS_EXPORTER value: otlp - name: K8S_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: K8S_NAMESPACE_NAME valueFrom: fieldRef: fieldPath: metadata.namespace - name: OTEL_RESOURCE_ATTRIBUTES value: deployment.environment.name=production,k8s.pod.name=$(K8S_POD_NAME),k8s.namespace.name=$(K8S_NAMESPACE_NAME)$(VAR) only expands variables defined earlier in the list, so keep
OTEL_RESOURCE_ATTRIBUTES last.
Records from the standard logging module (and libraries built on it, such as
structlog with the stdlib backend) are exported over OTLP with the trace and span IDs of
the active span.
| Setting | Effect |
|---|---|
OTEL_LOGS_EXPORTER=otlp |
Export logs over OTLP. |
OTEL_PYTHON_LOG_AUTO_INSTRUMENTATION |
Attach the OpenTelemetry handler to logging. On by default since OpenTelemetry Python 1.40.0; set false to turn off. |
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true |
Same, for releases before 1.40.0, where it is off by default. |
OTEL_PYTHON_LOG_CORRELATION=true |
Also add otelTraceID and otelSpanID to each record, for your own log format. |
The handler comes from opentelemetry-instrumentation-logging. If logs don’t arrive, check
that it is installed (pip show opentelemetry-instrumentation-logging). If a collector
already reads your stdout, set OTEL_LOGS_EXPORTER=none so each line is stored once.
Check that data arrives
Section titled “Check that data arrives”- Send a few requests to the service.
- Open Services. The service appears under its
OTEL_SERVICE_NAMEwithin a minute. - Open the Traces explorer and filter by
service.name.
Nothing arrives? Add console to an exporter (OTEL_TRACES_EXPORTER=otlp,console) to see
spans in the terminal, and check the endpoint and protocol match.