Incidentary Docs

Python

Instrument your Python services with the Incidentary SDK.

Python Quickstart

This guide gets you from zero to your first captured trace in a Python application.

Prerequisites

  • Python 3.11+
  • An Incidentary workspace and API key (from the dashboard under Settings → API Keys)

Install

pip install incidentary-sdk

Initialize the client

import os
from incidentary import IncidentaryClient

client = IncidentaryClient(
    api_key=os.environ["INCIDENTARY_API_KEY"],
    service_name="my-service",
)

That's the core setup. The SDK automatically patches outbound HTTP libraries (urllib, requests, httpx, aiohttp), supported queue systems, and databases — no additional code needed.

Inbound middleware

Django — automatic

The SDK auto-injects middleware into settings.MIDDLEWARE at startup. No code changes needed — just initialize the client and Django requests are captured.

Flask — automatic

The SDK auto-wraps Flask.wsgi_app for any Flask app created after client initialization. No manual wrapping needed.

FastAPI / Starlette (ASGI)

from incidentary import IncidentaryASGIMiddleware

app.add_middleware(IncidentaryASGIMiddleware, client=client)

Other WSGI frameworks

from incidentary import IncidentaryWSGIMiddleware

app = IncidentaryWSGIMiddleware(app, client)

The middleware captures every inbound HTTP request automatically and is non-blocking.

Outbound HTTP — automatic

The SDK patches urllib.request.urlopen, requests.Session.send, httpx.HTTPTransport.handle_request, and aiohttp.ClientSession._request at initialization. Every outbound HTTP call automatically gets trace headers injected.

No code changes needed. If OpenTelemetry has already patched a library, the SDK detects it and skips its own patching.

Queue instrumentation — automatic

LibraryWhat's instrumented
Celerybefore_task_publish, task_prerun, task_postrun signals — no monkey-patching
kombuProducer.publish — header injection for RabbitMQ/AMQP

Celery tasks automatically propagate trace context through task headers. The consumer side sets trace context before your task runs and clears it after.

Database instrumentation — automatic

LibraryWhat's captured
psycopg2cursor.execute / executemany — SQL text (truncated to 500 chars, no parameters)
asyncpgConnection.execute / fetch / fetchval / fetchrow

Database events appear as INTERNAL context events in the trace.

gRPC support

from incidentary import GrpcIntegration

grpc_integration = GrpcIntegration()
grpc_integration.patch(client)

# Client-side: intercept outbound gRPC calls
channel = grpc.intercept_channel(
    grpc.insecure_channel('localhost:50051'),
    grpc_integration.client_interceptor(),
)

# Server-side: intercept inbound gRPC calls
server = grpc.server(
    futures.ThreadPoolExecutor(),
    interceptors=[grpc_integration.server_interceptor()],
)

Recording custom events

Queue, job, and webhook events can also be recorded manually:

from incidentary.types import RecordEventOptions

client.record_queue_publish(RecordEventOptions(event_attrs={"topic": "orders.created"}))
client.record_queue_consume()
client.record_job_start(RecordEventOptions(parent_ce_id=parent_id))
client.record_job_end()
client.record_webhook_in()
client.record_webhook_out(RecordEventOptions(status=202))

Environment variables

VariableRequiredDefaultDescription
INCIDENTARY_API_KEYYesWorkspace API key (sk_...) from the dashboard
INCIDENTARY_SERVICE_NAMENoAlternative to passing service_name in code
INCIDENTARY_ENVIRONMENTNoproductionEnvironment label
INCIDENTARY_API_URLNohttps://api.incidentary.comOverride for self-hosted or local dev

Verify capture

After deploying with the SDK installed:

  1. Make a request to your service
  2. Open the Incidentary dashboard → Traces
  3. A trace should appear within a few seconds

Debugging

Check the SDK state with:

state = client.get_prearm_debug_state()
print(state)

This shows trigger counters, in-flight request counts, retry patterns, and whether the SDK is in a normal or elevated capture mode. Useful when diagnosing why events are or are not appearing.

Troubleshooting

401 from ingest: Verify your API key is a workspace key (sk_...), not a user token.

No CEs visible: Confirm the WSGI middleware is wrapping your application, not just imported.

426 version rejection: Upgrade to incidentary==0.2.0 or newer.

No module named incidentary: If testing locally with an editable install, ensure PYTHONPATH=src.

On this page