Metadata-Version: 2.5
Name: aspirator
Version: 0.1.1
Summary: Aspirator SDK for Python
Author-email: Rudra Narayan Gupta <rudra9506@gmail.com>
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# aspirator

Python SDK for Aspirator, a minimal
self-hosted error tracker. **Zero dependencies**, deliberately — an error
tracker that drags in a dependency tree is one more thing that can break the
app it is meant to be watching.

You need an Aspirator server to report to. This package on its own does
nothing.

## Install

```sh
pip install aspirator      # or: uv add aspirator
```

## Use

```python
import aspirator

aspirator.init()   # reads ASPIRATOR_DSN, ASPIRATOR_RELEASE, ASPIRATOR_ENVIRONMENT

try:
    charge(order)
except PaymentError as exc:
    aspirator.capture_exception(exc)
```

`capture_exception` also takes a plain string, for a problem you detected
rather than caught. It is reported as an issue like any other, named and
grouped by its text:

```python
if not rows:
    aspirator.capture_exception("verifier returned no rows", level="warning")
```

`init()` also installs interpreter-level hooks, so a crash in a thread, an
unretrieved `asyncio` task or a bare script is reported even where no framework
wraps it.

## Frameworks

```python
from aspirator.integrations import django as aspirator_django

aspirator.init(integrations=[aspirator_django])
```

Django, FastAPI/Starlette and Celery are supported, plus a `logging`
integration that forwards log lines and builds breadcrumbs. No middleware entry
is needed for any of them — each patches the point that sits outside the whole
chain, because middleware only ever sees what is raised below it.

## Running under uvicorn? Flush on shutdown

```python
@contextlib.asynccontextmanager
async def lifespan(app):
    yield
    aspirator.close()

app = FastAPI(lifespan=lifespan)
```

Events are sent by a background thread, and whatever it has not sent yet is
flushed at exit. But `docker stop` sends `SIGTERM`, and SIGTERM kills a Python
process **without unwinding** — so `atexit` never runs, and under uvicorn that
loses the queue and the open metrics window on every deploy.

gunicorn does not need this (its worker exits normally) and neither does Celery
(the integration is wired to the shutdown signals). It is uvicorn specifically,
and all three were measured.

## Also

Metrics (`increment`, `gauge`, `timing`), cron check-ins, breadcrumbs, request
capture, and credential scrubbing by key. Options are typed — the package ships
`py.typed`.

## Licence

MIT. Portions derived from [sentry-python](https://github.com/getsentry/sentry-python)
(MIT); see `LICENSE`.
