Adds a new logging level to the `logging` module and the currently configured logging class. Uses the existing numeric level_num if already defined. Based on https://stackoverflow.com/questions/2183233
(level_name, level_num, method_name=None)
| 13 | |
| 14 | |
| 15 | def add_logging_level(level_name, level_num, method_name=None): |
| 16 | """ |
| 17 | Adds a new logging level to the `logging` module and the |
| 18 | currently configured logging class. |
| 19 | |
| 20 | Uses the existing numeric level_num if already defined. |
| 21 | |
| 22 | Based on https://stackoverflow.com/questions/2183233 |
| 23 | """ |
| 24 | if method_name is None: |
| 25 | method_name = level_name.lower() |
| 26 | |
| 27 | # If the level name is already defined as a top-level `logging` |
| 28 | # constant, then adopt the existing numeric level. |
| 29 | if hasattr(logging, level_name): |
| 30 | existing_level_num = getattr(logging, level_name) |
| 31 | assert isinstance(existing_level_num, int) |
| 32 | level_num = existing_level_num |
| 33 | |
| 34 | def log_for_level(self, message, *args, **kwargs): |
| 35 | if self.isEnabledFor(level_num): |
| 36 | self._log(level_num, message, args, **kwargs) |
| 37 | |
| 38 | def log_to_root(message, *args, **kwargs): |
| 39 | logging.log(level_num, message, *args, **kwargs) # noqa: LOG015 |
| 40 | |
| 41 | # getLevelName resolves the numeric log level if already defined, |
| 42 | # otherwise returns a string |
| 43 | if not isinstance(logging.getLevelName(level_name), int): |
| 44 | logging.addLevelName(level_num, level_name) |
| 45 | |
| 46 | if not hasattr(logging, level_name): |
| 47 | setattr(logging, level_name, level_num) |
| 48 | |
| 49 | if not hasattr(logging.getLoggerClass(), method_name): |
| 50 | setattr(logging.getLoggerClass(), method_name, log_for_level) |
| 51 | |
| 52 | if not hasattr(logging, method_name): |
| 53 | setattr(logging, method_name, log_to_root) |
| 54 | |
| 55 | |
| 56 | class LoggingException(Exception): # noqa: N818 |