79532485

Date: 2025-03-25 01:16:39
Score: 0.5
Natty:
Report link

One update to the accepted answer from @vvvvv - the Python formatter caches the record object, so if one handler modifies it, the next handler will process the modified record rather than the original one. That caused some side effects depending on the order of the handlers. So, I passed in copies of the record object rather than the actual record to the formatter and that fixed the issue.

Here is what I've implemented. I also added a custom formatter that removed the stack trace messages but left one line showing any exception types that were raised.

class NoStackTraceFormatter(logging.Formatter):
    """Custom formatter to remove stack trace from log messages."""
    def format(self, record):
        """Removes all exception stack trace information from log messages."""
        temp_record = logging.LogRecord(record.name,
                                        record.levelno,
                                        record.pathname,
                                        record.lineno,
                                        record.msg,
                                        record.args,
                                        record.exc_info,
                                        record.funcName)
        temp_record.exc_info = None
        temp_record.exc_text = None
        temp_record.stack_info = None
        return logging.Formatter.format(self, temp_record)


class SimpleStackTraceFormatter(logging.Formatter):
    def format(self, record):
        """Remove the full stack trace from log messages but leave the lines
           in the stack trace that explicitly list the exception type raised.
        """
        temp_record = logging.LogRecord(record.name,
                                        record.levelno,
                                        record.pathname,
                                        record.lineno,
                                        record.msg,
                                        record.args,
                                        record.exc_info,
                                        record.funcName)
        if record.exc_info:
            # get rid of the stack trace except for lines that explicitly list the exception type raised
            if not record.exc_text:
                temp_record.exc_text = self.formatException(record.exc_info)
            if temp_record.exc_text:
                temp_record.exc_text = '\n'.join(
                    [f"    {line}" for line in temp_record.exc_text.splitlines()
                    if '.exceptions.' in line])
            temp_record.stack_info = None
        return logging.Formatter.format(self, temp_record)

An example of the output from the SimpleStackTraceFormatter is as follows:

2025-03-24 20:07:31,477 INFO    driver.py:439   Attempting to connect to the server
2025-03-24 20:07:34,513 ERROR   rest.py:921 Request timed out, will retry
    urllib3.exceptions.ConnectTimeoutError: (<urllib3.connection.HTTPSConnection object at 0x000002989D18DC90>, 'Connection to x.x.x.x timed out. (connect timeout=3)')
    urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='x.x.x.x', port=xxxx): Max retries exceeded with url: /path/ (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x000002989D18DC90>, 'Connection to x.x.x.x timed out. (connect timeout=3)'))
    requests.exceptions.ConnectTimeout: HTTPSConnectionPool(host='x.x.x.x', port=xxxx): Max retries exceeded with url: /path/ (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x000002989D18DC90>, 'Connection to x.x.x.x timed out. (connect timeout=3)'))
Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @vvvvv
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: DaveB