r47357 - Merge stdlib-exception-logging-8316: Fix logging of exceptions to stdlib logging.

mithrandi-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Sat, 7 May 2016 01:02:00 -0600 (MDT)
Newsgroups gmane.comp.python.twisted.commits
Message-ID <[email protected]>
Author: mithrandi
Date: Sat May  7 01:01:46 2016
New Revision: 47357

Added:
   trunk/twisted/topfiles/8316.bugfix
Modified:
   trunk/twisted/logger/_stdlib.py
   trunk/twisted/logger/test/test_stdlib.py

Log:
Merge stdlib-exception-logging-8316: Fix logging of exceptions to stdlib logging.

Author: mithrandi
Reviewer: adiroiban
Fixes: #8316

Exceptions weren't logged at all; now they are.

Modified: trunk/twisted/logger/_stdlib.py
==============================================================================
--- trunk/twisted/logger/_stdlib.py	(original)
+++ trunk/twisted/logger/_stdlib.py	Sat May  7 01:01:46 2016
@@ -105,8 +105,15 @@
         Format an event and bridge it to Python logging.
         """
         level = event.get("log_level", LogLevel.info)
+        failure = event.get('log_failure')
+        if failure is None:
+            excInfo = None
+        else:
+            excInfo = (
+                failure.type, failure.value, failure.getTracebackObject())
         stdlibLevel = toStdlibLogLevelMapping.get(level, stdlibLogging.INFO)
-        self.logger.log(stdlibLevel, StringifiableFromEvent(event))
+        self.logger.log(
+            stdlibLevel, StringifiableFromEvent(event), exc_info=excInfo)
 
 
 

Modified: trunk/twisted/logger/test/test_stdlib.py
==============================================================================
--- trunk/twisted/logger/test/test_stdlib.py	(original)
+++ trunk/twisted/logger/test/test_stdlib.py	Sat May  7 01:01:46 2016
@@ -12,9 +12,10 @@
 
 from zope.interface.verify import verifyObject, BrokenMethodImplementation
 
+from twisted.python.compat import _PY3, currentframe
+from twisted.python.failure import Failure
 from twisted.trial import unittest
 
-from twisted.python.compat import _PY3, currentframe
 from .._levels import LogLevel
 from .._observer import ILogObserver
 from .._stdlib import STDLibLogObserver
@@ -183,6 +184,45 @@
         self.assertEqual(str(records[0].msg), "")
 
 
+    def test_failure(self):
+        """
+        An event with a failure logs the failure details as well.
+        """
+        def failing_func():
+            1 / 0
+        try:
+            failing_func()
+        except ZeroDivisionError:
+            failure = Failure()
+        event = dict(log_format='Hi mom', who='me', log_failure=failure)
+        records, output = self.logEvent(event)
+        self.assertEqual(len(records), 1)
+        self.assertIn(u'Hi mom', output)
+        self.assertIn(u'in failing_func', output)
+        self.assertIn(u'ZeroDivisionError', output)
+
+
+    def test_cleanedFailure(self):
+        """
+        A cleaned Failure object has a fake traceback object; make sure that
+        logging such a failure still results in the exception details being
+        logged.
+        """
+        def failing_func():
+            1 / 0
+        try:
+            failing_func()
+        except ZeroDivisionError:
+            failure = Failure()
+        failure.cleanFailure()
+        event = dict(log_format='Hi mom', who='me', log_failure=failure)
+        records, output = self.logEvent(event)
+        self.assertEqual(len(records), 1)
+        self.assertIn(u'Hi mom', output)
+        self.assertIn(u'in failing_func', output)
+        self.assertIn(u'ZeroDivisionError', output)
+
+
 
 class StdlibLoggingContainer(object):
     """