#!/usr/bin/env python3 """ Structured logging for email worker with Daily Rotation """ import os import sys import logging import threading from logging.handlers import TimedRotatingFileHandler from datetime import datetime # Konfiguration LOG_DIR = "/var/log/email-worker" LOG_FILE = os.path.join(LOG_DIR, "worker.log") # Logger initialisieren logger = logging.getLogger("unified-worker") logger.setLevel(logging.INFO) logger.propagate = False # Formatierung definieren: [Timestamp] [Level] [Thread] Nachricht # Hinweis: worker_name wird in der Funktion 'log' manuell eingefügt formatter = logging.Formatter( '[%(asctime)s] [%(levelname)s] [%(threadName)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 1. Console Handler (damit 'docker logs' weiterhin etwas anzeigt) console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(formatter) logger.addHandler(console_handler) # 2. File Handler mit täglicher Rotation # Prüfen, ob das Verzeichnis schreibbar ist (durch Docker Volume Mount) if os.path.exists(LOG_DIR): try: # when="midnight": Rotiert jede Nacht um 00:00 Uhr # backupCount=30: Behält Logs für 30 Tage file_handler = TimedRotatingFileHandler( LOG_FILE, when="midnight", interval=1, backupCount=30, encoding='utf-8' ) file_handler.setFormatter(formatter) # Suffix für rotierte Dateien: worker.log.2023-10-27 file_handler.suffix = "%Y-%m-%d" logger.addHandler(file_handler) except Exception as e: print(f"⚠ Logging Setup Error: Could not create file handler: {e}") def log(message: str, level: str = 'INFO', worker_name: str = 'unified-worker'): """ Structured logging with timestamp and thread info. Drop-In Replacement for original print-based logging. """ # Mapping von String-Levels zu logging Konstanten lvl_map = { 'DEBUG': logging.DEBUG, 'INFO': logging.INFO, 'WARNING': logging.WARNING, 'ERROR': logging.ERROR, 'CRITICAL': logging.CRITICAL, 'SUCCESS': logging.INFO # 'SUCCESS' gibt es im Standard nicht, wir nutzen INFO } log_level = lvl_map.get(level.upper(), logging.INFO) # Prefix für SUCCESS Level manuell hinzufügen, da es im Standard-Logging fehlt prefix = "" if level.upper() == 'SUCCESS': prefix = "[SUCCESS] " # Den worker_name in die Nachricht integrieren final_message = f"[{worker_name}] {prefix}{message}" logger.log(log_level, final_message)