Integration · Python

Python monitoring and APM

Run your app with opentelemetry-instrument and Obseria shows traces, errors and runtime metrics for Django, Flask, FastAPI and Celery services, correlated with logs and infrastructure.
Obseria apps and capabilities: observability, APM, infrastructure and integrations
Obseria home dashboard with service health, open problems, SLO compliance and ingestion
Obseria trace explorer with span list and span attributes
Overview

Why monitor Python with Obseria

Zero-code start

opentelemetry-bootstrap detects installed libraries and installs the matching instrumentations; opentelemetry-instrument activates them at startup.

Web apps and workers in one trace

Requests, Celery tasks and outbound calls are linked, so background work is no longer a blind spot.

Errors with context

Exceptions are recorded on spans with stack traces, request attributes and the release that introduced them.

Coverage

Python frameworks and libraries Obseria monitors

  • Django. Views, middleware and ORM queries are traced with route templates and status codes.
  • Flask and FastAPI. WSGI and ASGI apps get server spans per endpoint, including async handlers.
  • Celery. Task publish and execution spans connect producers, brokers and workers.
  • requests, httpx, urllib3 and aiohttp. Outbound HTTP calls propagate W3C trace context.
  • psycopg, SQLAlchemy, PyMySQL and redis-py. Database and cache operations appear as client spans with duration.
  • boto3 and botocore. AWS SDK calls are traced, including service and operation names.
At a glance

The Python signals that matter

Obseria collects these values automatically and shows them in ready-made dashboards and alerts.

Response speed and demand

Shows how quickly your Python services answer and how many requests they are handling at the same time.

  • http.server.request.duration
  • http.server.active_requests

Dependency speed

Tells you how long your application waits for other services and partners, revealing slow external dependencies.

  • http.client.request.duration

Resource usage

Reveals how much processing power and memory your application consumes, helping you size servers and control costs.

  • process.runtime.cpython.cpu.utilization
  • process.runtime.cpython.memory

Internal workload

Shows how often the application cleans up memory and juggles parallel tasks, both hidden causes of slowdowns.

  • process.runtime.cpython.gc_count
  • process.runtime.cpython.thread_count
  • process.runtime.cpython.context_switches
Show all 8 metrics in detail
MetricUnitWhat it tells you
http.server.request.durationsLatency of inbound requests per route and status code.
http.server.active_requests{request}Requests in flight; growth with flat throughput means requests are stuck.
http.client.request.durationsLatency of outbound HTTP calls to downstream services.
process.runtime.cpython.cpu.utilization1CPU usage of the Python process, often capped at one core by the GIL.
process.runtime.cpython.memoryByResident and virtual memory of the interpreter process.
process.runtime.cpython.gc_count{count}Garbage collections per generation.
process.runtime.cpython.thread_count{thread}Active threads in the process.
process.runtime.cpython.context_switches{switch}Voluntary and involuntary context switches, a hint for contention.
Setup

Set up Python monitoring in minutes

  1. Step 1

    Install the distro

    pip install opentelemetry-distro and the OTLP exporter, then run opentelemetry-bootstrap to add instrumentations for your libraries.

  2. Step 2

    Configure via environment

    Set OTEL_SERVICE_NAME, the Obseria OTLP endpoint and your token.

  3. Step 3

    Wrap the start command

    Prefix your usual command with opentelemetry-instrument, for example for Gunicorn or Uvicorn.

Example configuration · BASH
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install

export OTEL_SERVICE_NAME="billing-api"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment.name=production"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_LOGS_EXPORTER="otlp"
export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED="true"
export OTEL_EXPORTER_OTLP_ENDPOINT="${OBSERIA_OTLP_ENDPOINT}"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20${OBSERIA_TOKEN}"

opentelemetry-instrument uvicorn app.main:app --host 0.0.0.0 --port 8000

Out of the box

Dashboards, alerts and SLOs that are ready the moment data arrives.

  • Python service health with RED metrics
  • Celery tasks: throughput, failures, duration
  • Alert on p95 latency per endpoint
  • Alert on new exception types after deploy
  • Slowest database queries by service
Guide

Python monitoring: what matters

Why Python monitoring matters

