summaryrefslogtreecommitdiffstats
path: root/Doc/howto
diff options
context:
space:
mode:
authorVinay Sajip <vinay_sajip@yahoo.co.uk>2013-07-24 16:52:01 (GMT)
committerVinay Sajip <vinay_sajip@yahoo.co.uk>2013-07-24 16:52:01 (GMT)
commita92fbe6dce55468b2dbf25008dfda8868a7e0856 (patch)
tree27e3358139d430027645c3ae67eb46cc9e095002 /Doc/howto
parent7d28b6b379ec2e772cbaa55c7ed6705459c2d5b4 (diff)
downloadcpython-a92fbe6dce55468b2dbf25008dfda8868a7e0856.zip
cpython-a92fbe6dce55468b2dbf25008dfda8868a7e0856.tar.gz
cpython-a92fbe6dce55468b2dbf25008dfda8868a7e0856.tar.bz2
Issue #18541: simplified LoggerAdapter example.
Diffstat (limited to 'Doc/howto')
-rw-r--r--Doc/howto/logging-cookbook.rst76
1 files changed, 19 insertions, 57 deletions
diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst
index cdd4b66..acf80b9 100644
--- a/Doc/howto/logging-cookbook.rst
+++ b/Doc/howto/logging-cookbook.rst
@@ -524,69 +524,31 @@ customized strings with your :class:`Formatter` instances which know about
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: