Source code for gratools.logger_config
import logging
import logging.config
import click
from pathlib import Path
import sys
from rich import get_console
from rich.traceback import install, Traceback
from rich.console import Console
# Définir des couleurs pour les différents niveaux de log
available_colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
                    'bright_black', 'bright_red', 'bright_green', 'bright_yellow', 'bright_blue', 'bright_magenta', 'bright_cyan', 'bright_white']
# https://click.palletsprojects.com/en/8.1.x/api/#click.style
LOG_COLORS = {
    'DEBUG': 'magenta',
    'INFO': 'cyan',
    'WARNING': 'yellow',
    'ERROR': 'red',
    'CRITICAL': 'bright_red',
    'FATAL': 'bright_red',
}
# Classe personnalisée pour ajouter des couleurs aux messages de log
[docs]
class ColoredFormatter(logging.Formatter):
    def __init__(self, fmt, datefmt, debug, verbosity):
        super().__init__(fmt, datefmt)
        self.debug = debug
        self.verbosity = verbosity
[docs]
    def format(self, record):
        # Formatage de l'exception si présente
        traceback_message = None
        log_message = super().format(record)
        colored_log_message = click.style(log_message, fg=LOG_COLORS.get(record.levelname, 'white'))
        # Ajouter le texte de l'exception formatée uniquement pour le mode DEBUG
        if self.verbosity == 'DEBUG' and record.exc_info:
            # Utiliser rich.Traceback pour formater l'exception
            traceback = Traceback.from_exception(*record.exc_info)
            console = get_console() or Console()
            with console.capture() as capture:
                console.print(traceback)
            traceback_message = capture.get()
        log_message = colored_log_message
        if traceback_message:
            log_message = traceback_message + "\n" + colored_log_message
        # Interrompre le programme en cas d'erreur critique ou fatale
        if record.levelno >= logging.ERROR:
            sys.exit(f"{log_message}\n")
        return log_message
[docs]
def configure_logger(name, log_path, verbosity):
    basenameLog = Path(log_path).joinpath(f"{name}_log")
    debug = False
    verbosity = verbosity.upper()
    if verbosity == 'DEBUG':
        debug = True
        install(show_locals=True)  # Installer rich.traceback
    logging.config.dictConfig({
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': f'%(asctime)s | {"%(name)-8s | %(funcName)-22s |" if debug else ""} %(levelname)-8s | %(message)s',
                'datefmt': '%m-%d %H:%M',
            },
            'colored': {
                '()': lambda: ColoredFormatter(
                    f'%(asctime)s | {"%(name)-8s | %(funcName)-22s |" if debug else ""} %(levelname)-8s | %(message)s',
                    '%m-%d %H:%M',
                    debug,
                    verbosity
                ),
            },
        },
        'handlers': {
            'stdout_handler': {
                'level': verbosity,
                'class': 'logging.StreamHandler',
                'formatter': 'colored',
                'stream': 'ext://sys.stdout',
            },
            'logHandler': {
                'level': verbosity,
                'filename': f"{basenameLog}.o",
                'class': 'logging.FileHandler',
                'formatter': 'standard',
                'mode': 'w',
            },
            'errorLogHandler': {
                'level': 'WARNING',
                'filename': f"{basenameLog}.e",
                'class': 'logging.FileHandler',
                'formatter': 'standard',
                'mode': 'w',
            },
        },
        'loggers': {
            "": {
                'handlers': ['stdout_handler', 'logHandler', 'errorLogHandler'],
                'level': verbosity,
                'propagate': True,
            },
        }
    })
    return logging.getLogger(name)
[docs]
def update_logger_file_paths(logger, new_log_path, name):
    basenameLog = Path(new_log_path).joinpath(f"{name}_log")
    # Remplacer les gestionnaires de fichiers existants par de nouveaux gestionnaires
    for handler in logger.handlers:
        if isinstance(handler, logging.FileHandler):
            if handler.level == logging.WARNING:
                new_handler = logging.FileHandler(f"{basenameLog}.e", mode='w')
            else:
                new_handler = logging.FileHandler(f"{basenameLog}.o", mode='w')
            new_handler.setFormatter(handler.formatter)
            new_handler.setLevel(handler.level)
            logger.removeHandler(handler)
            logger.addHandler(new_handler)
# Exemple d'utilisation
if __name__ == "__main__":
    logger = configure_logger('my_logger', '.', 'DEBUG')
    try:
        # Code qui peut générer une exception
        1 / 0
    except Exception as e:
        logger.error("An error occurred", exc_info=True)