Skip to content

Commit

Permalink
Allowing tracebacks to be surfaced through abort
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jmvrbanac committed Jun 4, 2015
1 parent 17d5357 commit d3159f1
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
25 changes: 19 additions & 6 deletions pecan/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from os.path import splitext
import logging
import operator
import sys
import types

import six
Expand Down Expand Up @@ -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={},
Expand Down
15 changes: 15 additions & 0 deletions pecan/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import sys
import os
import json
import traceback
import warnings

import webob
Expand Down Expand Up @@ -1121,6 +1122,20 @@ def index(self):
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):

Expand Down

0 comments on commit d3159f1

Please sign in to comment.