Mise en place d'un journal de connexions
This commit is contained in:
16
.env
16
.env
@@ -3,6 +3,11 @@ DB_HOST=162.19.78.131
|
|||||||
DB_USER=sondes
|
DB_USER=sondes
|
||||||
DB_PASS=TX.)-U1!zq5Axdk4
|
DB_PASS=TX.)-U1!zq5Axdk4
|
||||||
DB_NAME=Sondes
|
DB_NAME=Sondes
|
||||||
|
|
||||||
|
DB_USER2=journal_connexions
|
||||||
|
DB_PASS2=%t!RRa6sj4KY9dY%zTT
|
||||||
|
DB_NAME2=Acces
|
||||||
|
|
||||||
AUTH_USERS=[{"user":"Michel","pass":"210462"}]
|
AUTH_USERS=[{"user":"Michel","pass":"210462"}]
|
||||||
|
|
||||||
# MQTT
|
# MQTT
|
||||||
@@ -12,14 +17,17 @@ MQTT_PASS=3J@bjYP0
|
|||||||
MQTT_PORT=1883
|
MQTT_PORT=1883
|
||||||
|
|
||||||
# Synology Chat
|
# Synology Chat
|
||||||
SYNO_CHAT_WEBHOOK_MONITOR_SACLAY=https://mj91.fr/chat/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=QpLWAZEqIW1EOBHkfDkmr1LqC3P3J1SASWfqpchZdd1xPY7xGbYerS4lCADJnPrm
|
SYNO_CHAT_WEBHOOK_MONITOR_SACLAY=https://mj91.fr/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=zLaQnf5tD2BTsu6N7RQZvUyKipQSDSiXqV57VhWUfblQksL9K8NH22imxEtKas4m
|
||||||
SYNO_CHAT_WEBHOOK_MONITOR_MEUDON=https://mj91.fr/chat/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=QpLWAZEqIW1EOBHkfDkmr1LqC3P3J1SASWfqpchZdd1xPY7xGbYerS4lCADJnPrm
|
SYNO_CHAT_WEBHOOK_MONITOR_MEUDON=https://mj91.fr/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=3bU0z4cG15CyCxXvz76voErQq8c1SLsms8kxsH6DvUQhGVQ9w5zqLvZ0GLVsLONP
|
||||||
|
|
||||||
SYNO_CHAT_WEBHOOK_GYRO_SACLAY=https://mj91.fr/chat/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=NUqdEGbtmTBBGIN29z0AVZUeQnyZ8tskyXGpkOFqHwqOAXB8quvHxlEcewKX3Xnq
|
SYNO_CHAT_WEBHOOK_GYRO_SACLAY=https://mj91.fr/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=M0cJHOhtqhEWFEpdd8XTcmZHcTVq9ItDDCodvRq8MJHAJVbn9UTRZf1SxZXRn8mr
|
||||||
SYNO_CHAT_WEBHOOK_GYRO_MEUDON=https://mj91.fr/chat/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=NUqdEGbtmTBBGIN29z0AVZUeQnyZ8tskyXGpkOFqHwqOAXB8quvHxlEcewKX3Xnq
|
SYNO_CHAT_WEBHOOK_GYRO_MEUDON=https://mj91.fr/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=yllI91DMC75XqFDwMW798GraUTLVv5Hb4wGGGmd65fHm4wbQIghlb01cgYPkZLtd
|
||||||
|
|
||||||
|
SYNO_CHAT_WEBHOOK_CONNEXIONS=https://mj91.fr/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=R585242twVz04qmzukxbtSTMe7p0GgdroKtO8opBglDx3VLtaLwJhYb93btH6Hya
|
||||||
|
|
||||||
SYNO_CHAT_BOTNAME_MONITOR="Injection données dans tables"
|
SYNO_CHAT_BOTNAME_MONITOR="Injection données dans tables"
|
||||||
SYNO_CHAT_BOTNAME_GYRO="Gestion Gyro"
|
SYNO_CHAT_BOTNAME_GYRO="Gestion Gyro"
|
||||||
|
SYNO_CHAT_BOTNAME_CONNEXIONS="Journal Connexions"
|
||||||
|
|
||||||
SYNO_CHAT_TIMEOUT=10
|
SYNO_CHAT_TIMEOUT=10
|
||||||
SYNO_CHAT_VERIFY_SSL=true
|
SYNO_CHAT_VERIFY_SSL=true
|
||||||
|
|||||||
@@ -391,15 +391,22 @@ def depassement_depuis_30min(site: str, sonde: str, seuil: float) -> bool:
|
|||||||
# ========= Synology Chat =========
|
# ========= Synology Chat =========
|
||||||
def send_synology_chat(message: str, *, username: str | None = None) -> bool:
|
def send_synology_chat(message: str, *, username: str | None = None) -> bool:
|
||||||
webhook = (
|
webhook = (
|
||||||
|
_env_str(f"SYNO_CHAT_WEBHOOK_MONITOR_{SITE}") or
|
||||||
|
_env_str(f"SYNO_CHAT_WEBHOOK_MONITOR_{SITE.upper()}") or
|
||||||
|
_env_str("SYNO_CHAT_WEBHOOK_MONITOR") or
|
||||||
_env_str(f"SYNO_CHAT_WEBHOOK_{SITE}") or
|
_env_str(f"SYNO_CHAT_WEBHOOK_{SITE}") or
|
||||||
_env_str(f"SYNO_CHAT_WEBHOOK_MONITOR") or
|
_env_str(f"SYNO_CHAT_WEBHOOK_{SITE.upper()}") or
|
||||||
_env_str("SYNO_CHAT_WEBHOOK")
|
_env_str("SYNO_CHAT_WEBHOOK")
|
||||||
)
|
)
|
||||||
if not webhook:
|
if not webhook:
|
||||||
log.info("Synology Chat non configuré.")
|
log.info("Synology Chat non configuré.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
botname = username or _env_str("SYNO_CHAT_BOTNAME")
|
botname = (
|
||||||
|
username
|
||||||
|
or _env_str("SYNO_CHAT_BOTNAME_MONITOR")
|
||||||
|
or _env_str("SYNO_CHAT_BOTNAME")
|
||||||
|
)
|
||||||
timeout = int(_env_str("SYNO_CHAT_TIMEOUT", "10"))
|
timeout = int(_env_str("SYNO_CHAT_TIMEOUT", "10"))
|
||||||
verify_ssl = _env_bool("SYNO_CHAT_VERIFY_SSL", True)
|
verify_ssl = _env_bool("SYNO_CHAT_VERIFY_SSL", True)
|
||||||
|
|
||||||
@@ -407,7 +414,9 @@ def send_synology_chat(message: str, *, username: str | None = None) -> bool:
|
|||||||
if botname:
|
if botname:
|
||||||
chat_payload["username"] = botname
|
chat_payload["username"] = botname
|
||||||
|
|
||||||
form_data = {"payload": json.dumps(chat_payload, ensure_ascii=False)}
|
form_data = {
|
||||||
|
"payload": json.dumps(chat_payload, ensure_ascii=False)
|
||||||
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
|
|||||||
@@ -307,15 +307,22 @@ def depassement_depuis_30min(site: str, sonde: str, seuil: float) -> bool:
|
|||||||
# ========= Synology Chat =========
|
# ========= Synology Chat =========
|
||||||
def send_synology_chat(message: str, *, username: str | None = None) -> bool:
|
def send_synology_chat(message: str, *, username: str | None = None) -> bool:
|
||||||
webhook = (
|
webhook = (
|
||||||
|
_env_str(f"SYNO_CHAT_WEBHOOK_MONITOR_{SITE}") or
|
||||||
|
_env_str(f"SYNO_CHAT_WEBHOOK_MONITOR_{SITE.upper()}") or
|
||||||
|
_env_str("SYNO_CHAT_WEBHOOK_MONITOR") or
|
||||||
_env_str(f"SYNO_CHAT_WEBHOOK_{SITE}") or
|
_env_str(f"SYNO_CHAT_WEBHOOK_{SITE}") or
|
||||||
_env_str(f"SYNO_CHAT_WEBHOOK_MONITOR_SACLAY") or
|
_env_str(f"SYNO_CHAT_WEBHOOK_{SITE.upper()}") or
|
||||||
_env_str("SYNO_CHAT_WEBHOOK")
|
_env_str("SYNO_CHAT_WEBHOOK")
|
||||||
)
|
)
|
||||||
if not webhook:
|
if not webhook:
|
||||||
log.info("Synology Chat non configuré.")
|
log.info("Synology Chat non configuré.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
botname = username or _env_str("SYNO_CHAT_BOTNAME")
|
botname = (
|
||||||
|
username
|
||||||
|
or _env_str("SYNO_CHAT_BOTNAME_MONITOR")
|
||||||
|
or _env_str("SYNO_CHAT_BOTNAME")
|
||||||
|
)
|
||||||
timeout = int(_env_str("SYNO_CHAT_TIMEOUT", "10"))
|
timeout = int(_env_str("SYNO_CHAT_TIMEOUT", "10"))
|
||||||
verify_ssl = _env_bool("SYNO_CHAT_VERIFY_SSL", True)
|
verify_ssl = _env_bool("SYNO_CHAT_VERIFY_SSL", True)
|
||||||
|
|
||||||
|
|||||||
183
app/Monitor_connexions.py
Normal file
183
app/Monitor_connexions.py
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
from typing import Optional
|
||||||
|
import json
|
||||||
|
import pymysql
|
||||||
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format="%(asctime)s | %(levelname)s | %(message)s"
|
||||||
|
)
|
||||||
|
log = logging.getLogger("journal_connexions")
|
||||||
|
|
||||||
|
|
||||||
|
def env_str(name: str, default: Optional[str] = None) -> Optional[str]:
|
||||||
|
value = os.getenv(name, default)
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
value = value.strip()
|
||||||
|
return value if value else default
|
||||||
|
|
||||||
|
|
||||||
|
DB_CONFIG = {
|
||||||
|
"host": env_str("DB_HOST"),
|
||||||
|
"port": int(env_str("DB_PORT", "3306")),
|
||||||
|
"user": env_str("DB_USER2"),
|
||||||
|
"password": env_str("DB_PASS2"),
|
||||||
|
"database": env_str("DB_NAME2", "Acces"),
|
||||||
|
"charset": "utf8mb4",
|
||||||
|
"cursorclass": pymysql.cursors.DictCursor,
|
||||||
|
"autocommit": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
SYNO_CHAT_WEBHOOK = env_str("SYNO_CHAT_WEBHOOK_CONNEXIONS")
|
||||||
|
SYNO_CHAT_BOTNAME = env_str("SYNO_CHAT_BOTNAME_CONNEXIONS", "Journal Connexions")
|
||||||
|
POLL_INTERVAL = int(env_str("POLL_INTERVAL", "10"))
|
||||||
|
|
||||||
|
|
||||||
|
def get_connection():
|
||||||
|
return pymysql.connect(**DB_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
def format_message(row: dict) -> str:
|
||||||
|
return (
|
||||||
|
f"[Connexion MySQL]\n"
|
||||||
|
f"Utilisateur : {row.get('NomUtilisateur', '')}\n"
|
||||||
|
f"Poste : {row.get('PosteClient', '')}\n"
|
||||||
|
f"Tableur : {row.get('TableurSource', '')}\n"
|
||||||
|
f"Windows : {row.get('UtilisateurWindows', '')}\n"
|
||||||
|
f"Site : {row.get('SiteDemande', '')}\n"
|
||||||
|
f"Service : {row.get('ServiceDemande', '')}\n"
|
||||||
|
f"DSN : {row.get('DSN', '')}\n"
|
||||||
|
f"BDD : {row.get('BDD', '')}\n"
|
||||||
|
f"Statut : {row.get('Statut', '')}\n"
|
||||||
|
f"Motif : {row.get('Motif', '')}\n"
|
||||||
|
f"Heure : {row.get('DateHeure', '')}\n"
|
||||||
|
f"Session : {row.get('SessionID', '')}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def send_synology_chat(message: str) -> None:
|
||||||
|
if not SYNO_CHAT_WEBHOOK:
|
||||||
|
raise RuntimeError("SYNO_CHAT_WEBHOOK_CONNEXIONS non configuré")
|
||||||
|
|
||||||
|
syno_payload = {
|
||||||
|
"text": message
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(
|
||||||
|
SYNO_CHAT_WEBHOOK,
|
||||||
|
data={"payload": json.dumps(syno_payload, ensure_ascii=False)},
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
log.info("Synology Chat HTTP=%s body=%s", response.status_code, response.text)
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
body = response.json()
|
||||||
|
if not body.get("success", False):
|
||||||
|
raise RuntimeError(f"Synology Chat erreur: {body}")
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_pending_rows(conn) -> list[dict]:
|
||||||
|
sql = """
|
||||||
|
SELECT
|
||||||
|
Id_Journal,
|
||||||
|
DateHeure,
|
||||||
|
NomUtilisateur,
|
||||||
|
PosteClient,
|
||||||
|
TableurSource,
|
||||||
|
UtilisateurWindows,
|
||||||
|
SiteDemande,
|
||||||
|
ServiceDemande,
|
||||||
|
DSN,
|
||||||
|
BDD,
|
||||||
|
Statut,
|
||||||
|
Motif,
|
||||||
|
SessionID
|
||||||
|
FROM `Acces`.`JournalConnexions`
|
||||||
|
WHERE NotificationEnvoyee = 0
|
||||||
|
ORDER BY DateHeure ASC, Id_Journal ASC
|
||||||
|
LIMIT 50
|
||||||
|
"""
|
||||||
|
print("SQL fetch_pending_rows =")
|
||||||
|
print(sql)
|
||||||
|
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql)
|
||||||
|
return cur.fetchall()
|
||||||
|
|
||||||
|
|
||||||
|
def mark_sent(conn, row_id: int) -> None:
|
||||||
|
sql = """
|
||||||
|
UPDATE Acces.JournalConnexions
|
||||||
|
SET NotificationEnvoyee = 1,
|
||||||
|
DateNotification = NOW(),
|
||||||
|
ErreurNotification = NULL
|
||||||
|
WHERE Id_Journal = %s
|
||||||
|
"""
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql, (row_id,))
|
||||||
|
|
||||||
|
|
||||||
|
def mark_error(conn, row_id: int, error_msg: str) -> None:
|
||||||
|
sql = """
|
||||||
|
UPDATE `Acces`.`JournalConnexions`
|
||||||
|
SET ErreurNotification = %s
|
||||||
|
WHERE Id_Journal = %s
|
||||||
|
"""
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(sql, (error_msg[:255], row_id))
|
||||||
|
|
||||||
|
|
||||||
|
def process_once() -> None:
|
||||||
|
with get_connection() as conn:
|
||||||
|
rows = fetch_pending_rows(conn)
|
||||||
|
|
||||||
|
if not rows:
|
||||||
|
log.info("Aucune nouvelle connexion à notifier.")
|
||||||
|
return
|
||||||
|
|
||||||
|
log.info("%s connexion(s) à notifier.", len(rows))
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
row_id = row["Id_Journal"]
|
||||||
|
try:
|
||||||
|
message = format_message(row)
|
||||||
|
send_synology_chat(message)
|
||||||
|
mark_sent(conn, row_id)
|
||||||
|
log.info("Notification envoyée pour Id_Journal=%s", row_id)
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
log.exception("Erreur d'envoi pour Id_Journal=%s", row_id)
|
||||||
|
try:
|
||||||
|
mark_error(conn, row_id, str(exc))
|
||||||
|
except Exception:
|
||||||
|
log.exception("Impossible d'écrire ErreurNotification pour Id_Journal=%s", row_id)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
missing = [k for k, v in DB_CONFIG.items() if v is None and k != "port"]
|
||||||
|
if missing:
|
||||||
|
raise RuntimeError(f"Variables d'environnement manquantes : {', '.join(missing)}")
|
||||||
|
|
||||||
|
if not SYNO_CHAT_WEBHOOK:
|
||||||
|
raise RuntimeError("SYNO_CHAT_WEBHOOK_CONNEXIONS manquant")
|
||||||
|
|
||||||
|
log.info("Surveillance de JournalConnexions démarrée.")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
process_once()
|
||||||
|
except Exception:
|
||||||
|
log.exception("Erreur générale dans la boucle de surveillance")
|
||||||
|
time.sleep(POLL_INTERVAL)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -57,10 +57,12 @@ TABLES_SET = set(TABLES)
|
|||||||
DELAI_MINUTES = 15
|
DELAI_MINUTES = 15
|
||||||
RAPPEL_HEURES = 6
|
RAPPEL_HEURES = 6
|
||||||
|
|
||||||
SYNOLOGY_CHAT_WEBHOOK_URL = os.getenv("SYNOLOGY_CHAT_WEBHOOK_URL", "").strip()
|
def _env_str(name: str, default: str = "") -> str:
|
||||||
SYNOLOGY_CHAT_VERIFY_SSL = os.getenv("SYNOLOGY_CHAT_VERIFY_SSL", "true").strip().lower() in (
|
return (os.getenv(name, default) or "").strip()
|
||||||
"1", "true", "yes", "on"
|
|
||||||
)
|
def _env_bool(name: str, default: bool) -> bool:
|
||||||
|
value = _env_str(name, "1" if default else "0").lower()
|
||||||
|
return value in ("1", "true", "yes", "on")
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -201,19 +203,33 @@ def should_send_alert(site: str) -> bool:
|
|||||||
# NOTIFICATIONS
|
# NOTIFICATIONS
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def envoyer_chat(titre: str, message: str) -> None:
|
def envoyer_chat(site: str, titre: str, message: str) -> None:
|
||||||
if not SYNOLOGY_CHAT_WEBHOOK_URL:
|
webhook = (
|
||||||
logging.warning("Webhook Synology Chat non configuré : notification Chat ignorée.")
|
_env_str(f"SYNO_CHAT_WEBHOOK_MONITOR_{site}") or
|
||||||
|
_env_str(f"SYNO_CHAT_WEBHOOK_MONITOR_{site.upper()}") or
|
||||||
|
_env_str("SYNO_CHAT_WEBHOOK_MONITOR") or
|
||||||
|
_env_str(f"SYNO_CHAT_WEBHOOK_{site}") or
|
||||||
|
_env_str(f"SYNO_CHAT_WEBHOOK_{site.upper()}") or
|
||||||
|
_env_str("SYNO_CHAT_WEBHOOK")
|
||||||
|
)
|
||||||
|
|
||||||
|
if not webhook:
|
||||||
|
logging.warning(f"Webhook Synology Chat monitor non configuré pour {site} : notification Chat ignorée.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
verify_ssl = _env_bool("SYNO_CHAT_VERIFY_SSL", True)
|
||||||
|
botname = _env_str("SYNO_CHAT_BOTNAME_MONITOR", "Injection données dans tables")
|
||||||
|
|
||||||
texte = f"{titre}\n{message}"
|
texte = f"{titre}\n{message}"
|
||||||
payload = {"text": texte}
|
payload: dict[str, str] = {"text": texte}
|
||||||
|
if botname:
|
||||||
|
payload["username"] = botname
|
||||||
|
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
SYNOLOGY_CHAT_WEBHOOK_URL,
|
webhook,
|
||||||
data={"payload": json.dumps(payload, ensure_ascii=False)},
|
data={"payload": json.dumps(payload, ensure_ascii=False)},
|
||||||
timeout=10,
|
timeout=int(_env_str("SYNO_CHAT_TIMEOUT", "10")),
|
||||||
verify=SYNOLOGY_CHAT_VERIFY_SSL,
|
verify=verify_ssl,
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
@@ -224,10 +240,10 @@ def envoyer_chat(titre: str, message: str) -> None:
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
logging.info("💬 Notification Synology Chat envoyée.")
|
logging.info("💬 Notification Synology Chat envoyée pour %s.", site)
|
||||||
|
|
||||||
|
|
||||||
def envoyer_notifications(sujet: str, message: str) -> None:
|
def envoyer_notifications(site: str, sujet: str, message: str) -> None:
|
||||||
"""
|
"""
|
||||||
Envoie mail + chat.
|
Envoie mail + chat.
|
||||||
Lève une erreur si au moins un des deux canaux échoue.
|
Lève une erreur si au moins un des deux canaux échoue.
|
||||||
@@ -241,7 +257,7 @@ def envoyer_notifications(sujet: str, message: str) -> None:
|
|||||||
erreurs.append(f"mail: {e}")
|
erreurs.append(f"mail: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
envoyer_chat(sujet, message)
|
envoyer_chat(site, sujet, message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
erreurs.append(f"chat: {e}")
|
erreurs.append(f"chat: {e}")
|
||||||
|
|
||||||
@@ -293,6 +309,7 @@ def traiter_table(cursor, table: str, limite: datetime,
|
|||||||
if should_send_alert(table):
|
if should_send_alert(table):
|
||||||
try:
|
try:
|
||||||
envoyer_notifications(
|
envoyer_notifications(
|
||||||
|
table,
|
||||||
f"⚠️ ALERTE : erreur SQL sur {table}",
|
f"⚠️ ALERTE : erreur SQL sur {table}",
|
||||||
f"Erreur SQL détectée sur la table {table}.\n\nDétail :\n{e}"
|
f"Erreur SQL détectée sur la table {table}.\n\nDétail :\n{e}"
|
||||||
)
|
)
|
||||||
@@ -312,6 +329,7 @@ def traiter_table(cursor, table: str, limite: datetime,
|
|||||||
logging.warning(f"⚠️ {table} en défaut (dernier relevé : {last_update})")
|
logging.warning(f"⚠️ {table} en défaut (dernier relevé : {last_update})")
|
||||||
try:
|
try:
|
||||||
envoyer_notifications(
|
envoyer_notifications(
|
||||||
|
table,
|
||||||
f"⚠️ ALERTE : {table} absence de relevés",
|
f"⚠️ ALERTE : {table} absence de relevés",
|
||||||
f"Pas de relevés depuis plus de {DELAI_MINUTES} min.\nDernier relevé : {last_update}"
|
f"Pas de relevés depuis plus de {DELAI_MINUTES} min.\nDernier relevé : {last_update}"
|
||||||
)
|
)
|
||||||
@@ -339,6 +357,7 @@ def traiter_table(cursor, table: str, limite: datetime,
|
|||||||
message = f"✅ {table} : relevés à nouveau reçus (dernier : {last_update}). Situation normale."
|
message = f"✅ {table} : relevés à nouveau reçus (dernier : {last_update}). Situation normale."
|
||||||
try:
|
try:
|
||||||
envoyer_notifications(
|
envoyer_notifications(
|
||||||
|
table,
|
||||||
f"✅ OK : {table} relevés reçus",
|
f"✅ OK : {table} relevés reçus",
|
||||||
message
|
message
|
||||||
)
|
)
|
||||||
@@ -381,6 +400,7 @@ def main() -> None:
|
|||||||
logging.error(f"MySQL KO : {e}")
|
logging.error(f"MySQL KO : {e}")
|
||||||
try:
|
try:
|
||||||
envoyer_notifications(
|
envoyer_notifications(
|
||||||
|
"GLOBAL",
|
||||||
"⚠️ ALERTE : Base MySQL inaccessible",
|
"⚠️ ALERTE : Base MySQL inaccessible",
|
||||||
"Connexion MySQL impossible : la surveillance des relevés ne peut pas s’exécuter."
|
"Connexion MySQL impossible : la surveillance des relevés ne peut pas s’exécuter."
|
||||||
)
|
)
|
||||||
|
|||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
Reference in New Issue
Block a user