Skip to main content

Instrument a Python app for traces

The AtherOps agent receives traces over OTLP -- it does not inject tracing into a running Python process on its own. You instrument the app using the OpenTelemetry Python distribution, which auto-instruments common frameworks (Django, Flask, FastAPI, SQLAlchemy, requests, and others) without code changes.

If you haven't read Metrics/logs vs APM traces yet, that page explains why detection of a Python process does not automatically produce traces.

Prerequisites

  • The AtherOps agent is installed and running on the host.
  • collection.traces.enabled: true is set in /etc/atherops/config.yaml (this is the default).
  • Python 3.8 or later.

Step 1: Install the packages

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

opentelemetry-distro provides the opentelemetry-instrument launcher and the opentelemetry-bootstrap tool. opentelemetry-bootstrap -a install scans your installed packages and installs matching instrumentation libraries (for example, opentelemetry-instrumentation-django if Django is installed).

Step 2: Launch your app with opentelemetry-instrument

export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_SERVICE_NAME=my-python-service

opentelemetry-instrument python app.py

For a web server like Gunicorn:

opentelemetry-instrument gunicorn -w 4 myapp:app

The opentelemetry-instrument prefix works with any Python entry point -- the instrumentation wraps the process rather than modifying source code.

Step 3: Verify spans are reaching AtherOps

Generate some traffic, then query:

curl -s \
-H "Authorization: Bearer $ATHEROPS_JWT" \
"https://api.atherops.com/query/traces?service=my-python-service&limit=10"

A non-empty JSON array means spans are flowing. See Enable traces: verify spans reached AtherOps for details on the query parameters and how to obtain the bearer token.

Choosing the OTLP endpoint

Both gRPC (port 4317) and HTTP/protobuf (port 4318) work. HTTP is usually simpler; to use gRPC set:

export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc

gRPC requires opentelemetry-exporter-otlp-proto-grpc (usually installed as a transitive dependency of opentelemetry-exporter-otlp).

Troubleshooting

No spans appear after startup. Check the agent log:

journalctl -u atherops-otel-agent --since "5 min ago" | grep -i error

If there are no errors in the agent log, the app is likely not sending spans -- confirm you launched it with opentelemetry-instrument and that OTEL_EXPORTER_OTLP_ENDPOINT is set in the same shell or systemd unit.

opentelemetry-instrument: command not found. The command lives in the Python environment where you ran pip install. If you are using a virtualenv, activate it first. For system Python installs, the script may be in ~/.local/bin -- add that to your PATH.

ImportError or missing instrumentation for a framework. Run opentelemetry-bootstrap -a install again after installing new packages, or install the specific instrumentation library manually, for example pip install opentelemetry-instrumentation-fastapi.

Spans appear in the agent log path but with forward traces failed. The agent is receiving spans but cannot reach AtherOps. Check the AtherOps platform URL in /etc/atherops/config.yaml and verify network connectivity from the host.

Further reading