Source code for pantea.logger

import logging
import sys
from logging.handlers import RotatingFileHandler
from pathlib import Path
from typing import Any


[docs]class Logger: """ An utility logger class which allows more tweaks than the standard python logging. """ def __init__(self, level=logging.WARNING, filename=None) -> None: self.logger: Logger = logging.getLogger("Pantea") # type: ignore self.level: int = level self.handlers = list() self._add_console_handler() if filename: self._add_file_handler(filename) for handler in logging.root.handlers: logging.root.removeHandler(handler) logging.basicConfig(level=logging.DEBUG, handlers=self.handlers) # Avoiding matplotlib debug messages logging.getLogger("matplotlib").setLevel(logging.ERROR) logging.getLogger("matplotlib.font_manager").disabled = True logging.getLogger("jax").setLevel(logging.WARNING)
[docs] def set_level(self, level) -> None: """ Set the console logging level. :param level: INFO, WARNING, ERROR, and DEBUG """ self.level = level logging.root.handlers[0].setLevel(self.level)
def _add_console_handler(self) -> None: """ Prepare console handler and adding it as a default handler. """ console_handler = logging.StreamHandler(sys.stderr) console_handler.setFormatter( logging.Formatter("%(levelname)s | %(message)s") ) console_handler.setLevel(self.level) self.handlers.append(console_handler) def _add_file_handler(self, filename: Path) -> None: """ Add a file handler to the logging. :param filename: output log file name :type filename: Path """ # File handler is also useful for multi-process logging. file_handler = RotatingFileHandler(str(Path(filename)), "a", 1_000_000, 3) file_handler.setFormatter( logging.Formatter( "%(levelname)-8s | %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p" ) ) file_handler.setLevel(logging.DEBUG) self.handlers.append(file_handler)
[docs] def debug(self, msg, *args, **kwargs) -> None: self.logger.debug(msg, *args, **kwargs)
[docs] def info(self, msg, *args, **kwargs) -> None: self.logger.info(msg, *args, **kwargs)
[docs] def warning(self, msg, *args, **kwargs) -> None: self.logger.warning(msg, *args, **kwargs)
[docs] def warn(self, msg, *args, **kwargs) -> None: self.warning(msg, *args, **kwargs)
[docs] def error(self, msg, exception: Any = None, *args, **kwargs) -> None: self.logger.error(msg, *args, **kwargs) if exception is not None: raise exception(msg)
# Create the global logger object logger = Logger() # filename="debug.log"
[docs]def set_logging_level(level: int) -> None: """ Set the global logging level :param level: INFO, WARNING, ERROR, and DEBUG :type level: int (logging) """ logger.set_level(level)
[docs]class LoggingContextManager: """ This utility class allows to monitor logging messages with different level (e.g. INFO or DEBUG) for a particular section of the scripts. """ def __init__(self, level) -> None: self.level = level self.current_level = None def __enter__(self) -> Logger: global logger self.current_level = logger.level logger.set_level(self.level) return logger def __exit__(self, type, value, traceback) -> None: global logger logger.set_level(self.current_level)