Python OpenTelemetry troubleshooting
Python-specific problems and their fixes. For the generic endpoint, token, and pipeline checks that apply to every language, see the shared checklist at the end.
No data appears at all
Section titled “No data appears at all”Confirm the process is actually wrapped. opentelemetry-instrument must prefix the real server command — if it wraps a shell script or a process manager that re-execs your app, instrumentation is lost. Check that the exporter variables are set in the same environment the app runs in.
To isolate whether the problem is instrumentation or export, print spans to the console:
OTEL_TRACES_EXPORTER=console opentelemetry-instrument python app.pyIf spans print but nothing reaches Osuite, the problem is export (see Exporter connectivity). If nothing prints, the problem is instrumentation (wrapper not applied, or no instrumentor for your framework).
Gunicorn and uWSGI: no spans from workers
Section titled “Gunicorn and uWSGI: no spans from workers”Gunicorn and uWSGI fork worker processes from a master after startup. A TracerProvider with a BatchSpanProcessor created before the fork keeps its background export thread in the master only, so the workers that serve requests never flush spans.
Initialize the SDK inside a post-fork hook so each worker gets its own provider and export thread.
For Gunicorn, use a post_fork hook in the config file:
def post_fork(server, worker): from telemetry import configure_telemetry configure_telemetry()Start Gunicorn with that config, and register your framework instrumentor inside configure_telemetry() (for example FlaskInstrumentor().instrument()):
opentelemetry-instrument gunicorn -c gunicorn.conf.py app:app --bind 0.0.0.0:8000For uWSGI, enable threads and run the setup in a postfork decorator:
from uwsgidecorators import postfork
@postforkdef init_telemetry(): from telemetry import configure_telemetry configure_telemetry()uwsgi --http :8000 --module app:app --enable-threads --masterThe configure_telemetry() function is the programmatic setup shown in the instrumentation overview.
Django development server: use —noreload
Section titled “Django development server: use —noreload”manage.py runserver runs an autoreloader that forks a child process to serve requests. Under opentelemetry-instrument the parent is instrumented but the child serves traffic, so no traces appear. Run the dev server with --noreload:
opentelemetry-instrument python manage.py runserver --noreloadProduction servers (Gunicorn, uWSGI) do not use the autoreloader; for those, see the fork hook above. The same forking behavior affects Uvicorn’s --reload and Flask’s debug reloader — disable them for instrumented runs.
Missing instrumentor packages
Section titled “Missing instrumentor packages”If a library is not traced — no database spans, no framework spans — the instrumentor for it is probably not installed. opentelemetry-bootstrap -a install only adds instrumentors for libraries present when it ran. Rerun it after adding a dependency:
opentelemetry-bootstrap -a installTo confirm what is installed:
pip list | grep opentelemetry-instrumentationYou can also install a single instrumentor directly, for example the Redis one:
pip install opentelemetry-instrumentation-redisExporter connectivity
Section titled “Exporter connectivity”If spans are created but nothing reaches Osuite, the exporter cannot deliver them. Work through these:
- Endpoint —
OTEL_EXPORTER_OTLP_ENDPOINTmust behttps://ingest.<region>.osuite.io:443for your region. - Token —
OTEL_EXPORTER_OTLP_HEADERSmust bex-osuite-ingest-token=<your-ingest-token>with a current token. - Protocol — the distro defaults to OTLP over gRPC. If your network only allows HTTP, switch both the protocol and the transport: set
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf. Keep the same endpoint. - TLS — port
443uses TLS. Do not setOTEL_EXPORTER_OTLP_INSECURE=trueagainst the Osuite ingest endpoint.
Surface export errors by turning up the SDK log level:
OTEL_LOG_LEVEL=debug opentelemetry-instrument python app.pyExport failures (auth, DNS, TLS, connection refused) are logged by the exporter’s retry loop. A successful export is silent.
Shared checklist
Section titled “Shared checklist”No data in Osuite after a few minutes? Work through these checks.
- Endpoint — confirm the exporter targets exactly
ingest.<region>.osuite.io:443for your region, over TLS. - Token — confirm the ingest header carries a valid
<your-ingest-token>and has not been rotated. - Pipeline — confirm the signal you expect (traces, logs, or metrics) is wired into an active pipeline with the
otlp/osuiteexporter attached. - Export errors — check the application or Collector logs for OTLP export failures (auth, DNS, TLS, connection refused).
- Network — confirm the host has outbound access to the ingest endpoint on port
443. - Timing — allow up to a minute for the first data to appear before assuming a failure.
Still stuck? Ask the Investigation Agent or contact support.