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:
@@ -49,6 +49,9 @@ import numpy as np
|
||||
MIN_COVERAGE = 0.80 # sotto: la serie ha buchi -> non ci si decide sopra un gate
|
||||
MIN_BARS_PER_JUDGE = 2 # con una barra sola non esiste ne' coda ne' copertura
|
||||
GRAZIA_PREMATURO_MIN = 5.0 # tolleranza fra chiusura della barra e mtime del file (clock/IO)
|
||||
SOGLIA_ORARI_H = 6.0 # (#30) max_age_h <= questa soglia = "sorvegliante orario": i tre
|
||||
# con max_age 3h (cuscino_watch, venue_watch, collect_chain) oggi,
|
||||
# derivato dalla tabella e non da una lista di nomi cablata
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -244,3 +247,46 @@ def alerts_from(rows: list[dict]) -> list[str]:
|
||||
msg += f" | METTE A RISCHIO il gate {r['gate']}"
|
||||
out.append(msg)
|
||||
return out
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# GIRO ORARIO (#30). Il giro giornaliero (cron_daily) resta com'e': report completo, avviso
|
||||
# sempre. I sorveglianti a max_age <= 6h (oggi cuscino_watch, venue_watch, collect_chain) si
|
||||
# scoprono fermi fino a 24h dopo se nessuno li guarda fuori da quel giro: qui si guardano ogni
|
||||
# ora, ma si notifica solo cio' che e' NUOVO rispetto all'ultimo avviso (niente Telegram a
|
||||
# raffica sullo stesso guasto fermo). Tutto PURO: il marcatore lo legge/scrive lo script.
|
||||
# ===========================================================================
|
||||
def monitors_orari(monitors: tuple[MonitorSpec, ...] = MONITORS,
|
||||
soglia_h: float = SOGLIA_ORARI_H) -> tuple[MonitorSpec, ...]:
|
||||
"""I monitor con cadenza di controllo ORARIA: max_age_h <= soglia_h. Derivato dalla tabella
|
||||
`MONITORS`, non da una lista di nomi cablata: aggiungere un monitor orario lo include qui
|
||||
senza toccare questa funzione."""
|
||||
return tuple(m for m in monitors if m.max_age_h <= soglia_h)
|
||||
|
||||
|
||||
def chiave_alert(row: dict) -> str:
|
||||
"""Chiave stabile di un alert per il marcatore 'gia' detto': nome + stato, NON il testo
|
||||
(`why` contiene l'eta' dell'ultima barra, che cambia a ogni giro anche se il guasto e' lo
|
||||
stesso)."""
|
||||
return f"{row['name']}:{row['status']}"
|
||||
|
||||
|
||||
def alert_nuovi(rows: list[dict], detti: set[str]) -> list[dict]:
|
||||
"""Le righe-alert (non OK, non NUOVO — vedi `alerts_from`) la cui chiave NON e' nel
|
||||
marcatore `detti`: quelle davvero nuove, le sole da notificare."""
|
||||
return [r for r in rows if r["status"] not in ("OK", "NUOVO") and chiave_alert(r) not in detti]
|
||||
|
||||
|
||||
def marcatore_aggiornato(rows: list[dict], detti: set[str]) -> set[str]:
|
||||
"""Il marcatore dopo questo giro: le chiavi dei monitor ancora in alert restano/si aggiungono,
|
||||
quelle dei monitor tornati OK si TOLGONO — cosi' un nuovo guasto sullo stesso monitor riparte
|
||||
con un nuovo avviso invece di restare 'gia' detto' per sempre. Non scrive nulla: lo fa lo
|
||||
script, e solo se la notifica e' partita (stessa regola di fee_watch #29)."""
|
||||
out = set(detti)
|
||||
for r in rows:
|
||||
chiavi_monitor = {k for k in out if k.startswith(f"{r['name']}:")}
|
||||
if r["status"] == "OK":
|
||||
out -= chiavi_monitor
|
||||
elif r["status"] != "NUOVO":
|
||||
out.add(chiave_alert(r))
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user