Source code for hyd.backend.util.logger

"""
Module creating a basic logger setup with our preferred configuration style for the hyd package.

Author: Jendrik A. Potyka, Fabian A. Preiss.
"""
import logging
from logging import Handler, Logger, LoggerAdapter, StreamHandler, getLogger
from typing import TYPE_CHECKING

# Necessary until python3.11 (https://github.com/python/typeshed/issues/7855)
# in future just use LoggerAdapter[Logger]
if TYPE_CHECKING:
    _LoggerAdapter = LoggerAdapter[Logger]
else:
    _LoggerAdapter = LoggerAdapter


[docs]class HydLogger(_LoggerAdapter): """ Custom logger wrapping around the logging.Logger class. Parameters ---------- class_name : str Instance of the class the logger will be used inside of level : int loglevel where `FATAL = 50, ERROR = 40, WARNING = 30, INFO = 20, DEBUG = 10, NOTSET = 0` Notes ----- It is recommended to declare a separate logger object for every class using logging. Using the directive ``HydLogger(type(self).__name__, level)`` inside of the ``__init__`` function and running the ``super().__init__(level)`` from a child of said class provides a separate logger instance for each class as intended. Given the following definitions: >>> class Parent: ... def __init__(self, level: Optional[int] = logging.INFO): ... self.__log = HydLogger(type(self).__name__, level) ... ... @property ... def log(self): ... return self.__log ... >>> class Child(Parent): ... def __init__(self, level: Optional[int] = logging.INFO): ... super().__init__(level) ... >>> def main(): ... parent = Parent() ... parent.log.info("foo") ... parent.log.warning("bar") ... ... child = Child(logging.WARNING) ... child.log.warning("foo") Finally >>> main() Generates an output similar to: :: [2021-04-20 14:18:48][INFO][Parent][main] foo [2021-04-20 14:18:48][WARNING][Parent][main] bar [2021-04-20 14:18:48][WARNING][Child][main] foo """ def __init__(self, class_name: str = "Script", level: int = logging.INFO): self.logger: Logger = getLogger(class_name) handlers: list[Handler] = self.logger.handlers self.__console_handler: Handler if not handlers: self.logger.setLevel(logging.DEBUG) log_format = "[%(asctime)s][%(levelname)s][%(name)s][%(funcName)s] %(message)s" log_formatter = logging.Formatter( log_format, "%Y-%m-%d %H:%M:%S", ) self.__console_handler = StreamHandler() self.__console_handler.setFormatter(log_formatter) self.__console_handler.setLevel(level) self.logger.addHandler(self.__console_handler) else: self.__console_handler = handlers[0]
[docs] def setLevel(self, level: int | str = logging.INFO) -> None: self.__console_handler.setLevel(level)
[docs] def process(self, msg, kwargs): return msg, kwargs