Source code for sci_watch.utils.logger

import logging
import os
from functools import wraps
from logging import FileHandler, Formatter, Logger
from pathlib import Path
from typing import Callable, Literal

import coloredlogs
import verboselogs

from sci_watch.core.settings import settings

_FORMAT = "[%(levelname)s] [%(process)d] [%(thread)d] [%(name)s] %(asctime)s.%(msecs)04d %(message)s"
_DATE_FORMAT = "%H:%M:%S"


[docs]def get_logger( logger_name: str, level: Literal[ "NOTSET", "DEBUG", "INFO", "WARNING", "ERROR", "FATAL", "CRITICAL" ] = settings.log_level, log_file_path: str | os.PathLike = settings.log_file_path, ) -> Logger: """ Logger getter function. Parameters ---------- logger_name: str Should be name of the file importing the logger level: str Minimum level of logging Returns ------- Logger: A ready to use logger object """ verboselogs.install() logger = logging.getLogger(logger_name) field_styles = { "asctime": {"color": "magenta"}, "msecs": {"color": "magenta"}, "hostname": {"color": "blue"}, "programname": {"color": "cyan"}, "name": {"color": "green"}, "process": {"color": "green", "bold": True}, "levelname": {"color": "black", "bold": True, "bright": True}, "message": {"color": "white", "bright": True}, } coloredlogs.install( level=level, logger=logger, fmt=_FORMAT, datefmt=_DATE_FORMAT, field_styles=field_styles, ) if log_file_path: log_path = Path(log_file_path) log_path.parent.mkdir(exist_ok=True, parents=True) file_handler = FileHandler(filename=log_path, mode="a+", encoding="utf-8") file_handler.setFormatter(Formatter(fmt=_FORMAT, datefmt=_DATE_FORMAT)) file_handler.setLevel(level) logger.addHandler(file_handler) return logger
[docs]def logging_wrapper(logger: Logger) -> Callable: """ Wrap an entire function in a try / except block in order to catch and *log* any Exception; such exceptions are propagated to the caller. Parameters ---------- logger: logging.Logger The logger to use for logging raised exceptions. Returns ------- callable: The decorated function wrapped in a try / except block with error propagation. """ def decorator_factory(func: Callable): @wraps(func) def with_logging(*args, **kwargs): try: return func(*args, **kwargs) except Exception: logger.exception("An unexpected exception was raised") raise return with_logging return decorator_factory