import logging import sys import re # Couleurs ANSI par niveau de log COLOR_CODES = { logging.DEBUG: "\033[94m", # Bleu logging.INFO: "\033[92m", # Vert logging.WARNING: "\033[93m", # Jaune logging.ERROR: "\033[91m", # Rouge logging.CRITICAL: "\033[1;91m", # Rouge vif } RESET = "\033[0m" # Supprime les codes ANSI (pour l'écriture dans les fichiers) def strip_ansi_codes(text): ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') return ansi_escape.sub('', text) # Formatter pour la console avec couleurs class ConsoleFormatter(logging.Formatter): def format(self, record): color = COLOR_CODES.get(record.levelno, "") message = super().format(record) return f"{color}{message}{RESET}" # Formatter pour le fichier sans les couleurs class FileFormatter(logging.Formatter): def format(self, record): clean_msg = strip_ansi_codes(record.getMessage()) record_copy = logging.LogRecord( name=record.name, level=record.levelno, pathname=record.pathname, lineno=record.lineno, msg=clean_msg, args=(), exc_info=record.exc_info, func=record.funcName, sinfo=record.stack_info ) return super().format(record_copy) # Fonction de configuration du logger def setup_logger(logfile="app.log", debug_log=False): logger = logging.getLogger("Logger") logger.setLevel(logging.DEBUG) # Toujours logger tout (filtrage par handler) logger.handlers.clear() # Détermine le niveau de log selon la variable min_level = logging.DEBUG if debug_log else logging.INFO # Console handler console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(min_level) console_formatter = ConsoleFormatter("%(levelname)s: %(message)s") console_handler.setFormatter(console_formatter) logger.addHandler(console_handler) # File handler file_handler = logging.FileHandler(logfile, encoding="utf-8") file_handler.setLevel(min_level) file_formatter = FileFormatter("%(asctime)s - %(levelname)s - %(message)s") file_handler.setFormatter(file_formatter) logger.addHandler(file_handler) return logger