[Python-checkins] cpython (2.7): Issue #18541: simplified LoggerAdapter example.

vinay.sajip python-checkins at python.org
Wed Jul 24 18:53:17 CEST 2013


http://hg.python.org/cpython/rev/16c15d7d4480
changeset:   84806:16c15d7d4480
branch:      2.7
parent:      84779:e8b8279ca118
user:        Vinay Sajip <vinay_sajip at yahoo.co.uk>
date:        Wed Jul 24 17:47:52 2013 +0100
summary:
  Issue #18541: simplified LoggerAdapter example.

files:
  Doc/howto/logging-cookbook.rst |  76 +++++----------------
  1 files changed, 19 insertions(+), 57 deletions(-)


diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst
--- a/Doc/howto/logging-cookbook.rst
+++ b/Doc/howto/logging-cookbook.rst
@@ -460,69 +460,31 @@
 the keys of the dict-like object. If you need a different method, e.g. if you
 want to prepend or append the contextual information to the message string,
 you just need to subclass :class:`LoggerAdapter` and override :meth:`process`
-to do what you need. Here's an example script which uses this class, which
-also illustrates what dict-like behaviour is needed from an arbitrary
-'dict-like' object for use in the constructor::
+to do what you need. Here is a simple example::
 
-   import logging
+    class CustomAdapter(logging.LoggerAdapter):
+        """
+        This example adapter expects the passed in dict-like object to have a
+        'connid' key, whose value in brackets is prepended to the log message.
+        """
+        def process(self, msg, kwargs):
+            return '[%s] %s' % (self.extra['connid'], msg), kwargs
 
-   class ConnInfo:
-       """
-       An example class which shows how an arbitrary class can be used as
-       the 'extra' context information repository passed to a LoggerAdapter.
-       """
+which you can use like this::
 
-       def __getitem__(self, name):
-           """
-           To allow this instance to look like a dict.
-           """
-           from random import choice
-           if name == 'ip':
-               result = choice(['127.0.0.1', '192.168.0.1'])
-           elif name == 'user':
-               result = choice(['jim', 'fred', 'sheila'])
-           else:
-               result = self.__dict__.get(name, '?')
-           return result
+    logger = logging.getLogger(__name__)
+    adapter = CustomAdapter(logger, {'connid': some_conn_id})
 
-       def __iter__(self):
-           """
-           To allow iteration over keys, which will be merged into
-           the LogRecord dict before formatting and output.
-           """
-           keys = ['ip', 'user']
-           keys.extend(self.__dict__.keys())
-           return keys.__iter__()
+Then any events that you log to the adapter will have the value of
+``some_conn_id`` prepended to the log messages.
 
-   if __name__ == '__main__':
-       from random import choice
-       levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
-       a1 = logging.LoggerAdapter(logging.getLogger('a.b.c'),
-                                  { 'ip' : '123.231.231.123', 'user' : 'sheila' })
-       logging.basicConfig(level=logging.DEBUG,
-                           format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
-       a1.debug('A debug message')
-       a1.info('An info message with %s', 'some parameters')
-       a2 = logging.LoggerAdapter(logging.getLogger('d.e.f'), ConnInfo())
-       for x in range(10):
-           lvl = choice(levels)
-           lvlname = logging.getLevelName(lvl)
-           a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters')
+Using objects other than dicts to pass contextual information
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-When this script is run, the output should look something like this::
-
-   2008-01-18 14:49:54,023 a.b.c DEBUG    IP: 123.231.231.123 User: sheila   A debug message
-   2008-01-18 14:49:54,023 a.b.c INFO     IP: 123.231.231.123 User: sheila   An info message with some parameters
-   2008-01-18 14:49:54,023 d.e.f CRITICAL IP: 192.168.0.1     User: jim      A message at CRITICAL level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f INFO     IP: 192.168.0.1     User: jim      A message at INFO level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f WARNING  IP: 192.168.0.1     User: sheila   A message at WARNING level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f ERROR    IP: 127.0.0.1       User: fred     A message at ERROR level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f ERROR    IP: 127.0.0.1       User: sheila   A message at ERROR level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f WARNING  IP: 192.168.0.1     User: sheila   A message at WARNING level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f WARNING  IP: 192.168.0.1     User: jim      A message at WARNING level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f INFO     IP: 192.168.0.1     User: fred     A message at INFO level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f WARNING  IP: 192.168.0.1     User: sheila   A message at WARNING level with 2 parameters
-   2008-01-18 14:49:54,033 d.e.f WARNING  IP: 127.0.0.1       User: jim      A message at WARNING level with 2 parameters
+You don't need to pass an actual dict to a :class:`LoggerAdapter` - you could
+pass an instance of a class which implements ``__getitem__`` and ``__iter__`` so
+that it looks like a dict to logging. This would be useful if you want to
+generate values dynamically (whereas the values in a dict would be constant).
 
 
 .. _filters-contextual:

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list