19

I am using AWS and use AWS cloudwatch to view logs. While things should not break on AWS, they could. I just had such a case. Then I searched for Traceback and just got the lines

Traceback (most recent call last):

without the actual traceback. I have a working structured logging setup (see other question) and I would like to get tracebacks in a similar way.

So instead of:

Traceback (most recent call last):
  File "/home/math/Desktop/test.py", line 32, in <module>
    adf
NameError: name 'adf' is not defined

something like

{"message": "Traceback (most recent call last):\n      File \"/home/math/Desktop/test.py\", line 32, in <module>\n        adf\n    NameError: name 'adf' is not defined", "lineno": 35, "pathname": "/home/math/Desktop/test.py"}

or even better also with the string in a JSON format.

The only way to achieve this I can think of is a giant try-except block. Pokemon-style. Is there a better solution?

3
  • So you don't want a try except block and also want to log errors with formatted way? Commented Feb 6, 2018 at 11:40
  • 1
    You should use a custom logging.Formatter and implement formatException. Commented Feb 6, 2018 at 11:42
  • @ArpitSolanki Yes Commented Feb 6, 2018 at 12:45

3 Answers 3

21

You can use sys.excepthook. It is invoked whenever an exception occurs in your script.

import logging
import sys
import traceback

def exception_logging(exctype, value, tb):
    """
    Log exception by using the root logger.

    Parameters
    ----------
    exctype : type
    value : NameError
    tb : traceback
    """
    write_val = {'exception_type': str(exctype),
                 'message': str(traceback.format_tb(tb, 10))}
    logging.exception(str(write_val))

Then in your script you have to override the value of sys.excepthook.

sys.excepthook = exception_logging

Now whenever an exception occurs it will be logged with your logger handler.

Note: Don't forget to setup logger before running this

Sign up to request clarification or add additional context in comments.

1 Comment

I'm trying this with my django application...any idea where to place it, codewise? I'm trying a apps.py and AppConfig, using ready() to override the sys.excepthook. As seen in the following link, logging is setup quite early, so, before ready....but no look, still many lines...docs.djangoproject.com/en/3.0/ref/applications/…
4

In case somebody wants the exception logged in its default format, but in one line (for any reason), based on the accepted answer:

def exception_logging(exctype, value, tb):
    """
    Log exception in one line by using the root logger.

    Parameters
    ----------
    exctype : exception type
    value : seems to be the Exception object (with its message)
    tb : traceback
    """
    logging.error(''.join(traceback.format_exception(exctype, value, tb)))

Please also note, that it uses logging.error() instead of logging.exception() which also printed some extra "NoneType: None" line.
Also note that it only seems to work with uncaught exceptions.
For logging caught exceptions, visit How do I can format exception stacktraces in Python logging? and see also my answer.

Comments

0

A slight variation: If you run a Flask application, you can do this:

@app.errorhandler(Exception)
def exception_logger(error):
    """Log the exception."""
    logger.exception(str(error))
    return str(error)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.