Coverage for /usr/lib/python3.10/site-packages/hyd/backend/util/logger.py: 88%
24 statements
« prev ^ index » next coverage.py v7.0.3, created at 2023-01-05 15:47 +0000
« prev ^ index » next coverage.py v7.0.3, created at 2023-01-05 15:47 +0000
1"""
2Module creating a basic logger setup with our preferred configuration style for the hyd package.
4Author: Jendrik A. Potyka, Fabian A. Preiss.
5"""
6import logging
7from logging import Handler, Logger, LoggerAdapter, StreamHandler, getLogger
8from typing import TYPE_CHECKING
10# Necessary until python3.11 (https://github.com/python/typeshed/issues/7855)
11# in future just use LoggerAdapter[Logger]
12if TYPE_CHECKING:
13 _LoggerAdapter = LoggerAdapter[Logger]
14else:
15 _LoggerAdapter = LoggerAdapter
18class HydLogger(_LoggerAdapter):
19 """
20 Custom logger wrapping around the logging.Logger class.
22 Parameters
23 ----------
24 class_name : str
25 Instance of the class the logger will be used inside of
26 level : int
27 loglevel where `FATAL = 50, ERROR = 40, WARNING = 30,
28 INFO = 20, DEBUG = 10, NOTSET = 0`
30 Notes
31 -----
32 It is recommended to declare a separate logger object for every class using logging.
33 Using the directive ``HydLogger(type(self).__name__, level)`` inside of the ``__init__``
34 function and running the ``super().__init__(level)`` from a child of said class provides
35 a separate logger instance for each class as intended. Given the following definitions:
37 >>> class Parent:
38 ... def __init__(self, level: Optional[int] = logging.INFO):
39 ... self.__log = HydLogger(type(self).__name__, level)
40 ...
41 ... @property
42 ... def log(self):
43 ... return self.__log
44 ...
45 >>> class Child(Parent):
46 ... def __init__(self, level: Optional[int] = logging.INFO):
47 ... super().__init__(level)
48 ...
49 >>> def main():
50 ... parent = Parent()
51 ... parent.log.info("foo")
52 ... parent.log.warning("bar")
53 ...
54 ... child = Child(logging.WARNING)
55 ... child.log.warning("foo")
57 Finally
59 >>> main()
61 Generates an output similar to:
63 ::
65 [2021-04-20 14:18:48][INFO][Parent][main] foo
66 [2021-04-20 14:18:48][WARNING][Parent][main] bar
67 [2021-04-20 14:18:48][WARNING][Child][main] foo
68 """
70 def __init__(self, class_name: str = "Script", level: int = logging.INFO):
72 self.logger: Logger = getLogger(class_name)
73 handlers: list[Handler] = self.logger.handlers
74 self.__console_handler: Handler
76 if not handlers:
77 self.logger.setLevel(logging.DEBUG)
79 log_format = "[%(asctime)s][%(levelname)s][%(name)s][%(funcName)s] %(message)s"
80 log_formatter = logging.Formatter(
81 log_format,
82 "%Y-%m-%d %H:%M:%S",
83 )
85 self.__console_handler = StreamHandler()
86 self.__console_handler.setFormatter(log_formatter)
87 self.__console_handler.setLevel(level)
88 self.logger.addHandler(self.__console_handler)
89 else:
90 self.__console_handler = handlers[0]
92 def setLevel(self, level: int | str = logging.INFO) -> None:
93 self.__console_handler.setLevel(level)
95 def process(self, msg, kwargs):
96 return msg, kwargs