From d031f481b8a7542aad5f9b933c44a13cef0f5129 Mon Sep 17 00:00:00 2001 From: "R. Richard" Date: Mon, 24 Jun 2019 14:21:30 +0200 Subject: [PATCH] Print exceptions with stack trace --- lib/tfw/config/log.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/tfw/config/log.py b/lib/tfw/config/log.py index 332fef0..827bff9 100644 --- a/lib/tfw/config/log.py +++ b/lib/tfw/config/log.py @@ -1,6 +1,8 @@ # pylint: disable=bad-whitespace from sys import stderr +from collections import deque from datetime import datetime +from traceback import format_exception, walk_tb from logging import DEBUG, getLogger, Handler, Formatter, Filter TFW_LOG_PATH = '/var/log/tfw.log' @@ -71,6 +73,10 @@ class TFWLogFormatter(Formatter): 'NOTSET' : COLOR.CYAN } + def __init__(self): + self.last_trace = None + super().__init__() + def format(self, record): date = datetime.utcfromtimestamp(record.created).strftime('%H:%M:%S') if record.args: @@ -82,10 +88,23 @@ class TFWLogFormatter(Formatter): short_message = record.msg long_message = record.msg + if record.exc_info: + current_trace = self.fetch_exception_origin(record.exc_info[2]) + if current_trace != self.last_trace: + self.last_trace = current_trace + trace = '\n'+''.join(format_exception(*record.exc_info)) + else: + trace = (f'\nSee previous traceback...\n' + f'{record.exc_info[0].__name__}: {record.exc_info[1]}') + else: + trace = '' + short_entry = (f'[{COLOR.GREY}{date}{COLOR.RESET}|>' f'{self.severity[record.levelname]}{record.module}:' - f'{record.levelname.lower()}{COLOR.RESET}] {short_message}') - long_entry = f'[{date}|>{record.module}:{record.levelname.lower()}] {long_message}' + f'{record.levelname.lower()}{COLOR.RESET}] {short_message}' + f'{trace}') + long_entry = (f'[{date}|>{record.module}:{record.levelname.lower()}] ' + f'{long_message}{trace}') return short_entry, long_entry def trim(self, value, in_dict=False): @@ -97,6 +116,10 @@ class TFWLogFormatter(Formatter): value_str = str(value) return value_str if len(value_str) <= 20 else f'{value_str[:20]}...' + @staticmethod + def fetch_exception_origin(trace): + return deque(walk_tb(trace), maxlen=1).pop() + class TFWLogWhitelistFilter(Filter): def __init__(self, names):