Merge "Add a Python context that logs exceptions"
This commit is contained in:
commit
cd1aaad0eb
@ -98,14 +98,10 @@ class FlavorsGenerator(base.Context):
|
||||
"""Delete created flavors."""
|
||||
clients = osclients.Clients(self.context["admin"]["endpoint"])
|
||||
for flavor in self.context["flavors"].values():
|
||||
try:
|
||||
with logging.ExceptionLogger(
|
||||
LOG, _("Can't delete flavor %s") % flavor["id"]):
|
||||
rutils.retry(3, clients.nova().flavors.delete, flavor["id"])
|
||||
LOG.debug("Flavor is deleted %s" % flavor["id"])
|
||||
except Exception as e:
|
||||
LOG.error(
|
||||
"Can't delete flavor %s: %s" % (flavor["id"], e.message))
|
||||
if logging.is_debug():
|
||||
LOG.exception(e)
|
||||
|
||||
|
||||
class FlavorConfig(dict):
|
||||
|
@ -71,8 +71,8 @@ class Network(base.Context):
|
||||
def cleanup(self):
|
||||
for tenant_id, tenant_ctx in six.iteritems(self.context["tenants"]):
|
||||
for network in tenant_ctx.get("networks", []):
|
||||
try:
|
||||
with logging.ExceptionLogger(
|
||||
LOG,
|
||||
_("Failed to delete network for tenant %s")
|
||||
% tenant_id):
|
||||
self.net_wrapper.delete_network(network)
|
||||
except Exception as e:
|
||||
LOG.error("Failed to delete network for tenant %s\n"
|
||||
" reason: %s" % (tenant_id, e))
|
||||
|
@ -74,13 +74,10 @@ class RoleGenerator(base.Context):
|
||||
client = osclients.Clients(admin_endpoint).keystone()
|
||||
|
||||
for user in self.context["users"]:
|
||||
try:
|
||||
with logging.ExceptionLogger(
|
||||
LOG, _("Failed to remove role: %s") % role["id"]):
|
||||
client.roles.remove_user_role(
|
||||
user["id"], role["id"], tenant=user["tenant_id"])
|
||||
except Exception as ex:
|
||||
LOG.warning("Failed to remove role: %(role_id)s. "
|
||||
"Exception: %(ex)s" %
|
||||
{"role_id": role["id"], "ex": ex})
|
||||
|
||||
@rutils.log_task_wrapper(LOG.info, _("Enter context: `roles`"))
|
||||
def setup(self):
|
||||
|
@ -108,9 +108,6 @@ class AllowSSH(base.Context):
|
||||
@utils.log_task_wrapper(LOG.info, _("Exit context: `allow_ssh`"))
|
||||
def cleanup(self):
|
||||
for secgroup in self.secgroup:
|
||||
try:
|
||||
with logging.ExceptionLogger(
|
||||
LOG, _("Unable to delete secgroup: %s.") % secgroup.id):
|
||||
secgroup.delete()
|
||||
except Exception as ex:
|
||||
LOG.warning("Unable to delete secgroup: %(group_id)s. "
|
||||
"Exception: %(ex)s" %
|
||||
{"group_id": secgroup.id, "ex": ex})
|
||||
|
@ -67,5 +67,40 @@ class RallyContextAdapter(oslogging.ContextAdapter):
|
||||
self.log(logging.RDEBUG, msg, *args, **kwargs)
|
||||
|
||||
|
||||
class ExceptionLogger(object):
|
||||
"""Context that intercepts and logs exceptions.
|
||||
|
||||
Usage::
|
||||
LOG = logging.getLogger(__name__)
|
||||
...
|
||||
|
||||
def foobar():
|
||||
with ExceptionLogger(LOG, "foobar warning") as e:
|
||||
return house_of_raising_exception()
|
||||
|
||||
if e.exception:
|
||||
raise e.exception # remove if not required
|
||||
"""
|
||||
|
||||
def __init__(self, logger, warn=None):
|
||||
self.logger = logger
|
||||
self.warn = warn
|
||||
self.exception = None
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, type_, value, traceback):
|
||||
if value:
|
||||
self.exception = value
|
||||
|
||||
if self.warn:
|
||||
self.logger.warning(self.warn)
|
||||
self.logger.debug(value)
|
||||
if is_debug():
|
||||
self.logger.exception(value)
|
||||
return True
|
||||
|
||||
|
||||
def is_debug():
|
||||
return CONF.debug or CONF.rally_debug
|
||||
|
@ -76,3 +76,27 @@ class LogRallyContaxtAdapter(test.TestCase):
|
||||
|
||||
radapter.log.assert_called_once_with(mock_logging.RDEBUG,
|
||||
fake_msg)
|
||||
|
||||
|
||||
class ExceptionLoggerTestCase(test.TestCase):
|
||||
|
||||
@mock.patch("rally.common.log.is_debug")
|
||||
def test_context(self, mock_is_debug):
|
||||
# Prepare
|
||||
mock_is_debug.return_value = True
|
||||
|
||||
logger = mock.MagicMock()
|
||||
exception = Exception()
|
||||
|
||||
# Run
|
||||
with log.ExceptionLogger(logger, "foo") as e:
|
||||
raise exception
|
||||
|
||||
# Assertions
|
||||
logger.warning.assert_called_once_with("foo")
|
||||
|
||||
logger.exception.assert_called_once_with(exception)
|
||||
|
||||
logger.debug.assert_called_once_with(exception)
|
||||
|
||||
self.assertEqual(e.exception, exception)
|
||||
|
Loading…
Reference in New Issue
Block a user