Python SDK
Full observability for Python — databases, HTTP, frameworks, messaging, and logging captured automatically via OpenTelemetry
Built on OpenTelemetry
The Python SDK is a thin wrapper that configures OpenTelemetry with the Obtrace ingest endpoint. It includes every OTel auto-instrumentation for Python with zero extra code.
Installation
All OpenTelemetry auto-instrumentations are included by default.
Setup
Import this module early in your app. That's it.
What's Captured Automatically
With obtrace-sdk-python, the SDK enables all available OpenTelemetry instrumentations for your installed packages:
| What | How | Needs code? |
|---|---|---|
| All stdlib logging | logging.Handler auto-installed on init | No |
| Outbound HTTP | requests, httpx, urllib3, aiohttp instrumented via OTel | No |
| Inbound HTTP | django, flask, fastapi instrumented via OTel (no middleware needed) | No |
| Databases | psycopg2, asyncpg, sqlalchemy, pymongo instrumented when installed | No |
| Redis | redis-py instrumented via OTel | No |
| Task queues | celery tasks instrumented with spans | No |
| gRPC | grpcio client and server calls instrumented | No |
| AWS | boto3 calls instrumented via OTel | No |
| Process shutdown flush | atexit handler registered | No |
Every logging.info("..."), logging.warning("..."), logging.error("...") in your application (and libraries) is captured and sent to Obtrace as structured logs.
Outbound HTTP, database queries, cache operations, and task queue jobs are all automatically traced with method, URL/query, status, and duration. Trace context (traceparent header) is injected into outbound requests so downstream services can correlate traces.
Opting Out of Auto HTTP Instrumentation
FastAPI / Flask Middleware
With obtrace-sdk-python, inbound HTTP instrumentation is automatic via OpenTelemetry. No middleware registration is needed for Django, Flask, or FastAPI.
The explicit middleware still works if you prefer manual control:
Logging
Use client.log(level, message, context?) to record events you need to search for later. Good candidates:
- Caught exceptions and error conditions
- Business events (order placed, payment failed, user signed up)
- Audit trail entries (permission changed, API key rotated)
- State transitions (circuit breaker opened, cache invalidated)
The level parameter accepts: debug, info, warn, error, fatal. Messages are truncated at 32KB.
The context parameter is optional. When provided, it attaches structured attributes to the log entry. Use attrs for custom key-value pairs, and the built-in fields (trace_id, span_id, method, endpoint, status_code) to correlate logs with traces.
Metrics
Use client.metric(name, value, unit?, context?) to record measurements you want to graph or alert on. Good candidates:
- Latency measurements (how long did this take?)
- Counters (how many orders per minute?)
- Gauges (current queue depth, active connections)
- Business KPIs (revenue per checkout, items per cart)
The unit parameter defaults to "1". Follow OTLP conventions: "ms" for milliseconds, "By" for bytes, "1" for dimensionless values (counts, ratios), or a currency code.
Tracing / Spans
Use client.span(...) to track a unit of work and its duration. Returns a dict with trace_id and span_id so you can propagate context to downstream services. Good candidates:
- HTTP handler execution (request in, response out)
- Database queries
- External API calls
- Background task processing
- Any operation where you need to see where time was spent
Omit trace_id and span_id to auto-generate them. Pass an existing trace_id to group spans into the same trace. The status_code uses OTLP conventions: 0 = unset, 1 = OK, 2 = error.
Propagating Trace Context
Trace context is injected automatically on outbound requests and httpx calls. For other HTTP clients, inject manually:
Framework Integration
FastAPI
The middleware emits one span (http.server METHOD) and one log per request, with method, route, status code, and duration attached.
Flask
Django
Configuration Reference
| Field | Type | Default | Description |
|---|---|---|---|
api_key | str | Required. Your Obtrace API key. | |
service_name | str | Required. Stable name for this service. | |
service_version | str | "0.0.0" | Deployment version (git SHA, semver, date). |
tenant_id | str | None | Scoped ingest identity. |
project_id | str | None | Scoped ingest identity. |
app_id | str | None | Scoped ingest identity. |
env | str | None | Environment name (prod, staging, dev). |
auto_instrument_http | bool | True | Patch requests and httpx with automatic spans and trace propagation. |
request_timeout_sec | float | 5.0 | HTTP timeout per OTLP request in seconds. |
max_queue_size | int | 1000 | Max queued telemetry items before oldest are dropped. |
validate_semantic_metrics | bool | False | When True + debug, warns on non-canonical metric names. |
debug | bool | False | Enables SDK diagnostic output to stderr. |
default_headers | dict | {} | Extra headers sent with every OTLP request. |
Validation Checklist
After integrating the SDK, verify these before shipping to production:
-
service_name,env, andservice_versionare set and survive restarts and deploys - At least one request path emits both a log and a span
-
client.flush()is called before process exit, or you use the context manager - No
401or403errors appear during OTLP submission (check withdebug=True) - Metrics use correct units (
ms,By,1) not free-form strings - Outbound HTTP calls show auto-generated spans (or use
inject_propagationmanually if auto HTTP is disabled) - Database queries (psycopg2, sqlalchemy, etc.) show auto-generated spans when using
obtrace-sdk-python - FastAPI/Flask/Django requests are auto-instrumented via OTel (explicit middleware is optional)
See also: Semantic Metrics