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)