#!/usr/bin/python3 import logging import logging.handlers import os import stackprinter # type: ignore 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) stderr_fmt = logging.Formatter('[%(asctime)s] %(leveltag)s: %(message)s', datefmt='%H:%M:%S') syslog_fmt = logging.Formatter( '[%(name)s] %(module)s.%(funcName)s - %(leveltag)s: %(message)s' ) stderr.setFormatter(stderr_fmt) syslog.setFormatter(syslog_fmt) 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") print(stackprinter.format(ex, style="darkbg2", add_summary=True)) if os.environ["MM_ENV"] != "DEVELOPMENT": msg = stackprinter.format(ex) send_mail(Config.ERRORS_TO, Config.ERRORS_FROM, "Exception from musicmuster", msg) sys.excepthook = log_uncaught_exceptions