Python runs web APIs with Django, Flask and FastAPI, data pipelines, machine learning services and countless background workers built on Celery. These workloads have different performance profiles: a synchronous Django app scales with worker processes, a FastAPI service relies on an async event loop, and a Celery worker depends on broker health. Python monitoring has to cover all three and connect them, because a slow API response is often caused by a queue or a database call further down.

OpenTelemetry provides zero-code instrumentation for Python. The opentelemetry-bootstrap command inspects your installed packages and adds the matching instrumentation libraries, and opentelemetry-instrument activates them when the interpreter starts. That makes Python APM possible without touching application code.

Signals that matter for Python performance monitoring

  • Request latency and errors: http.server.request.duration per route, plus exceptions recorded on spans, give the RED view per service.
  • Concurrency: http.server.active_requests shows requests in flight. If it climbs while throughput stays flat, workers are blocked.
  • CPU and the GIL: process.runtime.cpython.cpu.utilization close to one core per process means CPU-bound code that more threads will not fix.
  • Memory and GC: process.runtime.cpython.memory and process.runtime.cpython.gc_count reveal leaks and allocation-heavy code paths.
  • Dependencies: client spans for databases, caches and HTTP APIs show where request time actually goes.

Common Python performance problems

Blocking calls in async code

A synchronous database driver or time.sleep inside an async def handler blocks the event loop of a FastAPI or aiohttp service. All requests on that worker slow down at once. Traces show long gaps without child spans; profiles show the blocking function.

Worker exhaustion

Gunicorn or uWSGI run a fixed number of workers. When slow upstream calls occupy them, new requests wait in the backlog. Rising active requests and timeouts at the load balancer are the typical signs.

N+1 queries in ORMs

Django ORM and SQLAlchemy make it easy to issue one query per row. Trace waterfalls with dozens of identical SQL spans make the problem obvious, and the fix is usually select_related or eager loading.

Memory growth in long-running workers

Celery workers and data jobs that hold references to large objects grow until the operating system kills them. Memory per process over time, together with task duration, shows which task is responsible.

Silent task failures

Background tasks that fail and retry quietly hide problems from users until data is missing. Tracing task execution with error status makes failures and retries visible next to the request that enqueued them.

Slow cold paths after deployment

Python imports modules lazily, and frameworks warm caches on first use. The first requests per worker after a rollout can be much slower. Comparing latency per service.version separates warm-up from real regressions.

Best practices for Python APM

  1. Run opentelemetry-bootstrap in your build so the instrumentation set matches your dependencies.
  2. With pre-fork servers such as Gunicorn, initialize OpenTelemetry in each worker as described in the OpenTelemetry Python documentation.
  3. Enable logging instrumentation to add trace IDs to log records.
  4. Add custom spans for expensive business steps, for example model inference or report generation.
  5. Use tail-based sampling to keep all failed and slow traces while dropping routine traffic.

How Obseria helps with Python monitoring

Obseria ingests OpenTelemetry traces, metrics and logs from Python over OTLP, so you keep open instrumentation and can export your data at any time. The Obseria Agent adds host and container context and runs as a DaemonSet on Kubernetes. TopoGraph shows how APIs, Celery workers, brokers and databases depend on each other. Continuous profiling with under 1% overhead identifies hot functions. When errors spike after a release, Obseria Intelligence correlates the deployment, the failing dependency and the affected endpoints and explains the root cause with its chain of evidence. Dashboards, alerts and SLOs are included.

Python monitoring FAQ

No. opentelemetry-instrument activates instrumentation for supported libraries at startup. Custom spans with the OpenTelemetry API are optional.

Django, Flask, FastAPI, Starlette, Celery and many clients such as requests, httpx, psycopg, SQLAlchemy, redis-py and boto3 have official OpenTelemetry instrumentations.

Yes. Wrap the start command with opentelemetry-instrument. For Gunicorn with pre-forked workers, follow the post-fork initialization pattern from the OpenTelemetry Python documentation.

Yes. The Celery instrumentation creates spans for publishing and executing tasks and propagates context through the broker, so the task appears in the trace of the request that enqueued it.

Yes. With logging instrumentation enabled, log records carry trace and span IDs, and Obseria links each log line to its trace.

Start monitoring Python today

Connect Python in minutes with OpenTelemetry or the Obseria Agent. Free for 14 days.