Fix: Mail-Alerts per Fingerprint deduplizieren — jede Mail nur einmal melden, nie wiederholen
This commit is contained in:
parent
7454db1bc6
commit
f7417f6517
1 changed files with 33 additions and 16 deletions
|
|
@ -11,13 +11,12 @@ sys.path.insert(0, os.path.dirname(__file__))
|
||||||
from core import config, loki_client, proxmox_client, mail_client
|
from core import config, loki_client, proxmox_client, mail_client
|
||||||
|
|
||||||
ALERT_STATE_FILE = os.path.join(os.path.dirname(__file__), ".alert_state.json")
|
ALERT_STATE_FILE = os.path.join(os.path.dirname(__file__), ".alert_state.json")
|
||||||
ALERT_COOLDOWN_MINUTES = {
|
ALERT_COOLDOWN_SECONDS = {
|
||||||
"mail": 120,
|
"container": 1800,
|
||||||
"container": 30,
|
"ram": 1800,
|
||||||
"ram": 30,
|
"panic": 3600,
|
||||||
"panic": 60,
|
"silence": 3600,
|
||||||
"silence": 60,
|
"default": 3600,
|
||||||
"default": 60,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -94,8 +93,26 @@ def check_all() -> list[str]:
|
||||||
mail_client.init(cfg)
|
mail_client.init(cfg)
|
||||||
important = mail_client.get_important_mails(hours=1)
|
important = mail_client.get_important_mails(hours=1)
|
||||||
if important and "error" not in important[0]:
|
if important and "error" not in important[0]:
|
||||||
senders = [m["from"][:30] for m in important]
|
state = _load_alert_state()
|
||||||
alerts.append(f"📧 {len(important)} wichtige Mail(s) (letzte Stunde): {', '.join(senders)}")
|
seen = state.get("seen_mails", {})
|
||||||
|
now = datetime.now(timezone.utc).timestamp()
|
||||||
|
|
||||||
|
new_mails = []
|
||||||
|
for m in important:
|
||||||
|
fp = hashlib.md5(
|
||||||
|
f"{m.get('date_str','')}|{m.get('from','')}|{m.get('subject','')}".encode()
|
||||||
|
).hexdigest()
|
||||||
|
if fp not in seen:
|
||||||
|
new_mails.append(m)
|
||||||
|
seen[fp] = now
|
||||||
|
|
||||||
|
seen = {k: v for k, v in seen.items() if now - v < 172800}
|
||||||
|
state["seen_mails"] = seen
|
||||||
|
_save_alert_state(state)
|
||||||
|
|
||||||
|
if new_mails:
|
||||||
|
senders = [m["from"][:30] for m in new_mails]
|
||||||
|
alerts.append(f"📧 {len(new_mails)} neue wichtige Mail(s): {', '.join(senders)}")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -160,8 +177,6 @@ def _alert_key(alert_text: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def _alert_category(alert_text: str) -> str:
|
def _alert_category(alert_text: str) -> str:
|
||||||
if "📧" in alert_text or "Mail" in alert_text:
|
|
||||||
return "mail"
|
|
||||||
if "CT " in alert_text and "ist " in alert_text:
|
if "CT " in alert_text and "ist " in alert_text:
|
||||||
return "container"
|
return "container"
|
||||||
if "RAM " in alert_text:
|
if "RAM " in alert_text:
|
||||||
|
|
@ -174,24 +189,26 @@ def _alert_category(alert_text: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def _filter_new_alerts(alerts: list[str]) -> list[str]:
|
def _filter_new_alerts(alerts: list[str]) -> list[str]:
|
||||||
"""Filtert bereits gemeldete Alerts. Gibt nur neue/fällige zurück."""
|
"""Filtert bereits gemeldete Infra-Alerts per Cooldown. Mails werden separat in check_all() dedupliziert."""
|
||||||
state = _load_alert_state()
|
state = _load_alert_state()
|
||||||
now = datetime.now(timezone.utc).timestamp()
|
now = datetime.now(timezone.utc).timestamp()
|
||||||
|
cooldowns = state.get("alert_cooldowns", {})
|
||||||
new_alerts = []
|
new_alerts = []
|
||||||
|
|
||||||
for alert in alerts:
|
for alert in alerts:
|
||||||
key = _alert_key(alert)
|
key = _alert_key(alert)
|
||||||
cat = _alert_category(alert)
|
cat = _alert_category(alert)
|
||||||
cooldown = ALERT_COOLDOWN_MINUTES.get(cat, 60) * 60
|
cooldown = ALERT_COOLDOWN_SECONDS.get(cat, 3600)
|
||||||
|
|
||||||
last_sent = state.get(key, {}).get("ts", 0)
|
last_sent = cooldowns.get(key, {}).get("ts", 0)
|
||||||
if now - last_sent > cooldown:
|
if now - last_sent > cooldown:
|
||||||
new_alerts.append(alert)
|
new_alerts.append(alert)
|
||||||
state[key] = {"ts": now, "text": alert[:80], "cat": cat}
|
cooldowns[key] = {"ts": now, "text": alert[:80], "cat": cat}
|
||||||
|
|
||||||
cutoff = now - 86400
|
cutoff = now - 86400
|
||||||
state = {k: v for k, v in state.items() if v.get("ts", 0) > cutoff}
|
cooldowns = {k: v for k, v in cooldowns.items() if v.get("ts", 0) > cutoff}
|
||||||
|
|
||||||
|
state["alert_cooldowns"] = cooldowns
|
||||||
_save_alert_state(state)
|
_save_alert_state(state)
|
||||||
return new_alerts
|
return new_alerts
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue