#!/usr/bin/python3 import logging import logging.handlers import stackprinter import sys import traceback from config import Config class LevelTagFilter(logging.Filter): """Add leveltag""" def filter(self, record: logging.LogRecord): # Extract the first character of the level name record.leveltag = record.levelname[0] # We never actually filter messages out, just abuse filtering to add an # extra field to the LogRecord return True class DebugStdoutFilter(logging.Filter): """Filter debug messages sent to stdout""" def filter(self, record: logging.LogRecord): # Exceptions are logged at ERROR level if record.levelno in [logging.DEBUG, logging.ERROR]: return True if record.module in Config.DEBUG_MODULES: return True if record.funcName in Config.DEBUG_FUNCTIONS: return True return False log = logging.getLogger(Config.LOG_NAME) log.setLevel(logging.DEBUG) # stderr stderr = logging.StreamHandler() stderr.setLevel(Config.LOG_LEVEL_STDERR) # syslog syslog = logging.handlers.SysLogHandler(address='/dev/log') syslog.setLevel(Config.LOG_LEVEL_SYSLOG) # Filter local_filter = LevelTagFilter() debug_filter = DebugStdoutFilter() syslog.addFilter(local_filter) stderr.addFilter(local_filter) stderr.addFilter(debug_filter) class VerboseExceptionFormatter(logging.Formatter): def formatException(self, exc_info): msg = stackprinter.format(exc_info) lines = msg.split('\n') lines_indented = [" ┆ " + line + "\n" for line in lines] msg_indented = "".join(lines_indented) return msg_indented stderr_fmt = '[%(asctime)s] %(leveltag)s: %(message)s' stderr_formatter = VerboseExceptionFormatter(stderr_fmt, datefmt='%H:%M:%S') stderr.setFormatter(stderr_formatter) syslog_fmt = '[%(name)s] %(module)s.%(funcName)s - %(leveltag)s: %(message)s' syslog_formatter = VerboseExceptionFormatter(syslog_fmt) syslog.setFormatter(syslog_formatter) # add the handlers to the log log.addHandler(stderr) log.addHandler(syslog) def log_uncaught_exceptions(ex_cls, ex, tb): from helpers import send_mail print("\033[1;31;47m") logging.critical(''.join(traceback.format_tb(tb))) print("\033[1;37;40m") stackprinter.show(style="darkbg2") msg = stackprinter.format(ex) send_mail(Config.ERRORS_TO, Config.ERRORS_FROM, "Exception from musicmuster", msg) sys.excepthook = log_uncaught_exceptions