Coverage for lisacattools/custom_logging.py: 74%

46 statements  

« prev     ^ index     » next       coverage.py v7.0.5, created at 2023-01-13 12:12 +0000

1# -*- coding: utf-8 -*- 

2# Copyright (C) 2020-2021 - Centre National d'Etudes Spatiales 

3# jean-christophe.malapert@cnes.fr 

4# 

5# This file is part of smt_crawler_lib. 

6# 

7# smt_crawler_lib is a free software; you can redistribute it and/or 

8# modify it under the terms of the GNU Lesser General Public 

9# License as published by the Free Software Foundation; either 

10# version 3.0 of the License, or (at your option) any later version. 

11# 

12# This library is distributed in the hope that it will be useful, 

13# but WITHOUT ANY WARRANTY; without even the implied warranty of 

14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 

15# Lesser General Public License for more details. 

16# 

17# You should have received a copy of the GNU Lesser General Public 

18# License along with this library; if not, write to the Free Software 

19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 

20# MA 02110-1301 USA 

21"""Module for customizing ths logs.""" 

22import logging 

23from typing import Optional 

24 

25 

26class UtilsLogs: 

27 """Utility class for logs.""" 

28 

29 @staticmethod 

30 def addLoggingLevel( 

31 levelName: str, levelNum: int, methodName: Optional[str] = None 

32 ) -> None: 

33 """Add a new logging level to the `logging` module. 

34 

35 Parameters 

36 ---------- 

37 levelName: str 

38 level name of the logging 

39 levelNum: int 

40 level number related to the level name 

41 methodName: Optional[str] 

42 method for both `logging` itself and the class returned by 

43 `logging.Logger` 

44 

45 Returns 

46 ------- 

47 None 

48 

49 Raises 

50 ------ 

51 AttributeError 

52 If this levelName or methodName is already defined in the 

53 logger. 

54 

55 """ 

56 if not methodName: 

57 methodName = levelName.lower() 

58 

59 def logForLevel(self, message, *args, **kwargs): 

60 if self.isEnabledFor(levelNum): 

61 self._log(levelNum, message, args, **kwargs) 

62 

63 def logToRoot(message, *args, **kwargs): 

64 logging.log(levelNum, message, *args, **kwargs) 

65 

66 logging.addLevelName(levelNum, levelName) 

67 setattr(logging, levelName, levelNum) 

68 setattr(logging.getLoggerClass(), methodName, logForLevel) 

69 setattr(logging, methodName, logToRoot) 

70 

71 

72class LogRecord(logging.LogRecord): 

73 """Specific class to handle output in logs.""" 

74 

75 def getMessage(self) -> str: 

76 """Return the message. 

77 

78 Format the message according to the type of the message. 

79 

80 Returns 

81 ------- 

82 str 

83 the message 

84 """ 

85 msg = str(self.msg) 

86 if isinstance(self.args, dict): 

87 return msg.format(self.args) 

88 return msg % self.args if self.args else msg 

89 

90 

91class CustomColorFormatter(logging.Formatter): 

92 """Color formatter.""" 

93 

94 UtilsLogs.addLoggingLevel("TRACE", 15) 

95 # Reset 

96 color_Off = "\033[0m" # Text Reset 

97 

98 log_colors = { 

99 logging.TRACE: "\033[0;36m", # cyan 

100 logging.DEBUG: "\033[1;34m", # blue 

101 logging.INFO: "\033[0;32m", # green 

102 logging.WARNING: "\033[1;33m", # yellow 

103 logging.ERROR: "\033[1;31m", # red 

104 logging.CRITICAL: "\033[1;41m", # red reverted 

105 } 

106 

107 def format(self, record: LogRecord) -> str: # type: ignore 

108 """Format the log. 

109 

110 Parameters 

111 ---------- 

112 record: LogRecord 

113 the log record 

114 

115 Returns 

116 ------- 

117 str 

118 the formatted log record 

119 """ 

120 record.levelname = "{}{}{}".format( 

121 CustomColorFormatter.log_colors[record.levelno], 

122 record.levelname, 

123 CustomColorFormatter.color_Off, 

124 ) 

125 record.msg = "{}{}{}".format( 

126 CustomColorFormatter.log_colors[record.levelno], 

127 record.msg, 

128 CustomColorFormatter.color_Off, 

129 ) 

130 

131 # Select the formatter according to the log if several handlers are 

132 # attached to the logger 

133 my_formatter = logging.Formatter 

134 my_handler = None 

135 handlers = logging.getLogger(__name__).handlers 

136 for handler in handlers: 

137 handler_level = handler.level 

138 if ( 

139 handler_level 

140 == logging.getLogger(__name__).getEffectiveLevel() 

141 ): 

142 my_formatter._fmt = handler.formatter._fmt 

143 my_handler = handler 

144 break 

145 if my_handler is not None: 

146 [ 

147 logging.getLogger(__name__).removeHandler(handler) 

148 for handler in handlers 

149 if handler != my_handler 

150 ] 

151 return my_formatter.format(self, record) 

152 

153 

154class ShellColorFormatter(CustomColorFormatter): 

155 """Shell Color formatter.""" 

156 

157 def format(self, record: LogRecord) -> str: 

158 """Format the log. 

159 

160 Parameters 

161 ---------- 

162 record: LogRecord 

163 the log record 

164 

165 Returns 

166 ------- 

167 str 

168 the formatted log record 

169 """ 

170 record.msg = "{}{}{}".format( 

171 CustomColorFormatter.log_colors[logging.INFO], 

172 record.msg, 

173 CustomColorFormatter.color_Off, 

174 ) 

175 return record.msg