Metadata-Version: 2.4
Name: watchdock-errors
Version: 0.3.0
Summary: Application error tracking SDK for the Watchdock platform
License: MIT
Keywords: error-tracking,observability,watchdock
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28
Provides-Extra: django
Requires-Dist: django>=3.2; extra == "django"
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.95; extra == "fastapi"
Requires-Dist: starlette>=0.27; extra == "fastapi"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-mock>=3.0; extra == "dev"
Requires-Dist: responses>=0.23; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"

# watchdock-errors

Python SDK for application-level error tracking on the [Watchdock](https://watchdock.cc) platform.

## Installation

```bash
pip install watchdock-errors
```

With framework extras:

```bash
pip install "watchdock-errors[django]"
pip install "watchdock-errors[fastapi]"
```

## Quickstart

```python
import watchdock_errors

watchdock_errors.init(
    api_key="wdk_xxx",
    environment="production",
    release="1.0.0",
)
```

### Django

```python
# settings.py
MIDDLEWARE = [
    ...
    "watchdock_errors.integrations.django.DjangoErrorMiddleware",
]
```

Or via `INSTALLED_APPS` for automatic registration:

```python
INSTALLED_APPS = [
    ...
    "watchdock_errors.integrations.django",
]
```

### FastAPI

```python
from watchdock_errors.integrations.fastapi import setup_watchdock

setup_watchdock(app)
```

## Manual capture

```python
# Capture the current exception
try:
    process_payment()
except Exception:
    watchdock_errors.capture_exception()

# Capture a specific exception
watchdock_errors.capture_exception(exc)

# Capture a message
watchdock_errors.capture_message("Stripe webhook signature invalid")

# Capture a message with a custom level
watchdock_errors.capture_message("Queue depth high", level="warning")
```

### Event levels

Every event carries a `level`. Exceptions default to `"error"`; messages default to `"info"` unless you pass `level` explicitly to `capture_message`.

## Correlating with nginx requests

If your app is behind nginx and you've added `$request_id` to your access log format (see the [nginx log collection docs](https://watchdock.cc/docs/nginx-log-collection)) and forwarded it to your app via `proxy_set_header X-Request-Id $request_id;`, this SDK automatically reads that header off every captured request and attaches it as `trace_id` — no code changes needed. This lets WatchDock link a failed request in your nginx access logs directly to the exception it produced.

You can also pass `trace_id` explicitly, which takes priority over the auto-extracted value:

```python
watchdock_errors.capture_exception(exc, trace_id=my_trace_id)
watchdock_errors.capture_message("Queue depth high", level="warning", trace_id=my_trace_id)
```

## SDK initialization

When `init()` is called, the SDK sends a one-time, fire-and-forget ping to the platform (with the SDK version and environment) to register that it started up. This never blocks application startup and any failure is silently ignored.

## PII scrubbing

By default, `Authorization`, `Cookie`, and `X-Api-Key` headers are stripped and the request body is not sent. Set `send_pii=True` to disable scrubbing.

Use the `before_send` hook for custom scrubbing:

```python
def scrub(event):
    event["request"]["headers"].pop("X-Internal-Token", None)
    return event  # return None to drop the event entirely

watchdock_errors.init(api_key="wdk_xxx", before_send=scrub)
```
