SigNoz
Why SigNozDocs
PricingCustomer Stories
Docs
IntroductionContributingMigrate from DatadogSigNoz API
OpenTelemetry
What is OpenTelemetryOpenTelemetry Collector GuideOpenTelemetry Demo
Community
Support
Slack
X
Launch Week
Changelog
Dashboard Templates
DevOps Wordle
Newsletter
KubeCon, Atlanta 2025
More
SigNoz vs DatadogSigNoz vs New RelicSigNoz vs GrafanaSigNoz vs Dynatrace
Careers
AboutTermsPrivacySecurity & Compliance
SigNoz Logo
SigNoz
All systems operational
HIPAASOC-2
SigNoz Cloud - This page applies to SigNoz Cloud editions.
Self-Host - This page applies to self-hosted SigNoz editions.

Python OpenTelemetry Instrumentation Guide

This guide shows you how to instrument your Python application with OpenTelemetry and send traces to SigNoz. The auto-instrumentation approach works with Django, Flask, FastAPI, Falcon, Celery, and most Python libraries out of the box.

Most steps are identical. To adapt this guide, update the endpoint and remove the ingestion key header as shown in Cloud → Self-Hosted.

Prerequisites

  • Python 3.9+
  • An instance of SigNoz (either Cloud or Self-Hosted)

Tested with Python 3.11 and OpenTelemetry Python SDK v1.27.0.

Send traces to SigNoz

A VM is a virtual computer that runs on physical hardware. This includes:

  • Cloud VMs: AWS EC2, Google Compute Engine, Azure VMs, DigitalOcean Droplets
  • On-premise VMs: VMware, VirtualBox, Hyper-V, KVM
  • Bare metal servers: Physical servers running Linux/Unix directly

Use this section if you're deploying your Python application directly on a server or VM without containerization.

Step 1. Set environment variables

export OTEL_RESOURCE_ATTRIBUTES="service.name=<service-name>"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443"
export OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_METRICS_EXPORTER="none"

The bootstrap command (Step 3) installs instrumentations for all detected libraries, including HTTP clients like requests, urllib3, and httpx. These libraries generate metrics such as request duration histograms and optionally request/response body sizes for every outgoing HTTP call.

Since opentelemetry-distro enables metrics by default, these HTTP metrics would be sent to SigNoz even though this guide only covers traces. For apps that make frequent HTTP calls, this can add up quickly.

Setting this to none disables metrics while keeping traces working as expected. If you want metrics later, you can change it to otlp or remove this variable altogether.

Verify these values:

  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: A descriptive name for your service (e.g., payment-service).

Step 2. Install OpenTelemetry packages

pip install opentelemetry-distro opentelemetry-exporter-otlp

Step 3. Install instrumentation for your dependencies

This command detects your installed packages and adds the corresponding instrumentation libraries:

opentelemetry-bootstrap --action=install

Run this after installing all your application dependencies. It will only instrument packages that are already installed.

Step 4. Run your application

opentelemetry-instrument <your_run_command>

See Framework instrumentation below for framework-specific commands.

For centralized instrumentation management or auto-injection without code changes, see the OTel Operator tab.

Step 1. Set environment variables

Add these environment variables to your deployment manifest:

env:
- name: OTEL_RESOURCE_ATTRIBUTES
  value: 'service.name=<service-name>'
- name: OTEL_EXPORTER_OTLP_ENDPOINT
  value: 'https://ingest.<region>.signoz.cloud:443'
- name: OTEL_EXPORTER_OTLP_HEADERS
  value: 'signoz-ingestion-key=<your-ingestion-key>'
- name: OTEL_EXPORTER_OTLP_PROTOCOL
  value: 'http/protobuf'
- name: OTEL_METRICS_EXPORTER
  value: 'none'

The bootstrap command (Step 3) installs instrumentations for all detected libraries, including HTTP clients like requests, urllib3, and httpx. These libraries generate metrics such as request duration histograms and optionally request/response body sizes for every outgoing HTTP call.

