Metadata-Version: 2.4
Name: tellmewhendown
Version: 0.1.0
Summary: Report from inside your app to TellMeWhenDown — cron heartbeats and self-checks in one line.
License: MIT
Project-URL: Homepage, https://tellmewhendown.com
Project-URL: Repository, https://github.com/TellMeWhenDown/Tell-Me-When-Down
Keywords: monitoring,uptime,heartbeat,cron,healthcheck
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# tellmewhendown

Report from inside your app to [TellMeWhenDown](https://tellmewhendown.com) —
cron heartbeats and self-checks in one line. Zero dependencies (stdlib only),
never raises, never slows a request.

```bash
pip install tellmewhendown
```

Put your app's API key (from your app's **Setup** tab) in the environment:

```bash
TMWD_API_KEY=tmwd_...
```

## Heartbeats — "alert me if this stops running"

Call at the **end** of any scheduled job. If the job dies, the beat stops
coming, and that silence is what alerts you.

```python
from tellmewhendown import tmwd

# after your cron job finishes:
tmwd.heartbeat("nightly-backup")

# or decorate the whole job — a raising job sends nothing (which is the point):
@tmwd.beat("nightly-backup")
def run_backup():
    ...
```

## Self-checks — "report what only the app can see"

```python
import time
from tellmewhendown import tmwd

started = time.monotonic()
try:
    db.execute("select 1")
    tmwd.check("db", status="ok", latency_ms=(time.monotonic() - started) * 1000)
except Exception as err:
    tmwd.check("db", status="fail", detail={"error": str(err)})
```

Two consecutive `fail` reports open an incident and email you; the next `ok`
resolves it. Monitors register themselves on the first signal — nothing to
configure on the dashboard first.

## Declare — "alert me even if a job never runs once"

A job that never sends its *first* signal has no monitor, so its silence is
invisible. Declaring registers everything up front, with the real schedule:

```python
# once at startup (idempotent — safe to call every boot):
tmwd.declare([
    {"kind": "heartbeat", "type": "nightly-backup", "interval_seconds": 86400},
    {"kind": "check", "type": "db", "interval_seconds": 3600},
])
```

## Framework notes

- **Django:** call from management commands, Celery tasks, or a periodic task.
- **Flask / FastAPI:** call from your scheduled jobs (APScheduler, Celery) or
  a small health task.
- **Anywhere else:** it's one POST — see the [ingest API docs](https://tellmewhendown.com/bot).

## API

```python
from tellmewhendown import TellMeWhenDown

client = TellMeWhenDown(
    api_key="tmwd_...",              # default: os.environ["TMWD_API_KEY"]
    base_url="https://...",          # default: https://tellmewhendown.com
    timeout=5.0,                     # seconds
    on_error=lambda msg: None,       # observe failures; reporting never raises
)
```

Every method returns `True` on success, `False` on any failure. A failure to
report is never allowed to become your app's failure.
