Metadata-Version: 2.4
Name: booboo-sdk
Version: 0.14.0
Summary: Lightweight error tracking for Python
Author-email: "booboo.dev" <hello@booboo.dev>
License-Expression: MIT
Project-URL: Homepage, https://booboo.dev
Project-URL: Repository, https://github.com/getbooboo/python
Project-URL: Issues, https://github.com/getbooboo/python/issues
Project-URL: Changelog, https://github.com/getbooboo/python/blob/main/CHANGELOG.md
Keywords: error-tracking,monitoring,debugging,exceptions,booboo
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Bug Tracking
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.20
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Dynamic: license-file

# booboo-sdk

[![CI](https://github.com/getbooboo/python/actions/workflows/ci.yml/badge.svg)](https://github.com/getbooboo/python/actions/workflows/ci.yml)
[![PyPI version](https://img.shields.io/pypi/v/booboo-sdk.svg)](https://pypi.org/project/booboo-sdk/)
[![Python versions](https://img.shields.io/pypi/pyversions/booboo-sdk.svg)](https://pypi.org/project/booboo-sdk/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

Official Python SDK for [booboo.dev](https://booboo.dev) error tracking.

## Installation

```bash
pip install booboo-sdk
```

## Quick Start

```python
import booboo

booboo.init("https://YOUR_TOKEN@ingest.booboo.dev/your-org/your-project")
```

That's it. Unhandled exceptions are automatically captured and sent to booboo.dev.

The DSN is a URL — the SDK parses out the ingest host so you don't need to configure an endpoint separately. Bare tokens (e.g. `"abc123..."`) are also accepted for back-compat with older dashboards.

## Manual Capture

```python
try:
    risky_operation()
except Exception:
    booboo.capture_exception()  # captures the current exception
```

Or pass an exception explicitly:

```python
try:
    risky_operation()
except Exception as e:
    booboo.capture_exception(e)
```

## User Context

```python
booboo.set_user({
    "id": "123",
    "email": "user@example.com",
    "username": "alice",
})
```

## Framework Integration

### Django

Auto-detected — no extra setup needed. The SDK injects middleware and patches Django's internal exception handler to capture errors that never reach middleware (like `DisallowedHost`). 404 errors are filtered by default.

### Flask

```python
from flask import Flask
import booboo

app = Flask(__name__)
booboo.init("https://YOUR_TOKEN@ingest.booboo.dev/your-org/your-project", app=app)
```

Or without passing `app` — the SDK monkey-patches `Flask.__init__` to auto-register on any Flask app created after `init()`. 404 errors are filtered by default.

### FastAPI

```python
from fastapi import FastAPI
import booboo

app = FastAPI()
booboo.init("https://YOUR_TOKEN@ingest.booboo.dev/your-org/your-project", app=app)
```

Same auto-detection as Flask if `app` is not passed explicitly.

## Configuration

```python
booboo.init(
    dsn="https://YOUR_TOKEN@ingest.booboo.dev/your-org/your-project",
    environment="production",
    ignore_errors=[KeyboardInterrupt, ConnectionError],
)
```

| Parameter | Default | Description |
|-----------|---------|-------------|
| `dsn` | (required) | Your project's DSN from booboo.dev |
| `app` | `None` | Flask/FastAPI app instance for explicit registration |
| `environment` | `""` | Environment name (e.g. `"production"`, `"staging"`). Attached to every event. |
| `ignore_errors` | `None` | List of exception classes to suppress. Uses `isinstance()` so subclasses are matched. |
| `endpoint` | derived from DSN URL, or `https://ingest.booboo.dev/` | Override the ingest endpoint. Normally unnecessary — the SDK derives it from the DSN URL automatically. |
| `before_send` | `None` | Hook called with the event dict before every send. Return the (possibly modified) event, or `None` to drop it. If the hook raises, the event is dropped. |

## before_send Hook

Use `before_send` to inspect or modify events before they leave your server, or to drop
them entirely. The SDK already scrubs sensitive variables *by name* (`password`, `token`,
…), but only your code knows which *values* are sensitive — use `before_send` for
value-level scrubbing such as IBANs, payment references, or emails inside variable values:

```python
import re

IBAN_RE = re.compile(r"\b[A-Z]{2}\d{2}[A-Z0-9]{10,30}\b")

def scrub_ibans(event):
    # Frames live on the top-level stacktrace and on each chained exception
    all_frames = list(event.get("stacktrace", []))
    for exc in event.get("exceptions", []):
        all_frames.extend(exc.get("stacktrace", []))
        exc["value"] = IBAN_RE.sub("[iban]", exc.get("value", ""))
    for frame in all_frames:
        for name, value in frame.get("vars", {}).items():
            frame["vars"][name] = IBAN_RE.sub("[iban]", value)
    event["message"] = IBAN_RE.sub("[iban]", event.get("message", ""))
    return event  # return None instead to drop the event

booboo.init(
    dsn="https://YOUR_TOKEN@ingest.booboo.dev/your-org/your-project",
    before_send=scrub_ibans,
)
```

The hook receives every event (exceptions and `capture_message()` calls alike) and runs on
the SDK's background sender thread, so it never adds latency to your request path.

## Features

- Automatic capture of unhandled exceptions
- Rich stack traces with source context and local variables
- Exception chain support (`raise ... from ...`)
- PII scrubbing for sensitive headers and variables
- Django, Flask, and FastAPI integrations
- Non-blocking event delivery
- Graceful shutdown flush
- Minimal dependency footprint (`requests` only)

## License

MIT
