Coverage for mlair/helpers/logger.py: 100%

24 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2023-06-30 10:22 +0000

1"""Logger class.""" 

2import logging 

3import os 

4import time 

5from ..configuration import ROOT_PATH 

6 

7 

8class Logger: 

9 """ 

10 Basic logger class to unify all logging outputs. 

11 

12 Logs are saved in local file and returned to std output. In default settings, logging level of file logger is DEBUG, 

13 logging level of stream logger is INFO. Class must be imported and initialised in starting script, all subscripts 

14 should log with logging.info(), debug, ... 

15 """ 

16 

17 def __init__(self, log_path=None, level_file=logging.DEBUG, level_stream=logging.INFO): 

18 """Construct logger.""" 

19 # define shared logger format 

20 self.formatter = '%(asctime)s - %(levelname)s: %(message)s [%(filename)s:%(funcName)s:%(lineno)s]' 

21 

22 # assure defaults 

23 level_stream = level_stream or logging.INFO 

24 level_file = level_file or logging.DEBUG 

25 

26 # set log path 

27 self.log_file = self.setup_logging_path(log_path) 

28 # set root logger as file handler 

29 logging.basicConfig(level=level_file, 

30 format=self.formatter, 

31 filename=self.log_file, 

32 filemode='a') 

33 # add stream handler to the root logger 

34 logging.getLogger('').addHandler(self.logger_console(level_stream)) 

35 # print logger path 

36 logging.info(f"File logger: {self.log_file}") 

37 

38 @staticmethod 

39 def setup_logging_path(path: str = None): 

40 """ 

41 Check if given path exists and creates if not. 

42 

43 If path is None, use path from main. The logging file is named like `logging_<runtime>.log` where 

44 runtime=`%Y-%m-%d_%H-%M-%S` of current run. 

45 

46 :param path: path to logfile 

47 

48 :return: path of logfile 

49 """ 

50 if not path: # set default path 

51 path = os.path.join(ROOT_PATH, "logging") 

52 if not os.path.exists(path): 

53 os.makedirs(path) 

54 runtime = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime()) 

55 log_file = os.path.join(path, f'logging_{runtime}.log') 

56 return log_file 

57 

58 def logger_console(self, level: int): 

59 """ 

60 Define a stream handler which writes messages of given level or higher to std out. 

61 

62 :param level: logging level as integer, e.g. logging.DEBUG or 10 

63 

64 :return: defines stream handler 

65 """ 

66 # define Handler 

67 console = logging.StreamHandler() 

68 # set level of Handler 

69 console.setLevel(level) 

70 # set a format which is simpler for console use 

71 formatter = logging.Formatter(self.formatter) 

72 # tell the handler to use this format 

73 console.setFormatter(formatter) 

74 return console