diagnostic_utils.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. """
  2. Diagnostic utilities
  3. """
  4. import functools
  5. import sys
  6. import traceback
  7. def create_log_exception_decorator(logger):
  8. """Create a decorator that logs and reraises any exceptions that escape
  9. the decorated function
  10. :param logging.Logger logger:
  11. :returns: the decorator
  12. :rtype: callable
  13. Usage example
  14. import logging
  15. from pika.diagnostics_utils import create_log_exception_decorator
  16. _log_exception = create_log_exception_decorator(logging.getLogger(__name__))
  17. @_log_exception
  18. def my_func_or_method():
  19. raise Exception('Oops!')
  20. """
  21. def log_exception(func):
  22. """The decorator returned by the parent function
  23. :param func: function to be wrapped
  24. :returns: the function wrapper
  25. :rtype: callable
  26. """
  27. @functools.wraps(func)
  28. def log_exception_func_wrap(*args, **kwargs):
  29. """The wrapper function returned by the decorator. Invokes the
  30. function with the given args/kwargs and returns the function's
  31. return value. If the function exits with an exception, logs the
  32. exception traceback and re-raises the
  33. :param args: positional args passed to wrapped function
  34. :param kwargs: keyword args passed to wrapped function
  35. :returns: whatever the wrapped function returns
  36. :rtype: object
  37. """
  38. try:
  39. return func(*args, **kwargs)
  40. except:
  41. logger.exception(
  42. 'Wrapped func exited with exception. Caller\'s stack:\n%s',
  43. ''.join(traceback.format_exception(*sys.exc_info())))
  44. raise
  45. return log_exception_func_wrap
  46. return log_exception