monitor_health: giro orario dei sorveglianti da 3h con marcatore gia' detto (#30)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,20 +10,91 @@ monitor e la soglia di copertura 0.80 (la stessa del veto d'integrita' di DVOLSP
|
||||
|
||||
uv run python scripts/live/monitor_health.py # report
|
||||
uv run python scripts/live/monitor_health.py --quiet # stampa/allerta solo se scatta
|
||||
uv run python scripts/live/monitor_health.py --solo-orari # (#30) solo i sorveglianti a
|
||||
# max_age<=6h (cuscino_watch, venue_watch, collect_chain), notifica solo il NUOVO
|
||||
# rispetto a data/live/monitor_health_detto.json — pensato per girare ogni ora
|
||||
# (cron_cuscino.sh), non per sostituire il giro giornaliero completo.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from src.live.monitor_health import MIN_COVERAGE, alerts_from, check_all # noqa: E402
|
||||
from src.live.monitor_health import ( # noqa: E402
|
||||
MIN_COVERAGE,
|
||||
alert_nuovi,
|
||||
alerts_from,
|
||||
check_all,
|
||||
marcatore_aggiornato,
|
||||
monitors_orari,
|
||||
)
|
||||
from src.live.notifier import notify # noqa: E402
|
||||
|
||||
# (#30) marcatore "gia' detto" del giro orario: {"detti": [<chiave alert>], "ts": ...}. Vive fuori
|
||||
# da src/ perche' e' I/O, non parte della misura pura.
|
||||
DETTO = ROOT / "data" / "live" / "monitor_health_detto.json"
|
||||
|
||||
|
||||
def _carica_detti(path: Path = DETTO) -> set[str]:
|
||||
if not path.exists():
|
||||
return set()
|
||||
try:
|
||||
return set(json.loads(path.read_text()).get("detti", []))
|
||||
except Exception:
|
||||
return set()
|
||||
|
||||
|
||||
def _salva_detti(detti: set[str], path: Path = DETTO) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(
|
||||
{"detti": sorted(detti), "ts": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")},
|
||||
indent=2))
|
||||
|
||||
|
||||
def main_orari() -> int:
|
||||
"""(#30) Giro orario: solo i sorveglianti a max_age<=6h, notifica solo il NUOVO rispetto al
|
||||
marcatore. Exit 2 se c'e' un alert (anche gia' detto), 0 altrimenti — il giro giornaliero
|
||||
resta l'unico posto dove "nessun alert nuovo" vuol dire davvero "tutto OK"."""
|
||||
quiet = "--quiet" in sys.argv
|
||||
rows = check_all(ROOT, monitors=monitors_orari())
|
||||
alerts = alerts_from(rows)
|
||||
detti = _carica_detti(DETTO) # DETTO letto qui, non nel default del parametro (monkeypatch)
|
||||
nuovi = alert_nuovi(rows, detti)
|
||||
aggiornato = marcatore_aggiornato(rows, detti)
|
||||
|
||||
if not quiet or alerts:
|
||||
print("=" * 92)
|
||||
print(" MONITOR HEALTH — giro orario (sorveglianti con max_age <= 6h)")
|
||||
print("=" * 92)
|
||||
for r in rows:
|
||||
cov = f"{r['coverage']:.0%}" if r["coverage"] is not None else "-"
|
||||
age = f"{r['age_h']:.0f}h" if r["age_h"] is not None else "-"
|
||||
print(f" {r['name']:<20}{r['status']:>10}{age:>13}{cov:>10}")
|
||||
|
||||
inviato = True
|
||||
if nuovi:
|
||||
msgs = alerts_from(nuovi)
|
||||
inviato = notify("🩺 MONITOR HEALTH — un sorvegliante orario non sta registrando",
|
||||
{f"alert {i+1}": m for i, m in enumerate(msgs)})
|
||||
for m in msgs:
|
||||
print(f" ALERT (nuovo): {m}")
|
||||
if not inviato:
|
||||
print(" ⚠️ invio FALLITO — marcatore NON aggiornato: il prossimo giro ritenta")
|
||||
if not nuovi or inviato:
|
||||
_salva_detti(aggiornato, DETTO)
|
||||
|
||||
return 2 if alerts else 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if "--solo-orari" in sys.argv:
|
||||
return main_orari()
|
||||
|
||||
rows = check_all(ROOT)
|
||||
alerts = alerts_from(rows)
|
||||
|
||||
@@ -55,15 +126,17 @@ def main() -> int:
|
||||
return 0
|
||||
|
||||
|
||||
USO = """uso: monitor_health.py [--quiet]
|
||||
USO = """uso: monitor_health.py [--quiet] [--solo-orari]
|
||||
|
||||
monitor_health.py — i forward-monitor stanno registrando? Riporta e allerta, non tocca nulla.
|
||||
uv run python scripts/live/monitor_health.py # report
|
||||
uv run python scripts/live/monitor_health.py --quiet # stampa/allerta solo se scatta
|
||||
uv run python scripts/live/monitor_health.py --solo-orari # (#30) solo i sorveglianti a
|
||||
max_age<=6h, notifica solo il NUOVO rispetto al marcatore
|
||||
|
||||
Dettaglio nel docstring in testa al file."""
|
||||
|
||||
if __name__ == "__main__":
|
||||
from src.live.cli import valida
|
||||
valida("monitor_health.py", USO, flag=("--quiet",), con_valore=())
|
||||
valida("monitor_health.py", USO, flag=("--quiet", "--solo-orari"), con_valore=())
|
||||
raise SystemExit(main())
|
||||
|
||||
Reference in New Issue
Block a user