[Zconfig] SVN: ZConfig/trunk/ZConfig/components/logger/ Added a configuration option for specifying a subclass of

Shane Hathaway shane at zope.com
Wed Jan 18 20:43:25 EST 2006


Log message for revision 41358:
  Added a configuration option for specifying a subclass of
  logging.Formatter.  This is in support of the following proposal:
  http://www.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/EnhanceTracebacksInPersistentLogs
  
  

Changed:
  U   ZConfig/trunk/ZConfig/components/logger/handlers.py
  U   ZConfig/trunk/ZConfig/components/logger/handlers.xml
  U   ZConfig/trunk/ZConfig/components/logger/tests/test_logger.py

-=-
Modified: ZConfig/trunk/ZConfig/components/logger/handlers.py
===================================================================
--- ZConfig/trunk/ZConfig/components/logger/handlers.py	2006-01-18 21:08:52 UTC (rev 41357)
+++ ZConfig/trunk/ZConfig/components/logger/handlers.py	2006-01-19 01:43:24 UTC (rev 41358)
@@ -54,6 +54,19 @@
         value = value.replace(pattern, replacement)
     return value
 
+def resolve(name):
+    """Given a dotted name, returns an object imported from a Python module."""
+    name = name.split('.')
+    used = name.pop(0)
+    found = __import__(used)
+    for n in name:
+        used += '.' + n
+        try:
+            found = getattr(found, n)
+        except AttributeError:
+            __import__(used)
+            found = getattr(found, n)
+    return found
 
 class HandlerFactory(Factory):
     def __init__(self, section):
@@ -67,8 +80,11 @@
     def create(self):
         import logging
         logger = self.create_loghandler()
-        logger.setFormatter(logging.Formatter(self.section.format,
-                                              self.section.dateformat))
+        if self.section.formatter:
+            f = resolve(self.section.formatter)
+        else:
+            f = logging.Formatter
+        logger.setFormatter(f(self.section.format, self.section.dateformat))
         logger.setLevel(self.section.level)
         return logger
 

Modified: ZConfig/trunk/ZConfig/components/logger/handlers.xml
===================================================================
--- ZConfig/trunk/ZConfig/components/logger/handlers.xml	2006-01-18 21:08:52 UTC (rev 41357)
+++ ZConfig/trunk/ZConfig/components/logger/handlers.xml	2006-01-19 01:43:24 UTC (rev 41358)
@@ -10,6 +10,14 @@
       loghandler directly since it doesn't implement the loghandler
       abstract section type.
     </description>
+    <key name="formatter" datatype="dotted-name" required="no">
+      <description>
+        Logging formatter class.  The default is 'logging.Formatter'.
+        An alternative is 'zope.exceptions.log.Formatter',
+        which enhances exception tracebacks with information from
+        __traceback_info__ and __traceback_supplement__ variables.
+      </description>
+    </key>
     <key name="dateformat"
          default="%Y-%m-%dT%H:%M:%S"/>
     <key name="level"

Modified: ZConfig/trunk/ZConfig/components/logger/tests/test_logger.py
===================================================================
--- ZConfig/trunk/ZConfig/components/logger/tests/test_logger.py	2006-01-18 21:08:52 UTC (rev 41357)
+++ ZConfig/trunk/ZConfig/components/logger/tests/test_logger.py	2006-01-19 01:43:24 UTC (rev 41358)
@@ -27,6 +27,18 @@
 from ZConfig.components.logger import loghandler
 
 
+class CustomFormatter(logging.Formatter):
+    def formatException(self, ei):
+        """Format and return the exception information as a string.
+
+        This adds helpful advice to the end of the traceback.
+        """
+        import traceback
+        sio = StringIO.StringIO()
+        traceback.print_exception(ei[0], ei[1], ei[2], file=sio)
+        return sio.getvalue() + "... Don't panic!"
+
+
 class LoggingTestBase(unittest.TestCase):
 
     # XXX This tries to save and restore the state of logging around
@@ -158,6 +170,30 @@
         logger.warn("woohoo!")
         self.assert_(sio.getvalue().find("woohoo!") >= 0)
 
+    def test_custom_formatter(self):
+        old_stream = sys.stdout
+        conf = self.get_config("""
+        <eventlog>
+        <logfile>
+        formatter ZConfig.components.logger.tests.test_logger.CustomFormatter
+        level info
+        path STDOUT
+        </logfile>
+        </eventlog>
+        """)
+        sio = StringIO.StringIO()
+        sys.stdout = sio
+        try:
+            logger = conf.eventlog()
+        finally:
+            sys.stdout = old_stream
+        try:
+            raise KeyError
+        except KeyError:
+            logger.exception("testing a KeyError")
+        self.assert_(sio.getvalue().find("KeyError") >= 0)
+        self.assert_(sio.getvalue().find("Don't panic") >= 0)
+
     def test_with_syslog(self):
         logger = self.check_simple_logger("<eventlog>\n"
                                           "  <syslog>\n"



More information about the ZConfig mailing list