Metadata-Version: 2.4
Name: sentinelle-agent
Version: 0.1.2
Summary: Sentinelle monitoring agent for Python apps (Flask, FastAPI, Django)
Author-email: Sentinelle <hello@sentinelle.dev>
License: MIT
Project-URL: Homepage, https://sentinelle.dev
Project-URL: Documentation, https://sentinelle.dev/docs/agent
Project-URL: Source, https://github.com/sentinelle-dev/sentinelle-python
Project-URL: Issues, https://github.com/sentinelle-dev/sentinelle-python/issues
Keywords: monitoring,rasp,security,observability,sentinelle,flask,fastapi,django
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
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: Topic :: System :: Monitoring
Classifier: Topic :: Security
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.25
Provides-Extra: flask
Requires-Dist: flask>=2.0; extra == "flask"
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.95; extra == "fastapi"
Requires-Dist: starlette>=0.27; extra == "fastapi"
Provides-Extra: django
Requires-Dist: django>=3.2; extra == "django"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"

# sentinelle-agent (Python)

Sentinelle monitoring agent for Python web apps. Supports **Flask**, **FastAPI**, **Django**.

Mirror of the official Node.js SDK ([sentinelle-agent on npm](https://www.npmjs.com/package/sentinelle-agent)) - same backend, same payload contract, same dashboard.

## Install

```bash
pip install sentinelle-agent
```

Optional extras for framework auto-detection of typed dependencies:

```bash
pip install "sentinelle-agent[flask]"     # Flask
pip install "sentinelle-agent[fastapi]"   # FastAPI / Starlette
pip install "sentinelle-agent[django]"    # Django
```

## Configuration

Two ways, equivalent:

**Env vars** (recommended for production):
```bash
export SENTINELLE_API_KEY=your-project-api-key
export SENTINELLE_SERVER_URL=https://api.sentinelle.dev
export SENTINELLE_APP_NAME=my-python-app
```

**Code**:
```python
import sentinelle_agent

sentinelle_agent.init(
    api_key="your-project-api-key",
    server_url="https://api.sentinelle.dev",
    app_name="my-python-app",
)
```

Get your `api_key` from your Sentinelle dashboard - project settings.

## Flask

```python
from flask import Flask
import sentinelle_agent
from sentinelle_agent.flask_adapter import wrap_flask

sentinelle_agent.init(app_name="my-flask-app")

app = Flask(__name__)
wrap_flask(app)

@app.get("/hello")
def hello():
    return {"ok": True}
```

That's it. Routes are auto-discovered, request metrics tracked, errors captured.

## FastAPI

```python
from fastapi import FastAPI
import sentinelle_agent
from sentinelle_agent.fastapi_adapter import wrap_fastapi

sentinelle_agent.init(app_name="my-fastapi-app")

app = FastAPI()
wrap_fastapi(app)

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

Works with Starlette too (FastAPI is built on Starlette).

## Django

In `settings.py`:

```python
import sentinelle_agent
sentinelle_agent.init(app_name="my-django-app")

MIDDLEWARE = [
    # ... your other middlewares ...
    "sentinelle_agent.django_adapter.SentinelleMiddleware",
]
```

## What it does

Per-request:
- Times each request (HTTP middleware)
- Tracks method, path, route template, status code, response ms
- Aggregates top routes, errors 4xx / 5xx, status distribution

Errors:
- Captures unhandled exceptions raised by your handlers
- Captures uncaught exceptions on any thread (via `sys.excepthook` and `threading.excepthook`)
- Captures slow requests (> 5000 ms) as warnings
- Sensitive fields auto-redacted in request bodies / headers / query: `password`, `token`, `secret`, `authorization`, `cookie`, `credit_card`, `cvv`, `ssn`, `api_key`, `session`

Routes:
- Discovered at startup (Flask `url_map`, FastAPI `app.routes`, Django URL conf)
- Posted once to `/api/webhooks/agent/routes`

Heartbeat (every 60s by default):
- App uptime, RSS memory (via `psutil` if available, else `resource`)
- Python version, hostname, PID, platform, arch
- Request metrics (total, avg ms, errors 4xx/5xx, top 5 routes)
- Posted to `/api/webhooks/agent/heartbeat`

Server-driven kill switch:
- If the backend returns `kill_switch_active: true` in a heartbeat response, the agent stops uploading new errors (but keeps sending heartbeats so the project stays observable).

## Custom errors

```python
import sentinelle_agent

try:
    do_something()
except Exception as e:
    sentinelle_agent.report_error({
        "type": "PaymentFailed",
        "message": str(e),
        "fatal": False,
    })
    raise
```

## Sentinelle agent options

```python
sentinelle_agent.init(
    api_key="...",
    server_url="https://api.sentinelle.dev",
    app_name="my-app",
    heartbeat_interval=60,     # seconds, default 60
    capture_unhandled=True,    # install sys/threading excepthooks, default True
    debug=False,               # print [Sentinelle Agent] log lines, default False
)
```

## Memory & performance

- Two daemon threads (heartbeat + flush). Both exit when the process exits.
- Per-request middleware overhead: < 100us in steady state (a few dict updates under a lock, no I/O on the hot path).
- Errors are buffered and sent in batches (every 30s, or sooner when 10+ accumulated, or immediately on fatal).
- Request body sanitization is bounded (3 levels deep, lists capped at 50 items).

## License

MIT