Since opentelemetry-distro enables metrics by default, these HTTP metrics would be sent to SigNoz even though this guide only covers traces. For apps that make frequent HTTP calls, this can add up quickly.

Setting this to none disables metrics while keeping traces working as expected. If you want metrics later, you can change it to otlp or remove this variable altogether.

Verify these values:

  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: A descriptive name for your service (e.g., payment-service).

Step 2. Install OpenTelemetry packages

pip install opentelemetry-distro opentelemetry-exporter-otlp

Step 3. Install instrumentation for your dependencies

This command detects your installed packages and adds the corresponding instrumentation libraries:

opentelemetry-bootstrap --action=install

Run this after installing all your application dependencies. It will only instrument packages that are already installed.

Step 4. Run your application

opentelemetry-instrument <your_run_command>

See Framework instrumentation below for framework-specific commands.

The OpenTelemetry Operator auto-injects instrumentation into your Python pods without modifying your application image.

Step 1. Set up the OpenTelemetry Operator

Install the Operator and Collector following the K8s OTel Operator installation guide.

Step 2. Create the Instrumentation resource

Create instrumentation.yaml to configure Python auto-instrumentation:

instrumentation.yaml
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: python-instrumentation
spec:
  exporter:
    endpoint: http://otel-collector-collector:4318
  propagators:
    - tracecontext
    - baggage
  env:
    - name: OTEL_METRICS_EXPORTER
      value: "none"
  python:
    image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-python:latest

The OTel Operator's Python auto-instrumentation image includes instrumentations for HTTP clients like requests, urllib3, and httpx. These libraries generate metrics such as request duration histograms for every outgoing HTTP call.

Since metrics are enabled by default, these HTTP metrics would be sent to your collector even though this guide only covers traces. For apps that make frequent HTTP calls, this can add up quickly.

Setting OTEL_METRICS_EXPORTER to none disables metrics while keeping traces working as expected. If you want metrics later, you can change it to otlp or remove this variable altogether.

Deploy this resource to your cluster.

Step 3. Add annotations to your deployment

Add these annotations to your pod template's metadata.annotations:

instrumentation.opentelemetry.io/inject-python: "true"
instrumentation.opentelemetry.io/otel-python-platform: "glibc"  # or "musl" for Alpine

Step 1. Set environment variables

$env:OTEL_RESOURCE_ATTRIBUTES = "service.name=<service-name>"
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "https://ingest.<region>.signoz.cloud:443"
$env:OTEL_EXPORTER_OTLP_HEADERS = "signoz-ingestion-key=<your-ingestion-key>"
$env:OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"
$env:OTEL_METRICS_EXPORTER = "none"

The bootstrap command (Step 3) installs instrumentations for all detected libraries, including HTTP clients like requests, urllib3, and httpx. These libraries generate metrics such as request duration histograms and optionally request/response body sizes for every outgoing HTTP call.

Since opentelemetry-distro enables metrics by default, these HTTP metrics would be sent to SigNoz even though this guide only covers traces. For apps that make frequent HTTP calls, this can add up quickly.

Setting this to none disables metrics while keeping traces working as expected. If you want metrics later, you can change it to otlp or remove this variable altogether.

Verify these values:

  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: A descriptive name for your service (e.g., payment-service).

Step 2. Install OpenTelemetry packages

pip install opentelemetry-distro opentelemetry-exporter-otlp

Step 3. Install instrumentation for your dependencies

This command detects your installed packages and adds the corresponding instrumentation libraries:

opentelemetry-bootstrap --action=install

Run this after installing all your application dependencies. It will only instrument packages that are already installed.

Step 4. Run your application

opentelemetry-instrument <your_run_command>

See Framework instrumentation below for framework-specific commands.

Step 1. Set environment variables in Dockerfile

ENV OTEL_RESOURCE_ATTRIBUTES=service.name=<service-name>
ENV OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.<region>.signoz.cloud:443
ENV OTEL_EXPORTER_OTLP_HEADERS=signoz-ingestion-key=<your-ingestion-key>
ENV OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
ENV OTEL_METRICS_EXPORTER=none

