Coverage for C:\src\imod-python\imod\logging\pythonlogger.py: 92%

37 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-08 13:27 +0200

1import logging 

2import sys 

3 

4from imod.logging.ilogger import ILogger 

5from imod.logging.loglevel import LogLevel 

6 

7 

8def _formatter(): 

9 return logging.Formatter( 

10 "%(name)s: %(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(process)d >>> %(message)s" 

11 ) 

12 

13 

14def _stack_level(additional_depth: int) -> int: 

15 """ 

16 The stack level is used to print the file and line number of the line being logged. 

17 Because there are a few layers between the place where the imod logger is used and 

18 the place where the pyton logger is used we need to set a custom stack level. 

19 

20 An additional_depth can be provided to add to this default stack level. 

21 This is useful when a decorator is added which introduces an additional level between 

22 the imod logger and the python logger. 

23 """ 

24 

25 default_stack_level = 3 

26 return default_stack_level + additional_depth 

27 

28 

29class PythonLogger(ILogger): 

30 """ 

31 The :class:`PythonLogger` is used to log messages using the default python logging framework. 

32 """ 

33 

34 def __init__( 

35 self, 

36 log_level: LogLevel, 

37 add_default_stream_handler: bool, 

38 add_default_file_handler: bool, 

39 ) -> None: 

40 self.logger = logging.getLogger("imod") 

41 self._set_level(log_level) 

42 

43 if add_default_stream_handler: 

44 self._add_stream_handler() 

45 if add_default_file_handler: 

46 self._add_file_handler() 

47 

48 def debug(self, message: str, additional_depth: int = 0) -> None: 

49 self.logger.debug(message, stacklevel=_stack_level(additional_depth)) 

50 

51 def info(self, message: str, additional_depth: int = 0) -> None: 

52 self.logger.info(message, stacklevel=_stack_level(additional_depth)) 

53 

54 def warning(self, message: str, additional_depth: int = 0) -> None: 

55 self.logger.warning(message, stacklevel=_stack_level(additional_depth)) 

56 

57 def error(self, message: str, additional_depth: int = 0) -> None: 

58 self.logger.error(message, stacklevel=_stack_level(additional_depth)) 

59 

60 def critical(self, message: str, additional_depth: int = 0) -> None: 

61 self.logger.critical(message, stacklevel=_stack_level(additional_depth)) 

62 

63 def _set_level(self, log_level: LogLevel) -> None: 

64 self.logger.setLevel(log_level.value) 

65 

66 def _add_stream_handler(self) -> None: 

67 stdout = logging.StreamHandler(stream=sys.stdout) 

68 stdout.setFormatter(_formatter()) 

69 

70 self.logger.addHandler(stdout) 

71 

72 def _add_file_handler(self) -> None: 

73 file = logging.FileHandler("imod-python.log") 

74 file.setFormatter(_formatter()) 

75 

76 self.logger.addHandler(file)