Files
scrap/pricewatch/app/core/logging.py
2026-01-13 19:49:04 +01:00

113 lines
3.2 KiB
Python
Executable File

"""
Configuration du système de logging pour PriceWatch.
Fournit un logger configuré avec formatage coloré et niveaux appropriés.
Les logs incluent : timestamp, niveau, module, et message.
"""
import logging
import sys
from typing import Optional
class ColoredFormatter(logging.Formatter):
"""Formatter avec couleurs pour améliorer la lisibilité en CLI."""
# Codes ANSI pour les couleurs
COLORS = {
"DEBUG": "\033[36m", # Cyan
"INFO": "\033[32m", # Vert
"WARNING": "\033[33m", # Jaune
"ERROR": "\033[31m", # Rouge
"CRITICAL": "\033[35m", # Magenta
}
RESET = "\033[0m"
BOLD = "\033[1m"
def format(self, record: logging.LogRecord) -> str:
"""Formate le log avec couleurs selon le niveau."""
# Copie pour éviter de modifier l'original
log_color = self.COLORS.get(record.levelname, self.RESET)
record.levelname = f"{log_color}{self.BOLD}{record.levelname}{self.RESET}"
# Colorer le nom du module
record.name = f"\033[90m{record.name}{self.RESET}"
return super().format(record)
def setup_logging(level: str = "INFO", enable_colors: bool = True) -> logging.Logger:
"""
Configure le logger racine de PriceWatch.
Args:
level: Niveau de log (DEBUG, INFO, WARNING, ERROR, CRITICAL)
enable_colors: Activer la colorisation (désactiver pour les logs fichier)
Returns:
Logger configuré
Justification technique:
- Handler unique sur stdout pour éviter les duplications
- Format détaillé avec timestamp ISO8601 pour faciliter le debug
- Colorisation optionnelle pour améliorer l'UX en CLI
"""
logger = logging.getLogger("pricewatch")
# Éviter d'ajouter plusieurs handlers si appelé plusieurs fois
if logger.handlers:
return logger
logger.setLevel(getattr(logging, level.upper(), logging.INFO))
logger.propagate = False
# Handler console
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logger.level)
# Format avec timestamp ISO8601
log_format = "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s"
date_format = "%Y-%m-%d %H:%M:%S"
if enable_colors and sys.stdout.isatty():
formatter = ColoredFormatter(log_format, datefmt=date_format)
else:
formatter = logging.Formatter(log_format, datefmt=date_format)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
return logger
def get_logger(name: Optional[str] = None) -> logging.Logger:
"""
Retourne un logger enfant de 'pricewatch'.
Args:
name: Nom du sous-module (ex: 'scraping.http')
Returns:
Logger configuré
"""
if name:
return logging.getLogger(f"pricewatch.{name}")
return logging.getLogger("pricewatch")
def set_level(level: str) -> None:
"""
Change dynamiquement le niveau de log.
Args:
level: Nouveau niveau (DEBUG, INFO, WARNING, ERROR, CRITICAL)
"""
logger = logging.getLogger("pricewatch")
logger.setLevel(getattr(logging, level.upper(), logging.INFO))
for handler in logger.handlers:
handler.setLevel(logger.level)
# Initialisation par défaut au premier import
_default_logger = setup_logging()