95 lines
2.5 KiB
Python
95 lines
2.5 KiB
Python
#!/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="lightbg")
|
|
msg = stackprinter.format(ex)
|
|
send_mail(Config.ERRORS_TO, Config.ERRORS_FROM,
|
|
"Exception from musicmuster", msg)
|
|
|
|
|
|
sys.excepthook = log_uncaught_exceptions
|