The logs I am creating in Python are intended to be temporarily stored as files which will, in turn, be processed into a log database. They take a pipe-delineated format to dictate how the logs will be processed, but logging.exception() is breaking my standard by adding one too many fields and way too many newlines.
import logging
logging.basicConfig(filename='output.txt',
format='%(asctime)s|%(levelname)s|%(message)s|',
datefmt='%m/%d/%Y %I:%M:%S %p',
level=logging.DEBUG)
logging.info('Sample message')
try:
x = 1 / 0
except ZeroDivisionError as e:
logging.exception('ZeroDivisionError: {0}'.format(e))
# output.txt
01/27/2015 02:09:01 PM|INFO|Sample message|
01/27/2015 02:09:01 PM|ERROR|ZeroDivisionError: integer division or modulo by zero|
Traceback (most recent call last):
File "C:\Users\matr06586\Desktop\ETLstage\Python\blahblah.py", line 90, in <module>
x = 1 / 0
ZeroDivisionError: integer division or modulo by zero
How can I best handle or format tracebacks with the whitespace and newlines? These messages are part and parcel in logging.exception(), but it feels odd to circumvent the function when I am attempting to document instances of exceptions. How do I record my tracebacks and format them too? Should the tracebacks be ignored?
Thank you for your time!
You can define your own Formatter
whose methods you can override to format exception information exactly how you want it. Here is a simplistic (but working) example:
import logging
class OneLineExceptionFormatter(logging.Formatter):
def formatException(self, exc_info):
result = super(OneLineExceptionFormatter, self).formatException(exc_info)
return repr(result) # or format into one line however you want to
def format(self, record):
s = super(OneLineExceptionFormatter, self).format(record)
if record.exc_text:
s = s.replace('\n', '') + '|'
return s
fh = logging.FileHandler('output.txt', 'w')
f = OneLineExceptionFormatter('%(asctime)s|%(levelname)s|%(message)s|', '%m/%d/%Y %I:%M:%S %p')
fh.setFormatter(f)
root = logging.getLogger()
root.setLevel(logging.DEBUG)
root.addHandler(fh)
logging.info('Sample message')
try:
x = 1 / 0
except ZeroDivisionError as e:
logging.exception('ZeroDivisionError: {0}'.format(e))
This produces just two lines:
01/28/2015 07:28:27 AM|INFO|Sample message|
01/28/2015 07:28:27 AM|ERROR|ZeroDivisionError: integer division or modulo by zero|'Traceback (most recent call last):\n File "logtest2.py", line 23, in <module>\n x = 1 / 0\nZeroDivisionError: integer division or modulo by zero'|
Of course, you can build on this example to do precisely what you want, e.g. via the traceback
module.