diff --git a/src/boot_utils.py b/src/boot_utils.py index 2e89d66..6e11d09 100644 --- a/src/boot_utils.py +++ b/src/boot_utils.py @@ -7,6 +7,8 @@ import discord from LRFutils import progress +from src.utils.logging_formats import get_logging_formatter + if TYPE_CHECKING: from .cobot import CObot @@ -25,13 +27,11 @@ def setup_logger(): # file logging file_handler = RotatingFileHandler("logs/debug.log", maxBytes=int(1e6), backupCount=2, delay=True) - log_format = logging.Formatter( - "[{asctime}] {levelname:<7}: [{name}] {message}", - datefmt="%Y-%m-%d %H:%M:%S", style='{' - ) - - file_handler.setFormatter(log_format) - stream_handler.setFormatter(log_format) + # add formatters to handlers + stream_supports_colors = discord.utils.stream_supports_colour(stream_handler.stream) + stream_handler.setFormatter(get_logging_formatter(stream_supports_colors)) + file_supports_colors = discord.utils.stream_supports_colour(file_handler.stream) + file_handler.setFormatter(get_logging_formatter(file_supports_colors)) # add handlers to root logger root_logger = logging.getLogger() diff --git a/src/utils/logging_formats.py b/src/utils/logging_formats.py new file mode 100644 index 0000000..e5a4612 --- /dev/null +++ b/src/utils/logging_formats.py @@ -0,0 +1,45 @@ +import logging + +def get_logging_formatter(with_colors: bool): + "Return a logging formatter with or without colors" + if not with_colors: + return logging.Formatter( + fmt="[{asctime}] {levelname:<7} [{name}] {message}", + datefmt="%Y-%m-%d %H:%M:%S", style='{' + ) + + return _ColourFormatter() + +class _ColourFormatter(logging.Formatter): + "A formatter that adds colors to the log messages" + LEVEL_COLOURS = [ + (logging.DEBUG, '\x1b[40;1m'), + (logging.INFO, '\x1b[34;1m'), + (logging.WARNING, '\x1b[33;1m'), + (logging.ERROR, '\x1b[31m'), + (logging.CRITICAL, '\x1b[41m'), + ] + + FORMATS = { + level: logging.Formatter( + f'\x1b[30;1m%(asctime)s\x1b[0m {colour}%(levelname)-7s\x1b[0m \x1b[35m[%(name)s]\x1b[0m %(message)s', + '%Y-%m-%d %H:%M:%S', + ) + for level, colour in LEVEL_COLOURS + } + + def format(self, record): + formatter = self.FORMATS.get(record.levelno) + if formatter is None: + formatter = self.FORMATS[logging.DEBUG] + + # Override the traceback to always print in red + if record.exc_info: + text = formatter.formatException(record.exc_info) + record.exc_text = f'\x1b[31m{text}\x1b[0m' + + output = formatter.format(record) + + # Remove the cache layer + record.exc_text = None + return output