Truncate error_summary if exc_info not explicitly passed
Currently, when logging at level >= WARNING, exception information is added to the log message as an "error summary" for operators. The error summary includes the exception type and the message. However, when the exception is a _Remote exception generated from oslo.messaging and sent over RPC, the full traceback from the exception is appended to the exception message [1] to preserve it. So, the error summary ends up outputting the full traceback, unintentionally. This truncates the error_summary to keep only the first line unless exc_info was explicitly passed, via LOG.exception(), for example. Closes-Bug: #1729475 [1] https://github.com/openstack/oslo.messaging/blob/8d42484/oslo_messaging/_drivers/common.py#L208 Change-Id: I2e4e356d23dff2e6ac1946fe9e994c4d962ab55a
This commit is contained in:
parent
97434d48b2
commit
a63438cb5b
@ -156,6 +156,13 @@ def _get_error_summary(record):
|
|||||||
exc_info[0],
|
exc_info[0],
|
||||||
exc_info[1],
|
exc_info[1],
|
||||||
)[0].rstrip()
|
)[0].rstrip()
|
||||||
|
# If the exc_info wasn't explicitly passed to us, take only the
|
||||||
|
# first line of it. _Remote exceptions from oslo.messaging append
|
||||||
|
# the full traceback to the exception message, so we want to avoid
|
||||||
|
# outputting the traceback unless we've been passed exc_info
|
||||||
|
# directly (via LOG.exception(), for example).
|
||||||
|
if not record.exc_info:
|
||||||
|
error_summary = error_summary.split('\n', 1)[0]
|
||||||
except TypeError as type_err:
|
except TypeError as type_err:
|
||||||
# Work around https://bugs.python.org/issue28603
|
# Work around https://bugs.python.org/issue28603
|
||||||
error_summary = "<exception with %s>" % six.text_type(type_err)
|
error_summary = "<exception with %s>" % six.text_type(type_err)
|
||||||
|
@ -541,6 +541,30 @@ class JSONFormatterTestCase(LogTestBase):
|
|||||||
self.assertIn('error_summary', data)
|
self.assertIn('error_summary', data)
|
||||||
self.assertEqual('', data['error_summary'])
|
self.assertEqual('', data['error_summary'])
|
||||||
|
|
||||||
|
def test_exception_without_exc_info_passed(self):
|
||||||
|
ctxt = _fake_context()
|
||||||
|
ctxt.request_id = six.text_type('99')
|
||||||
|
try:
|
||||||
|
raise RuntimeError('test_exception\ntraceback\nfrom\nremote error')
|
||||||
|
except RuntimeError:
|
||||||
|
self.log.warning('testing', context=ctxt)
|
||||||
|
data = jsonutils.loads(self.stream.getvalue())
|
||||||
|
self.assertIn('error_summary', data)
|
||||||
|
self.assertEqual('RuntimeError: test_exception', data['error_summary'])
|
||||||
|
|
||||||
|
def test_exception_with_exc_info_passed(self):
|
||||||
|
ctxt = _fake_context()
|
||||||
|
ctxt.request_id = six.text_type('99')
|
||||||
|
try:
|
||||||
|
raise RuntimeError('test_exception\ntraceback\nfrom\nremote error')
|
||||||
|
except RuntimeError:
|
||||||
|
self.log.exception('testing', context=ctxt)
|
||||||
|
data = jsonutils.loads(self.stream.getvalue())
|
||||||
|
self.assertIn('error_summary', data)
|
||||||
|
self.assertEqual('RuntimeError: test_exception'
|
||||||
|
'\ntraceback\nfrom\nremote error',
|
||||||
|
data['error_summary'])
|
||||||
|
|
||||||
def test_fallback(self):
|
def test_fallback(self):
|
||||||
if not formatters._HAVE_JSONUTILS_FALLBACK:
|
if not formatters._HAVE_JSONUTILS_FALLBACK:
|
||||||
self.skipTest("need the fallback parameter of "
|
self.skipTest("need the fallback parameter of "
|
||||||
|
Loading…
Reference in New Issue
Block a user