Last active
September 22, 2023 13:51
-
-
Save apua/31562caa6cb58a0143d617de0018ea6a to your computer and use it in GitHub Desktop.
Refer to Rust `env_logger`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import os | |
class ColoredFormatter(logging.Formatter): | |
def __init__(self, coloring=True, fmt='%(L)s{asctime} {levelname:<%(T)s} {name}%(R)s {message}', | |
datefmt = '%Y-%m-%dT%H:%M:%SZ', style = '{', *args, **kwargs): | |
if coloring: | |
L, R = map('\033[90m{}\033[m'.format, '[]') | |
T = 15 | |
else: | |
L, R = '[]' | |
T = 5 | |
super().__init__(fmt=fmt%locals(), datefmt=datefmt, style=style, *args, **kwargs) | |
self.coloring = coloring | |
def format(self, record): | |
if self.coloring: | |
# NOTE: Keep ASCII code be the same length (except CRITICAL) in order to format alignment. | |
if record.levelname == 'CRITICAL': | |
record.levelname = f'\033[1;4;5;7;35mCRITICAL\033[m' | |
elif record.levelname == 'ERROR': | |
record.levelname = f'\033[1;31mERROR\033[m' | |
elif record.levelname == 'WARNING': | |
record.levelname = f'\033[0;33mWARN\033[m' | |
elif record.levelname == 'INFO': | |
record.levelname = f'\033[0;32mINFO\033[m' | |
elif record.levelname == 'DEBUG': | |
record.levelname = f'\033[0;34mDEBUG\033[m' | |
elif record.levelname == 'TRACE': | |
record.levelname = f'\033[0;36mTRACE\033[m' | |
else: | |
pass | |
return super().format(record) | |
def register_trace(logging, trace_level=5): | |
""" | |
Register logging to support `TRACE` level. | |
""" | |
def trace(self, msg, *args, **kwargs): | |
if self.isEnabledFor(trace_level): | |
self._log(trace_level, msg, args, **kwargs) | |
logging.TRACE = trace_level | |
logging.addLevelName(trace_level, 'TRACE') | |
logging.Logger.trace = trace | |
def init(var_name='LOGGING'): | |
""" | |
Initialize `env_logger` including: | |
* registering trace level | |
* coloring if destination is a TTY | |
* reading environment variable for config | |
""" | |
register_trace(logging) | |
stream_handler = logging.StreamHandler() | |
stream_handler.setFormatter(ColoredFormatter( | |
coloring = 'TERM' in os.environ and stream_handler.stream.isatty() | |
)) | |
# NOTE: To keep it simple, now the config only support a level name for root logger. | |
logging_config = os.getenv(var_name, '').strip() | |
levelname = logging_config.upper() | |
if (level := getattr(logging, levelname, None)) is None: | |
logger = logging.getLogger() | |
logger.addHandler(stream_handler) | |
else: | |
logger = logging.getLogger() | |
logger.setLevel(level) | |
logger.addHandler(stream_handler) | |
if __name__ == '__main__': | |
init() | |
logger = logging.getLogger() | |
logger.critical('message') | |
logger.error('message') | |
logger.warning('message') | |
logger.info('message') | |
logger.debug('message') | |
logger.trace('message') |
Author
apua
commented
Sep 22, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment