save_and_reraise_exception: make logging respect the reraise parameter

Do not log original exception if reraise is set to False

Closes-Bug: #1291850
Related-Bug: #1288188

Change-Id: Icd5fcba25c2cd549cee70353a7a62d83bfe1255b
This commit is contained in:
Oleg Bondarev 2014-03-13 13:32:09 +04:00 committed by Ben Nemec
parent 0e98afda1b
commit 33a2cee6a6
2 changed files with 48 additions and 14 deletions

View File

@ -49,9 +49,22 @@ class save_and_reraise_exception(object):
decide_if_need_reraise() decide_if_need_reraise()
if not should_be_reraised: if not should_be_reraised:
ctxt.reraise = False ctxt.reraise = False
If another exception occurs and reraise flag is False,
the saved exception will not be logged.
If the caller wants to raise new exception during exception handling
he/she sets reraise to False initially with an ability to set it back to
True if needed::
except Exception:
with save_and_reraise_exception(reraise=False) as ctxt:
[if statements to determine whether to raise a new exception]
# Not raising a new exception, so reraise
ctxt.reraise = True
""" """
def __init__(self): def __init__(self, reraise=True):
self.reraise = True self.reraise = reraise
def __enter__(self): def __enter__(self):
self.type_, self.value, self.tb, = sys.exc_info() self.type_, self.value, self.tb, = sys.exc_info()
@ -59,10 +72,11 @@ class save_and_reraise_exception(object):
def __exit__(self, exc_type, exc_val, exc_tb): def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None: if exc_type is not None:
logging.error(_LE('Original exception being dropped: %s'), if self.reraise:
traceback.format_exception(self.type_, logging.error(_LE('Original exception being dropped: %s'),
self.value, traceback.format_exception(self.type_,
self.tb)) self.value,
self.tb))
return False return False
if self.reraise: if self.reraise:
six.reraise(self.type_, self.value, self.tb) six.reraise(self.type_, self.value, self.tb)

View File

@ -15,6 +15,8 @@
import logging import logging
import time import time
import mock
from openstack.common import excutils from openstack.common import excutils
from openstack.common.fixture import moxstubout from openstack.common.fixture import moxstubout
from openstack.common import test from openstack.common import test
@ -42,16 +44,18 @@ class SaveAndReraiseTest(test.BaseTestCase):
def test_save_and_reraise_exception_dropped(self): def test_save_and_reraise_exception_dropped(self):
e = None e = None
msg = 'second exception' msg = 'second exception'
try: with mock.patch('logging.error') as log:
try: try:
raise Exception('dropped') try:
except Exception: raise Exception('dropped')
with excutils.save_and_reraise_exception(): except Exception:
raise Exception(msg) with excutils.save_and_reraise_exception():
except Exception as _e: raise Exception(msg)
e = _e except Exception as _e:
e = _e
self.assertEqual(str(e), msg) self.assertEqual(str(e), msg)
self.assertTrue(log.called)
def test_save_and_reraise_exception_no_reraise(self): def test_save_and_reraise_exception_no_reraise(self):
"""Test that suppressing the reraise works.""" """Test that suppressing the reraise works."""
@ -61,6 +65,22 @@ class SaveAndReraiseTest(test.BaseTestCase):
with excutils.save_and_reraise_exception() as ctxt: with excutils.save_and_reraise_exception() as ctxt:
ctxt.reraise = False ctxt.reraise = False
def test_save_and_reraise_exception_dropped_no_reraise(self):
e = None
msg = 'second exception'
with mock.patch('logging.error') as log:
try:
try:
raise Exception('dropped')
except Exception:
with excutils.save_and_reraise_exception(reraise=False):
raise Exception(msg)
except Exception as _e:
e = _e
self.assertEqual(str(e), msg)
self.assertFalse(log.called)
class ForeverRetryUncaughtExceptionsTest(test.BaseTestCase): class ForeverRetryUncaughtExceptionsTest(test.BaseTestCase):