Mise au point des monitoring
This commit is contained in:
@@ -9,8 +9,7 @@ PROGRAM_NAME = f"Monitor_{SITE}"
|
||||
import os, re, time, ssl, smtplib, logging
|
||||
import datetime as dt
|
||||
from email.message import EmailMessage
|
||||
from typing import List
|
||||
|
||||
from datetime import datetime
|
||||
from dotenv import load_dotenv, find_dotenv
|
||||
load_dotenv(find_dotenv(usecwd=True), override=False)
|
||||
|
||||
@@ -41,6 +40,45 @@ if not log.handlers:
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
|
||||
|
||||
# ========= DB utils =========
|
||||
def open_alert(conn, table_alertes: str, sonde: str, dt: datetime) -> bool:
|
||||
"""
|
||||
Ouvre UNE alerte si aucune alerte 'En cours' n'existe encore pour la sonde.
|
||||
Retourne True si une nouvelle alerte a été créée (→ notifier).
|
||||
"""
|
||||
cur = conn.cursor()
|
||||
cur.execute(
|
||||
f"SELECT 1 FROM `{table_alertes}` WHERE Sonde=%s AND Etat='En cours' LIMIT 1",
|
||||
(sonde,)
|
||||
)
|
||||
if cur.fetchone():
|
||||
cur.close()
|
||||
return False # déjà ouverte → pas de notif
|
||||
|
||||
cur.execute(
|
||||
f"INSERT INTO `{table_alertes}` (Sonde, Debut_defaut, Etat) VALUES (%s, %s, 'En cours')",
|
||||
(sonde, dt.strftime('%Y-%m-%d %H:%M:%S'))
|
||||
)
|
||||
conn.commit()
|
||||
cur.close()
|
||||
return True # nouvelle alerte → notifier
|
||||
|
||||
def close_alert(conn, table_alertes: str, sonde: str) -> bool:
|
||||
"""
|
||||
Ferme l'alerte 'En cours' si présente.
|
||||
Retourne True si une alerte est passée à 'Acquitté' (→ notifier).
|
||||
"""
|
||||
cur = conn.cursor()
|
||||
cur.execute(
|
||||
f"UPDATE `{table_alertes}` SET Etat='Acquitté' "
|
||||
f"WHERE Sonde=%s AND Etat='En cours' "
|
||||
f"ORDER BY Debut_defaut DESC LIMIT 1",
|
||||
(sonde,)
|
||||
)
|
||||
changed = (cur.rowcount == 1)
|
||||
conn.commit()
|
||||
cur.close()
|
||||
return changed # True → notifier, False → rien
|
||||
|
||||
def get_db():
|
||||
cnx = mysql.connector.connect(
|
||||
host=os.getenv("DB_HOST"),
|
||||
@@ -136,19 +174,6 @@ def depassement_depuis_30min(site: str, sonde: str, seuil: float) -> bool:
|
||||
finally:
|
||||
cnx.close()
|
||||
|
||||
def alerte_en_cours(site: str, sonde: str) -> bool:
|
||||
table = f"Alertes_{site}"
|
||||
cnx = get_db()
|
||||
try:
|
||||
cur = cnx.cursor()
|
||||
cur.execute(f"SELECT 1 FROM `{table}` WHERE `Sonde`=%s AND `Etat`='En cours' LIMIT 1", (sonde,))
|
||||
return cur.fetchone() is not None
|
||||
except MySQLError as err:
|
||||
log.exception("Erreur DB (alerte_en_cours): %s", err)
|
||||
return False
|
||||
finally:
|
||||
cnx.close()
|
||||
|
||||
def any_alert_open(site: str) -> bool:
|
||||
table = f"Alertes_{site}"
|
||||
cnx = get_db()
|
||||
@@ -161,31 +186,6 @@ def any_alert_open(site: str) -> bool:
|
||||
return False
|
||||
finally:
|
||||
cnx.close()
|
||||
|
||||
def creer_alerte(site: str, sonde: str):
|
||||
table = f"Alertes_{site}"
|
||||
cnx = get_db()
|
||||
try:
|
||||
cur = cnx.cursor()
|
||||
cur.execute(f"INSERT INTO `{table}` (`Sonde`, `Debut_defaut`, `Etat`) VALUES (%s, NOW(), 'En cours')", (sonde,))
|
||||
cnx.commit()
|
||||
except MySQLError as err:
|
||||
log.exception("Erreur DB (creer_alerte): %s", err)
|
||||
finally:
|
||||
cnx.close()
|
||||
|
||||
def acquitter_alerte(site: str, sonde: str):
|
||||
table = f"Alertes_{site}"
|
||||
cnx = get_db()
|
||||
try:
|
||||
cur = cnx.cursor()
|
||||
cur.execute(f"UPDATE `{table}` SET `Etat`='Acquitté' WHERE `Sonde`=%s AND `Etat`='En cours'", (sonde,))
|
||||
cnx.commit()
|
||||
except MySQLError as err:
|
||||
log.exception("Erreur DB (acquitter_alerte): %s", err)
|
||||
finally:
|
||||
cnx.close()
|
||||
|
||||
# ========= Helpers listes/numéros =========
|
||||
def _split_list(raw: str | None) -> list[str]:
|
||||
return [x.strip() for x in re.split(r"[;,]", raw or "") if x.strip()]
|
||||
@@ -454,13 +454,29 @@ def run_monitor_cycle(site: str = SITE):
|
||||
sondes = lire_sondes_depuis_db(site)
|
||||
seuils = lire_seuils_depuis_db(site)
|
||||
for r in sondes:
|
||||
nom = str(r["Sonde"]); temp = float(r["Temperature"]); seuil = float(seuils.get(nom, 6.0))
|
||||
nom = str(r["Sonde"])
|
||||
temp = float(r["Temperature"])
|
||||
seuil = float(seuils.get(nom, 6.0))
|
||||
|
||||
now = now_paris()
|
||||
if temp > seuil:
|
||||
if depassement_depuis_30min(site, nom, seuil) and not alerte_en_cours(site, nom):
|
||||
creer_alerte(site, nom); notifier_sur_depassement(site, nom, temp, seuil)
|
||||
if depassement_depuis_30min(site, nom, seuil):
|
||||
# Ouvrir si pas déjà ouvert → notifier seulement si ouverture réelle
|
||||
try:
|
||||
conn = get_db()
|
||||
if open_alert(conn, f"Alertes_{site}", nom, now):
|
||||
notifier_sur_depassement(site, nom, temp, seuil)
|
||||
finally:
|
||||
conn.close()
|
||||
else:
|
||||
if alerte_en_cours(site, nom):
|
||||
acquitter_alerte(site, nom); notifier_acquittement(site, nom, temp, seuil)
|
||||
# Fermer si ouvert → notifier seulement si fermeture réelle
|
||||
try:
|
||||
conn = get_db()
|
||||
if close_alert(conn, f"Alertes_{site}", nom):
|
||||
notifier_acquittement(site, nom, temp, seuil)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def run_monitor_loop(site: str = SITE, period_sec: int = 300):
|
||||
log.info("%s démarré (site=%s, période=%ss) ✅", PROGRAM_NAME, site, period_sec)
|
||||
|
||||
Reference in New Issue
Block a user