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:
parent
17d5357003
commit
d3159f1d6b
|
@ -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={},
|
||||
|
|
|
@ -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):
|
||||
|
||||
|
|
Loading…
Reference in New Issue