import os import smtplib import logging from datetime import datetime, timezone, timedelta from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import psycopg2 from app.core.config import ( DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD, MAIL_HOST, MAIL_PORT, MAIL_FROM, WATCHDOG_RECIPIENT_EMAILS, WATCHDOG_CC_EMAILS, ) STALE_THRESHOLD_H = 1 COOLDOWN_H = 2 COOLDOWN_FILE = '/tmp/etl_alert_sent' logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s: %(message)s') log = logging.getLogger(__name__) def get_last_run(): conn = psycopg2.connect( host=DB_HOST, port=DB_PORT, dbname=DB_NAME, user=DB_USER, password=DB_PASSWORD, connect_timeout=5, ) try: cur = conn.cursor() cur.execute("SELECT source, last_run_at FROM watermarks ORDER BY last_run_at DESC LIMIT 1") return cur.fetchone() finally: conn.close() def in_cooldown(): if not os.path.exists(COOLDOWN_FILE): return False mtime = datetime.fromtimestamp(os.path.getmtime(COOLDOWN_FILE), tz=timezone.utc) return (datetime.now(timezone.utc) - mtime) < timedelta(hours=COOLDOWN_H) def mark_cooldown(): with open(COOLDOWN_FILE, 'w') as f: f.write(datetime.now(timezone.utc).isoformat()) def clear_cooldown(): if os.path.exists(COOLDOWN_FILE): os.remove(COOLDOWN_FILE) def build_html(source, last_run_at, horas, mins): last_run_brt = last_run_at - timedelta(hours=3) last_run_str = last_run_brt.strftime('%d/%m %H:%M BRT') tempo_str = f"{horas}h{mins:02d}min" return f"""
O pipeline de dados do WiFi da Heineken House está parado há mais de {STALE_THRESHOLD_H}h. Os dados do dashboard podem estar desatualizados. Dê uma olhada quando puder.
| Última fonte {source} | Última execução {last_run_str} | Tempo parado {tempo_str} |
Este alerta não será repetido nas próximas {COOLDOWN_H}h. Se o problema persistir, um novo aviso será enviado automaticamente.