Or pass them at runtime using docker run:

docker run -e OTEL_RESOURCE_ATTRIBUTES="service.name=<service-name>" \
    -e OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443" \
    -e OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>" \
    -e OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" \
    -e OTEL_METRICS_EXPORTER="none" \
    your-image:latest

The bootstrap command (Step 3) installs instrumentations for all detected libraries, including HTTP clients like requests, urllib3, and httpx. These libraries generate metrics such as request duration histograms and optionally request/response body sizes for every outgoing HTTP call.

Since opentelemetry-distro enables metrics by default, these HTTP metrics would be sent to SigNoz even though this guide only covers traces. For apps that make frequent HTTP calls, this can add up quickly.

Setting this to none disables metrics while keeping traces working as expected. If you want metrics later, you can change it to otlp or remove this variable altogether.

Verify these values:

  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service-name>: A descriptive name for your service (e.g., payment-service).

Step 2. Install OpenTelemetry packages

pip install opentelemetry-distro opentelemetry-exporter-otlp

Step 3. Install instrumentation for your dependencies

This command detects your installed packages and adds the corresponding instrumentation libraries:

opentelemetry-bootstrap --action=install

Run this after installing all your application dependencies. It will only instrument packages that are already installed.

Step 4. Run your application

opentelemetry-instrument <your_run_command>

See Framework instrumentation below for framework-specific commands.

Framework instrumentation

Choose your framework below to see the specific run command. The setup steps above are the same for all frameworks.

Web Frameworks

Django

Prerequisites

Set the DJANGO_SETTINGS_MODULE environment variable:

export DJANGO_SETTINGS_MODULE=myproject.settings

Run command

opentelemetry-instrument python manage.py runserver --noreload

Always use --noreload with Django. The auto-reload mechanism spawns child processes that break OpenTelemetry instrumentation.

CMD ["opentelemetry-instrument", "python", "manage.py", "runserver", "0.0.0.0:8000", "--noreload"]

Running with Gunicorn or uWSGI

Gunicorn works out of the box. No extra setup needed unless you use the --preload flag. If you do use --preload, see the post_fork hook example.

uWSGI requires one of these options:

  • Add lazy-apps = true to your uWSGI config (recommended, simplest fix)
  • Or implement a post_fork hook (see example)

OpenTelemetry's span exporter uses a background thread. When a server forks worker processes, this thread doesn't copy over correctly, causing spans to get stuck.

Gunicorn loads your app in each worker after forking (so the thread starts fresh). With --preload, it loads before forking, causing the same issue.

uWSGI loads your app before forking by default. Setting lazy-apps = true makes it load after forking instead.

Validate

With your application running, verify traces are being sent to SigNoz:

  1. Trigger an action in your app that generates a web request. Hit the endpoint a few times.
  2. In SigNoz, open the Services tab and click Refresh. Your application should appear.
  3. Go to the Traces tab to see your application's traces.

Troubleshooting

Why don't traces appear in SigNoz?

Check environment variables are set:

echo $OTEL_EXPORTER_OTLP_ENDPOINT
echo $OTEL_RESOURCE_ATTRIBUTES

Verify network connectivity:

# For SigNoz Cloud
curl -v https://ingest.<region>.signoz.cloud:443/v1/traces

Enable console exporter to verify spans are being created:

OTEL_TRACES_EXPORTER=console opentelemetry-instrument <your_run_command>

If you see JSON span output in your terminal but traces don't appear in SigNoz, the issue is with export configuration (endpoint, auth, or network). If no output appears, the instrumentation isn't capturing your requests.

Why do multi-worker servers (Uvicorn, Gunicorn) drop spans?

Application servers that spawn multiple worker processes require special handling because the OpenTelemetry SDK isn't fork-safe.

  • Uvicorn with --workers flag is not supported. Use Gunicorn with Uvicorn workers instead:
    opentelemetry-instrument gunicorn -k uvicorn.workers.UvicornWorker main:app
    
  • Hypercorn/Unicorn are not supported due to fork-safety issues. See the Hypercorn/Unicorn tab for details and workarounds.
  • Gunicorn with --preload or uWSGI need extra config. See Running with Gunicorn or uWSGI.

Hot reload breaks instrumentation

Don't run your app in reloader/hot-reload mode. For Flask, avoid FLASK_ENV=development. For Django, use --noreload. For Uvicorn/FastAPI, don't use --reload.

Database calls not showing in traces

Auto-instrumentation detects and instruments common database libraries. Ensure you've run opentelemetry-bootstrap --action=install after installing your database drivers.

PostgreSQL note: psycopg2 is preferred over psycopg2-binary for auto-instrumentation. If you must use psycopg2-binary, you may need to use manual instrumentation with Psycopg2Instrumentor().instrument(skip_dep_check=True).

Common database instrumentations installed by bootstrap:

  • PostgreSQL: opentelemetry-instrumentation-psycopg2
  • MySQL: opentelemetry-instrumentation-pymysql or opentelemetry-instrumentation-mysql
  • MongoDB: opentelemetry-instrumentation-pymongo
  • Redis: opentelemetry-instrumentation-redis
  • SQLAlchemy: opentelemetry-instrumentation-sqlalchemy

Check supported versions for compatibility with your library versions.

Setup OpenTelemetry Collector (Optional)

What is the OpenTelemetry Collector?

Think of the OTel Collector as a middleman between your app and SigNoz. Instead of your application sending data directly to SigNoz, it sends everything to the Collector first, which then forwards it along.

Why use it?

  • Cleaning up data — Filter out noisy traces you don't care about, or remove sensitive info before it leaves your servers.
  • Keeping your app lightweight — Let the Collector handle batching, retries, and compression instead of your application code.
  • Adding context automatically — The Collector can tag your data with useful info like which Kubernetes pod or cloud region it came from.
  • Future flexibility — Want to send data to multiple backends later? The Collector makes that easy without changing your app.

See Switch from direct export to Collector for step-by-step instructions to convert your setup.

For more details, see Why use the OpenTelemetry Collector? and the Collector configuration guide.

Next steps

  • Add manual instrumentation for custom spans and attributes
  • Send logs from Python using auto-instrumentation
  • Send metrics from Python to correlate traces with metrics for better observability
  • Set up alerts for your Python application
  • Create dashboards to visualize metrics

Sample applications:

  • Django sample app
  • Flask sample app
  • FastAPI sample app

Last updated: May 18, 2026

Edit on GitHub

Was this page helpful?

Your response helps us improve this page.

Prev
Send Traces and APM Data
Next
Manual Instrumentation
On this page
Prerequisites
Send traces to SigNoz
Step 1. Set environment variables
Step 2. Install OpenTelemetry packages
Step 3. Install instrumentation for your dependencies
Step 4. Run your application
Step 1. Set environment variables
Step 2. Install OpenTelemetry packages
Step 3. Install instrumentation for your dependencies
Step 4. Run your application
Step 1. Set up the OpenTelemetry Operator
Step 2. Create the Instrumentation resource
Step 3. Add annotations to your deployment
Step 1. Set environment variables
Step 2. Install OpenTelemetry packages
Step 3. Install instrumentation for your dependencies
Step 4. Run your application
Step 1. Set environment variables in Dockerfile
Step 2. Install OpenTelemetry packages
Step 3. Install instrumentation for your dependencies
Step 4. Run your application
Framework instrumentation
Running with Gunicorn or uWSGI
Validate
Troubleshooting
Why don't traces appear in SigNoz?
Why do multi-worker servers (Uvicorn, Gunicorn) drop spans?
Hot reload breaks instrumentation
Database calls not showing in traces
Setup OpenTelemetry Collector (Optional)
What is the OpenTelemetry Collector?
Why use it?
Next steps

Is this page helpful?

Your response helps us improve this page.