Skip to main content

condux (Python SDK)

Report errors from a Python app to a Condux relay. Emits the Sentry "store" wire shape, so the relay normalizes it exactly like an official Sentry SDK — point it at a project DSN and it works.

Delivery is resilient (429 / 5xx / network failures retry with backoff, honoring Retry-After) and never raises — a failed send returns a SendResult, it does not crash the host app. That holds even if init was never called: capture warns once and drops the event, because the middleware below report from inside an except block and an SDK that raised there would replace your application's exception with its own. A malformed DSN is refused by init instead, where it is a developer-time mistake.

Install

pip install condux

Usage

import condux

condux.init(
    dsn="https://<key>@ingest.condux.ai/<projectId>",
    environment="production",
    release="1.4.2",
)

try:
    do_work()
except Exception as error:
    condux.capture_exception(error)
    raise

# or a bare message
condux.capture_message("cache miss storm", condux.Level.WARNING)

Verify your setup

Silence is what a broken error monitor and a healthy app look like from the outside, so prove the pipeline once:

CONDUX_DSN="https://<key>@ingest.condux.ai/<projectId>" python -m condux.test_event

Exit code 0 means delivered (the message appears as an info-level issue), 1 means delivery failed and prints why, 2 means the DSN was missing or malformed.

Enrichment

Attach the ambient facts triage always needs. Every subsequent event carries them, so nothing has to be threaded through capture calls:

condux.set_user({"id": "1042", "email": "dev@example.com"})   # None clears it (sign-out)
condux.set_tag("plan", "team")                                 # None removes the tag
condux.set_context("job", {"queue": "billing", "attempt": 3})  # None removes the context
condux.add_breadcrumb("charge.started", category="billing")

The breadcrumb trail keeps the most recent 30 entries. condux.clear_scope() resets everything.

In a server, scope one request at a time

Those calls are process wide by default, which is right for facts about the deployment and wrong for facts about one request: a server handles requests concurrently, so a bare set_user in a view can attach that user to a different request's error. That is worse than reporting no user, because it is confidently wrong.

request_scope() isolates it. Anything set inside belongs to that request alone, layered over the process-wide values:

with condux.request_scope():
    condux.set_user({"id": user.id})   # this request only
    handle(request)

The framework integrations do this for you, so a set_user inside a Flask, Django, FastAPI or Starlette view is already isolated. Call it directly for background jobs and consumers, which have the same problem: many in flight at once, each wanting its own identity on its own events. It is built on contextvars, so one mechanism covers threads and asyncio.

Detail belonging to a single event can also skip the scope entirely:

condux.capture_exception(error, request={"url": "/api/sync"}, tags={"job": "nightly"})

Framework integrations

Each reports an uncaught request exception as unhandled, with the request and the matched route, and isolates enrichment to that request.

# Flask
from condux.integrations.flask import ConduxFlask
ConduxFlask(app)

# Django: add to MIDDLEWARE in settings.py
MIDDLEWARE = ["condux.integrations.django.ConduxMiddleware", ...]

# FastAPI / Starlette
from condux.integrations.asgi import ConduxAsgiMiddleware
app = ConduxAsgiMiddleware(app)

Flask and Django need their own integrations, not the WSGI one. Both catch a view exception, convert it to a 500 and return it, so nothing propagates out of the application. A WSGI middleware wraps the application from the outside and would therefore never see the exception at all: it reports zero events, silently, with nothing to tell you it is not working. ConduxFlask and ConduxMiddleware hook got_request_exception instead, which is the signal each framework actually fires.

ConduxWsgiMiddleware remains correct for a bare WSGI application, or any framework that lets exceptions escape:

from condux.integrations.wsgi import ConduxWsgiMiddleware
application = ConduxWsgiMiddleware(my_wsgi_app)

Develop

pip install -e .
python -m unittest discover -s tests

Zero runtime dependencies (standard library only). The transport and sleep are injectable, so the tests exercise the retry/backoff with no real network or timers.

Metadata

Release files for condux 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for condux 0.2.1
File Size Uploaded
condux-0.2.1.tar.gz 34.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for condux 0.2.1
File Interpreter ABI Platform
condux-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 64.3 kB

Release files / condux-0.2.1.tar.gz

Download URL condux-0.2.1.tar.gz
Size 34.7 kB
Tags Source
SHA-256 checksum
How to use checksums
1287e403146270adb77561471f563ceb6b4042d7964a87d514c6aa3c3aa706f6
BLAKE2b-256 checksum
How to use checksums
f24c3eafb7c950a12d73136b60c2eb59d06645d7fae9337f88f4f62f403bcc3d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / condux-0.2.1-py3-none-any.whl

Download URL condux-0.2.1-py3-none-any.whl
Size 29.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b40aed8682fe333732b7bbeb1ffaeddd65e41257241707c450dc9fe66225f64
BLAKE2b-256 checksum
How to use checksums
5388f6a2838cbc1156e1d58b2f53e75fb145aecef1710d591ca2b68cc02075f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page