check retention

This commit is contained in:
2026-03-10 14:30:10 +00:00
parent 7f0447f82c
commit 3ffaf0cc4d
6 changed files with 65 additions and 3 deletions

View File

@@ -3,3 +3,7 @@
DOCKER_REGISTRY=docker.io
DOCKER_IMAGE=myorg/myapp
IMAGE_TAG=latest
# Optional: check retention (limits DB growth)
# CHECK_RETENTION_COUNT=5000 # keep last N checks per service (default 5000)
# CHECK_RETENTION_DAYS=30 # also delete checks older than N days (0=disabled)

View File

@@ -42,6 +42,21 @@ docker run -p 8080:8080 -v $(pwd)/data:/app/data myapp:test
Add services from the dashboard (e.g. `https://example.com`, `google.com:443` for TCP) and view reports.
### Check Retention
To limit database growth, the app prunes old checks every 15 minutes:
| Env var | Default | Description |
|---------|---------|-------------|
| `CHECK_RETENTION_COUNT` | 5000 | Keep last N checks per service |
| `CHECK_RETENTION_DAYS` | 0 (disabled) | Also delete checks older than N days |
Example: keep 2000 checks per service and drop anything older than 30 days:
```bash
docker run -e CHECK_RETENTION_COUNT=2000 -e CHECK_RETENTION_DAYS=30 ...
```
## Jenkins Pipeline
The pipeline:

View File

@@ -141,7 +141,7 @@ def report(service_id):
status_filter = request.args.get("status")
search = request.args.get("search", "").strip() or None
page = max(1, int(request.args.get("page", 1)))
per_page = min(100, max(10, int(request.args.get("per_page", 25))))
per_page = min(100, max(10, int(request.args.get("per_page", 10))))
stats = models.get_report_stats(service_id, from_ts=from_ts, to_ts=to_ts)
checks_total = models.get_checks_count(service_id, from_ts=from_ts, to_ts=to_ts, status_filter=status_filter, search=search)
checks = models.get_checks(

View File

@@ -2,12 +2,16 @@
import os
import sqlite3
from contextlib import contextmanager
from datetime import datetime
from datetime import datetime, timedelta, timezone
from pathlib import Path
DATA_PATH = os.environ.get("DATA_PATH", "/app/data")
DB_PATH = Path(DATA_PATH) / "monitor.db"
# Retention: keep last N checks per service, and optionally drop checks older than N days
CHECK_RETENTION_COUNT = int(os.environ.get("CHECK_RETENTION_COUNT", "5000"))
CHECK_RETENTION_DAYS = int(os.environ.get("CHECK_RETENTION_DAYS", "0")) or None
def _ensure_data_dir():
Path(DATA_PATH).mkdir(parents=True, exist_ok=True)
@@ -232,3 +236,38 @@ def get_all_services_for_scheduler():
with get_db() as conn:
rows = conn.execute("SELECT id, target, protocol, interval_seconds FROM services").fetchall()
return [dict(r) for r in rows]
def prune_checks_retention() -> int:
"""
Remove old checks to limit storage. Keeps last CHECK_RETENTION_COUNT per service.
If CHECK_RETENTION_DAYS is set, also deletes checks older than that.
Returns number of rows deleted.
"""
with get_db() as conn:
deleted = 0
# Delete checks older than N days (if configured)
if CHECK_RETENTION_DAYS:
cutoff = (datetime.now(timezone.utc) - timedelta(days=CHECK_RETENTION_DAYS)).isoformat()
cur = conn.execute("DELETE FROM checks WHERE timestamp < ?", (cutoff,))
deleted += cur.rowcount
# Keep only last N checks per service
service_ids = [r[0] for r in conn.execute("SELECT id FROM services").fetchall()]
for sid in service_ids:
# Get ids of checks to keep (most recent N)
keep_ids = conn.execute(
"SELECT id FROM checks WHERE service_id = ? ORDER BY timestamp DESC LIMIT ?",
(sid, CHECK_RETENTION_COUNT),
).fetchall()
keep_ids = [r[0] for r in keep_ids]
if not keep_ids:
continue
placeholders = ",".join("?" * len(keep_ids))
cur = conn.execute(
f"DELETE FROM checks WHERE service_id = ? AND id NOT IN ({placeholders})",
[sid] + keep_ids,
)
deleted += cur.rowcount
return deleted

View File

@@ -2,7 +2,7 @@
from apscheduler.schedulers.background import BackgroundScheduler
from app.checker import run_check
from app.models import get_all_services_for_scheduler
from app.models import get_all_services_for_scheduler, prune_checks_retention
def _run_all_checks():
@@ -54,4 +54,7 @@ def start_scheduler():
# Sync job list every 60 seconds (only adds/removes when services change)
scheduler.add_job(sync_jobs, "interval", seconds=60, id="sync_jobs")
# Prune old checks every 15 minutes (retention/compression)
scheduler.add_job(prune_checks_retention, "interval", minutes=15, id="prune_checks")
scheduler.start()

View File

@@ -10,4 +10,5 @@ services:
- ./data:/app/data
environment:
- VERSION=${IMAGE_TAG:-latest}
# Optional: CHECK_RETENTION_COUNT=5000, CHECK_RETENTION_DAYS=30
restart: unless-stopped