Allowing tracebacks to be surfaced through abort

Currently, anytime abort(...) is called, It raises a new
exception which then suppresses any existing tracebacks.
This causes error monitoring systems like NewRelic to
report back worthless surface-level tracebacks that have
nothing to do with the application.
This change allows for the exception type to change, but
keep the existing traceback (if one exists). This allows
for monitoring systems to see a real traceback that can
be correlated to logged information.

Change-Id: Ibe6eb37e25b74d1dcfca76dfc1f5bbce28d34e85
This commit is contained in:
John Vrbanac 2015-06-01 18:24:22 -05:00
parent 17d5357003
commit d3159f1d6b
2 changed files with 34 additions and 6 deletions

View File

@ -8,6 +8,7 @@ from mimetypes import guess_type, add_type
from os.path import splitext
import logging
import operator
import sys
import types
import six
@ -123,12 +124,24 @@ def abort(status_code=None, detail='', headers=None, comment=None, **kw):
:param comment: A comment to include in the response.
'''
raise exc.status_map[status_code](
detail=detail,
headers=headers,
comment=comment,
**kw
)
# If there is a traceback, we need to catch it for a re-raise
try:
_, _, traceback = sys.exc_info()
webob_exception = exc.status_map[status_code](
detail=detail,
headers=headers,
comment=comment,
**kw
)
if six.PY3:
raise webob_exception.with_traceback(traceback)
else:
# Using exec to avoid python 3 parsers from crashing
exec('raise webob_exception, None, traceback')
finally:
# Per the suggestion of the Python docs, delete the traceback object
del traceback
def redirect(location=None, internal=False, code=None, headers={},

View File

@ -3,6 +3,7 @@
import sys
import os
import json
import traceback
import warnings
import webob
@ -1121,6 +1122,20 @@ class TestAbort(PecanTestCase):
r = app.get('/', status=401)
assert r.status_int == 401
def test_abort_keeps_traceback(self):
last_exc, last_traceback = None, None
try:
try:
raise Exception('Bottom Exception')
except:
abort(404)
except Exception:
last_exc, _, last_traceback = sys.exc_info()
assert last_exc is HTTPNotFound
assert 'Bottom Exception' in traceback.format_tb(last_traceback)[-1]
class TestScriptName(PecanTestCase):