Coverage for src / prepare_times_nz / utilities / logger_setup.py: 53%

30 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-01 22:14 +0000

1""" 

2Logger Configuration and Utilities Module 

3 

4This module configures and defines logging behavior for the entire application. 

5It provides a custom logging formatter that adds colored output to console logs, 

6making different log levels visually distinct. 

7 

8Main Features: 

9- **CustomFormatter**: A logging formatter that applies ANSI color codes to log messages 

10 based on their severity (DEBUG, INFO, WARNING, ERROR, CRITICAL). 

11 This improves readability when scanning logs in the console. 

12- **HTML-like Color Markup**: Supports limited markup parsing for inline coloring 

13 within messages. For example, wrapping text in `<red>` or `<blue>` tags dynamically 

14 highlights parts of a log entry. 

15- **Convenience Functions**: 

16 - `h1(text)`: Emits a prominent heading in the logs to delineate sections. 

17 - `h2(text)`: Emits a secondary heading with less emphasis. 

18 - `red_text(text)`: Wraps a string with `<red>` tags for red highlighting. 

19 Good for drawing attention to key issues 

20 - `blue_text(text)`: Wraps a string with `<blue>` tags for blue highlighting. 

21 Good for highlighting field/address components of a message 

22 

23Usage: 

24- Call `setup_logging()` once at application startup to initialize the logger. 

25- Use the `h1()` and `h2()` functions to visually separate major log sections. 

26- Use `red_text()` and `blue_text()` to inject colored text inline within log messages. 

27 

28Color References: 

29- Debug: Blue 

30- Info: Green 

31- Warning: Yellow 

32- Error: Red 

33- Critical: Bright Red 

34 

35Example: 

36 logger.info("This is an info message.") 

37 logger.warning(red_text"This warning contains red_text(red text!)") 

38 h1("Major Section Start") 

39 h2("Secondary section start) 

40 

41Note: 

42The color codes rely on ANSI escape sequences and will work in most modern terminals. 

43Logs redirected to files will contain the raw escape codes unless handled separately. 

44 

45 

46""" 

47 

48import logging 

49 

50logger = logging.getLogger() 

51 

52 

53def setup_logging(): 

54 """ 

55 Runs all required commands to setup the logger handlers and set to 

56 required level (currently INFO) 

57 """ 

58 handler = logging.StreamHandler() 

59 handler.setFormatter(CustomFormatter()) 

60 logger.handlers = [handler] 

61 logger.setLevel(logging.INFO) 

62 

63 

64class CustomFormatter(logging.Formatter): 

65 """ 

66 A custom logging formatter that adds ANSI color codes to log messages. 

67 

68 This formatter applies color highlighting to log output based on the 

69 log level (DEBUG, INFO, WARNING, ERROR, CRITICAL), making logs easier 

70 to read in the console. In addition to coloring the entire message, 

71 it supports limited inline markup for selectively highlighting text 

72 within messages. 

73 """ 

74 

75 # Define colors for each log level 

76 COLORS = { 

77 logging.DEBUG: "\033[94m", # Blue 

78 logging.INFO: "\033[92m", # Green 

79 logging.WARNING: "\033[93m", # Yellow 

80 logging.ERROR: "\033[91m", # Red 

81 logging.CRITICAL: "\033[1;91m", # Bright Red 

82 } 

83 

84 RESET = "\033[0m" 

85 

86 def format(self, record): 

87 """ 

88 Format the specified log record as a string with color highlighting. 

89 

90 This method applies ANSI color codes to the entire log message based 

91 on the record's log level (DEBUG, INFO, WARNING, ERROR, CRITICAL). 

92 It also parses and replaces custom HTML-like tags (`<red>...</red>`, 

93 `<blue>...</blue>`) within the log message to allow inline color highlighting. 

94 

95 Args: 

96 record (logging.LogRecord): The log record to be formatted. 

97 

98 Returns: 

99 str: The formatted log message string with ANSI color codes applied. 

100 

101 Notes: 

102 - If no matching color is found for a log level, the default terminal 

103 reset code is used. 

104 - Inline color tags are replaced only if they exactly match the predefined 

105 patterns (e.g., "<red>", "</red>"). 

106 - The reset code applied to closing tags ensures that the inline color 

107 correctly blends with the outer log level color. 

108 

109 Colour reference: 

110 

111 black \033[30m 

112 red \033[91m 

113 green \033[92m 

114 yellow \033[93m 

115 blue \033[94m 

116 magenta \033[95m 

117 cyan \033[96m 

118 white \033[97m 

119 reset \033[0m 

120 

121 

122 Extra Extra 

123 bold \033[1m 

124 dim \033[2m 

125 underline \033[4m 

126 blink \033[5m 

127 

128 """ 

129 

130 color = self.COLORS.get(record.levelno, self.RESET) 

131 msg = f"{color} {record.getMessage()}{self.RESET}" 

132 

133 # We add limited parsing support for html colour tags 

134 

135 # red 

136 msg = msg.replace("<red>", "\033[91m") 

137 msg = msg.replace("</red>", color) 

138 

139 # blue 

140 msg = msg.replace("<blue>", "\033[94m") 

141 msg = msg.replace("</blue>", color) 

142 

143 return msg 

144 

145 

146# Headers 

147def h1(text: str): 

148 """ 

149 takes the string input and returns a logging info formatted to make headings 

150 Allowing consistent log heading methods (h1) 

151 """ 

152 line = "-" * (len(text) + 12) 

153 # logger.info("") 

154 logger.info(line) 

155 logger.info("---- {%s} ----", text) 

156 logger.info(line) 

157 

158 

159def h2(text: str): 

160 """ 

161 takes the string input and returns a log info formatted to make headings 

162 Allowing consistent log heading methods (h2) 

163 Less grandiose than h1 

164 """ 

165 logger.info("---- {%s} ----", text) 

166 

167 

168# Specific colours 

169def red_text(text): 

170 """ 

171 Returns input text string with html tags for red 

172 """ 

173 return f"<red>{text}</red>" 

174 

175 

176def blue_text(text): 

177 """ 

178 Returns input text string with html tags for blue. 

179 """ 

180 return f"<blue>{text}</blue>" 

181 

182 

183setup_logging()