From a58af46f1504d16f8ef3b92541896e5f9ebbfeaa Mon Sep 17 00:00:00 2001 From: Terry Geng Date: Sat, 9 May 2020 10:44:01 +0800 Subject: [PATCH] feat: enhanced logging to file support, redirecting all stdout and stderr to log file. This feature woulb be useful for troubleshooting daemonized bots since now all exceptions are also wrote to log file. --- mumbleBot.py | 5 +++++ util.py | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/mumbleBot.py b/mumbleBot.py index cab12a3..033c074 100644 --- a/mumbleBot.py +++ b/mumbleBot.py @@ -700,6 +700,7 @@ if __name__ == '__main__': var.db = SettingsDatabase(var.dbfile) # Setup logger + bot_logger = logging.getLogger("bot") formatter = logging.Formatter('[%(asctime)s %(levelname)s %(threadName)s] %(message)s', "%b %d %H:%M:%S") bot_logger.setLevel(logging.INFO) @@ -714,7 +715,10 @@ if __name__ == '__main__': logfile = util.solve_filepath(var.config.get('bot', 'logfile')) handler = None if logfile: + print(f"Redirecting stdout and stderr to log file: {logfile}") handler = logging.handlers.RotatingFileHandler(logfile, mode='a', maxBytes=10240) # Rotate after 10KB + sys.stdout = util.LoggerIOWrapper(bot_logger, logging.INFO, fallback_io_buffer=sys.stdout.buffer) + sys.stderr = util.LoggerIOWrapper(bot_logger, logging.ERROR, fallback_io_buffer=sys.stderr.buffer) else: handler = logging.StreamHandler() @@ -755,3 +759,4 @@ if __name__ == '__main__': # Start the main loop. var.bot.loop() + diff --git a/util.py b/util.py index 184ea12..7da3886 100644 --- a/util.py +++ b/util.py @@ -4,6 +4,7 @@ import hashlib import magic import os +import io import sys import variables as var import zipfile @@ -335,3 +336,16 @@ def youtube_search(query): error_traceback = traceback.format_exc().split("During")[0] log.error("util: youtube query failed with error:\n %s" % error_traceback) return False + +class LoggerIOWrapper(io.TextIOWrapper): + def __init__(self, logger: logging.Logger, logging_level, fallback_io_buffer): + super().__init__(fallback_io_buffer, write_through=True) + self.logger = logger + self.logging_level = logging_level + + def write(self, text): + if isinstance(text, bytes): + self.logger.log(self.logging_level, text.decode('utf-8').rstrip()) + else: + self.logger.log(self.logging_level, text.rstrip()) +