Metadata-Version: 2.4
Name: nilguard
Version: 0.1.2
Summary: Nilguard Python SDK — server-side error tracking with token-based ingest
Project-URL: Homepage, https://github.com/nilguard/nilguard
Project-URL: Documentation, https://github.com/nilguard/nilguard/tree/main/docs
Project-URL: Source, https://github.com/nilguard/nilguard
Project-URL: Issues, https://github.com/nilguard/nilguard/issues
Author: Plivo
License: MIT
Keywords: asgi,crash-reporting,error-monitoring,fastapi,flask,nilguard,starlette,wsgi
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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.11
Requires-Dist: httpx>=0.27
Provides-Extra: asgi
Provides-Extra: dev
Requires-Dist: fastapi>=0.111; extra == 'dev'
Requires-Dist: flask>=3.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: uvicorn>=0.30; extra == 'dev'
Provides-Extra: wsgi
Description-Content-Type: text/markdown

# Nilguard — Python SDK

Server-side error tracking for ASGI apps (FastAPI, Starlette) and WSGI apps
(Flask, Django-WSGI). Mirrors the browser SDK's wire format so the dashboard,
ticketing and agent-run pipeline work unchanged.

## Install

```bash
pip install nilguard
```

For local development, install the package in editable mode from this directory:


```bash
uv pip install -e .
```

You can also pull it directly as a `[tool.uv.sources]` path entry from another
project during local testing.

## Quick start

```python
from fastapi import FastAPI
import nilguard

nilguard.init(
    service="billing-api",                     # human-readable identifier
    framework="fastapi",                       # dashboard renders the right icon
    ingest_key="ng_srv_...",                  # shown once at mint time
    backend_url="https://nilguard.example.com",
    environment="production",
    release="2026-05-23-a1b2c3d",
)

app = FastAPI()
app.add_middleware(nilguard.NilguardASGIMiddleware)

@app.get("/healthy")
async def healthy():
    return {"ok": True}

@app.get("/boom")
async def boom():
    1 / 0   # raises ZeroDivisionError; middleware sends a crash bundle, then re-raises
```

### Try the FastAPI example without installing anything

The `examples/fastapi_demo.py` script uses PEP 723 inline metadata so
`uv` will install FastAPI + uvicorn + this SDK (via a local path source)
for you on first run:

```bash
cd examples/python-fastapi
NILGUARD_INGEST_KEY="ng_srv_..." uv run fastapi_demo.py
```

## WSGI / Flask quick start

For synchronous WSGI frameworks, wrap the WSGI app with
`NilguardWSGIMiddleware` as the outermost layer. It behaves identically to the
ASGI middleware (clean requests send nothing; unhandled exceptions — including
ones raised mid-stream while iterating the response body — send one crash
bundle, then re-raise) but uses the synchronous HTTP client.

```python
from flask import Flask
import nilguard

nilguard.init(
    service="billing-api",
    framework="flask",
    ingest_key="ng_srv_...",
    backend_url="https://nilguard.example.com",
    environment="production",
)

app = Flask(__name__)
app.wsgi_app = nilguard.NilguardWSGIMiddleware(app.wsgi_app)

@app.get("/boom")
def boom():
    1 / 0   # middleware sends a crash bundle, then re-raises
```

A runnable demo lives in `examples/python-flask/flask_demo.py` (PEP 723
inline-deps, same style as the FastAPI demo):

```bash
cd examples/python-flask
NILGUARD_INGEST_KEY="ng_srv_..." uv run flask_demo.py
```

## Manual capture

```python
try:
    risky()
except Exception as exc:
    nilguard.capture_exception(exc, context={"job_id": job.id})
    raise
```

## What gets sent

- **Clean requests** send nothing. The middleware stays on the request path
  only long enough to observe exceptions.
- **Crash bundle** on unhandled exception. Includes a `network` event
  describing the inbound request plus a `crash`
  object with `signal=server_exception` and a redacted traceback in
  `metadata`.
- Headers, cookies, query values, and anything matching the redaction
  denylist (`authorization|cookie|token|secret|password|session|credential|auth`)
  are scrubbed client-side before the POST. The backend re-applies the same
  rules — it remains the source of truth.

## Auth

All ingest requests carry `Authorization: Bearer <ingest_key>`. No
`Origin`/CORS dance: the token is the only thing the backend trusts for the
server-ingest path.
