Skip to content

Commit 7b3ce6e

Browse files
committed
Improved the log.assertion() and unreachable() functions to send a deeper traceback when reporting by email, rather than just the last stack frame.
- Legacy-Id: 12999
1 parent 0af1223 commit 7b3ce6e

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

ietf/utils/log.py

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,41 +53,64 @@ def log(msg):
5353

5454
logger = logging.getLogger('django')
5555

56+
def build_traceback(stack):
57+
"""
58+
Build something that looks sufficiently like a traceback to be passed to a
59+
logging.logger as the exc_info argument.
60+
"""
61+
class Traceback():
62+
pass
63+
next = None
64+
for frame_record in stack:
65+
fr_frame, fr_filename, fr_lineno, fr_funcname, fr_context, fr_context_this = frame_record
66+
tb = Traceback()
67+
tb.tb_frame = fr_frame
68+
tb.tb_lasti = fr_frame.f_lasti
69+
tb.tb_lineno = fr_lineno
70+
tb.tb_next = next
71+
next = tb
72+
# Stop traceback at _get_response() -- we don't want to see the
73+
# middleware, debug server, or wsgi internals when the exception
74+
# occurs in our app code, below _get_response():
75+
if fr_funcname == '_get_response' and fr_filename.endswith('django/core/handlers/base.py'):
76+
break
77+
return tb
78+
5679
def assertion(statement):
5780
"""
5881
This acts like an assertion. It uses the django logger in order to send
5982
the failed assertion and a backtrace as for an internal server error.
6083
6184
"""
62-
class Traceback():
63-
pass
64-
frame = inspect.stack()[1][0]
85+
stack = inspect.stack()[1:]
86+
frame = stack[0][0]
6587
value = eval(statement, frame.f_globals, frame.f_locals)
6688
if not value:
6789
if settings.DEBUG is True or settings.SERVER_MODE == 'test':
6890
raise AssertionError("Assertion '%s' failed." % (statement,))
6991
else:
7092
# build a simulated traceback object
71-
tb = Traceback()
72-
tb.tb_frame = frame
73-
tb.tb_lasti = None
74-
tb.tb_lineno = frame.f_lineno
75-
tb.tb_next = None
76-
logger.error("Assertion '%s' failed.", statement, exc_info=(AssertionError, statement, tb))
93+
tb = build_traceback(stack)
94+
# provide extra info if available
95+
extra = {}
96+
for key in [ 'request', 'status_code', ]:
97+
if key in frame.f_locals:
98+
extra[key] = frame.f_locals[key]
99+
logger.error("Assertion '%s' failed.", statement, exc_info=(AssertionError, statement, tb), extra=extra)
77100

78101
def unreachable():
79102
"Raises an assertion or sends traceback to admins if executed."
80-
class Traceback():
81-
pass
82-
frame = inspect.stack()[1][0]
103+
stack = inspect.stack()[1:]
104+
frame = stack[0][0]
83105
if settings.DEBUG is True or settings.SERVER_MODE == 'test':
84106
raise AssertionError("Arrived at code in %s() which was marked unreachable." % frame.f_code.co_name)
85107
else:
86108
# build a simulated traceback object
87-
tb = Traceback()
88-
tb.tb_frame = frame
89-
tb.tb_lasti = None
90-
tb.tb_lineno = frame.f_lineno
91-
tb.tb_next = None
92-
logger.error("Arrived at code in %s() which was marked unreachable.", frame.f_code.co_name, exc_info=(AssertionError, frame.f_code.co_name, tb))
109+
tb = build_traceback(stack)
110+
# provide extra info if available
111+
extra = {}
112+
for key in [ 'request', 'status_code', ]:
113+
if key in frame.f_locals:
114+
extra[key] = frame.f_locals[key]
115+
logger.error("Arrived at code in %s() which was marked unreachable.", frame.f_code.co_name, exc_info=(AssertionError, frame.f_code.co_name, tb), extra=extra)
93116

0 commit comments

Comments
 (0)