63 lines
1.8 KiB
Python
63 lines
1.8 KiB
Python
"""Alert history and acknowledgement endpoints."""
|
|
import time
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
|
|
from ..auth import require_session, require_session_and_csrf
|
|
from ..storage import get_redis
|
|
|
|
router = APIRouter(prefix="/api/alerts")
|
|
|
|
|
|
@router.get("")
|
|
async def list_alerts(
|
|
ups: str | None = Query(None),
|
|
severity: str | None = Query(None),
|
|
days: int = Query(30, ge=1, le=90),
|
|
user=Depends(require_session),
|
|
):
|
|
r = get_redis()
|
|
raw = r.lrange("ups:alerts:history:all", 0, -1)
|
|
cutoff = int(time.time()) - days * 86400
|
|
out = []
|
|
for item in raw:
|
|
parts = item.split("|", 5)
|
|
if len(parts) < 5:
|
|
continue
|
|
try:
|
|
ts = int(parts[0])
|
|
except ValueError:
|
|
continue
|
|
if ts < cutoff:
|
|
continue
|
|
row = {
|
|
"ts": ts,
|
|
"severity": parts[1],
|
|
"ups": parts[2],
|
|
"code": parts[3],
|
|
"message": parts[4],
|
|
"id": parts[5] if len(parts) > 5 else "",
|
|
}
|
|
if ups and row["ups"] != ups:
|
|
continue
|
|
if severity and row["severity"] != severity.upper():
|
|
continue
|
|
ack = r.get(f"ups:alerts:ack:{row['id']}")
|
|
row["acked_ts"] = int(ack) if ack else None
|
|
out.append(row)
|
|
return out
|
|
|
|
|
|
@router.get("/active")
|
|
async def list_active(user=Depends(require_session)):
|
|
"""Active alerts = history entries not yet acknowledged, most recent first."""
|
|
all_alerts = await list_alerts(days=7, user=user)
|
|
return [a for a in all_alerts if not a.get("acked_ts")]
|
|
|
|
|
|
@router.post("/{alert_id}/ack")
|
|
async def ack_alert(alert_id: str, user=Depends(require_session_and_csrf)):
|
|
r = get_redis()
|
|
r.set(f"ups:alerts:ack:{alert_id}", int(time.time()), ex=30 * 86400)
|
|
return {"message": "acknowledged"}
|