diff options
| author | 2021-12-30 23:41:58 +0000 | |
|---|---|---|
| committer | 2021-12-30 23:41:58 +0000 | |
| commit | 17bcd45c68f144f3b88fdfdf05bd0db654c0322e (patch) | |
| tree | ad07a6a449a322165d7246699908256c2df7a047 /bot/log.py | |
| parent | Migrate to `og_blurple` (diff) | |
| parent | Merge pull request #994 from python-discord/logging-in-AoC-completer-task (diff) | |
Merge remote-tracking branch 'origin/main' into main
# Conflicts:
#	bot/exts/holidays/halloween/candy_collection.py
Diffstat (limited to '')
| -rw-r--r-- | bot/log.py | 96 | 
1 files changed, 96 insertions, 0 deletions
| diff --git a/bot/log.py b/bot/log.py new file mode 100644 index 00000000..29e696e0 --- /dev/null +++ b/bot/log.py @@ -0,0 +1,96 @@ +import logging +import logging.handlers +import os +import sys +from pathlib import Path + +import coloredlogs + +from bot.constants import Client + + +def setup() -> None: +    """Set up loggers.""" +    # Configure the "TRACE" logging level (e.g. "log.trace(message)") +    logging.TRACE = 5 +    logging.addLevelName(logging.TRACE, "TRACE") +    logging.Logger.trace = _monkeypatch_trace + +    format_string = "%(asctime)s | %(name)s | %(levelname)s | %(message)s" +    log_format = logging.Formatter(format_string) +    root_logger = logging.getLogger() + +    if Client.file_logs: +        # Set up file logging +        log_file = Path("logs/sir-lancebot.log") +        log_file.parent.mkdir(exist_ok=True) + +        # File handler rotates logs every 5 MB +        file_handler = logging.handlers.RotatingFileHandler( +            log_file, maxBytes=5 * (2 ** 20), backupCount=10, encoding="utf-8", +        ) +        file_handler.setFormatter(log_format) +        root_logger.addHandler(file_handler) + +    if "COLOREDLOGS_LEVEL_STYLES" not in os.environ: +        coloredlogs.DEFAULT_LEVEL_STYLES = { +            **coloredlogs.DEFAULT_LEVEL_STYLES, +            "trace": {"color": 246}, +            "critical": {"background": "red"}, +            "debug": coloredlogs.DEFAULT_LEVEL_STYLES["info"], +        } + +    if "COLOREDLOGS_LOG_FORMAT" not in os.environ: +        coloredlogs.DEFAULT_LOG_FORMAT = format_string + +    coloredlogs.install(level=logging.TRACE, stream=sys.stdout) + +    root_logger.setLevel(logging.DEBUG if Client.debug else logging.INFO) +    # Silence irrelevant loggers +    logging.getLogger("discord").setLevel(logging.ERROR) +    logging.getLogger("websockets").setLevel(logging.ERROR) +    logging.getLogger("PIL").setLevel(logging.ERROR) +    logging.getLogger("matplotlib").setLevel(logging.ERROR) +    logging.getLogger("async_rediscache").setLevel(logging.WARNING) + +    _set_trace_loggers() + +    root_logger.info("Logging initialization complete") + + +def _monkeypatch_trace(self: logging.Logger, msg: str, *args, **kwargs) -> None: +    """ +    Log 'msg % args' with severity 'TRACE'. + +    To pass exception information, use the keyword argument exc_info with a true value, e.g. +    logger.trace("Houston, we have an %s", "interesting problem", exc_info=1) +    """ +    if self.isEnabledFor(logging.TRACE): +        self._log(logging.TRACE, msg, args, **kwargs) + + +def _set_trace_loggers() -> None: +    """ +    Set loggers to the trace level according to the value from the BOT_TRACE_LOGGERS env var. + +    When the env var is a list of logger names delimited by a comma, +    each of the listed loggers will be set to the trace level. + +    If this list is prefixed with a "!", all of the loggers except the listed ones will be set to the trace level. + +    Otherwise if the env var begins with a "*", +    the root logger is set to the trace level and other contents are ignored. +    """ +    level_filter = Client.trace_loggers +    if level_filter: +        if level_filter.startswith("*"): +            logging.getLogger().setLevel(logging.TRACE) + +        elif level_filter.startswith("!"): +            logging.getLogger().setLevel(logging.TRACE) +            for logger_name in level_filter.strip("!,").split(","): +                logging.getLogger(logger_name).setLevel(logging.DEBUG) + +        else: +            for logger_name in level_filter.strip(",").split(","): +                logging.getLogger(logger_name).setLevel(logging.TRACE) | 
