mirror of
https://github.com/python/cpython.git
synced 2025-09-28 19:25:27 +00:00
Updated information on logging contextual information.
This commit is contained in:
parent
9a0cb6a8d0
commit
957a47cd6f
1 changed files with 76 additions and 0 deletions
|
@ -1335,6 +1335,10 @@ level of granularity you want to use in logging an application, it could
|
||||||
be hard to manage if the number of :class:`Logger` instances becomes
|
be hard to manage if the number of :class:`Logger` instances becomes
|
||||||
effectively unbounded.
|
effectively unbounded.
|
||||||
|
|
||||||
|
|
||||||
|
Using LoggerAdapters to impart contextual information
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
An easy way in which you can pass contextual information to be output along
|
An easy way in which you can pass contextual information to be output along
|
||||||
with logging event information is to use the :class:`LoggerAdapter` class.
|
with logging event information is to use the :class:`LoggerAdapter` class.
|
||||||
This class is designed to look like a :class:`Logger`, so that you can call
|
This class is designed to look like a :class:`Logger`, so that you can call
|
||||||
|
@ -1442,6 +1446,78 @@ When this script is run, the output should look something like this::
|
||||||
|
|
||||||
The :class:`LoggerAdapter` class was not present in previous versions.
|
The :class:`LoggerAdapter` class was not present in previous versions.
|
||||||
|
|
||||||
|
Using Filters to impart contextual information
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
You can also add contextual information to log output using a user-defined
|
||||||
|
:class:`Filter`. ``Filter`` instances are allowed to modify the ``LogRecords``
|
||||||
|
passed to them, including adding additional attributes which can then be output
|
||||||
|
using a suitable format string, or if needed a custom :class:`Formatter`.
|
||||||
|
|
||||||
|
For example in a web application, the request being processed (or at least,
|
||||||
|
the interesting parts of it) can be stored in a threadlocal
|
||||||
|
(:class:`threading.local`) variable, and then accessed from a ``Filter`` to
|
||||||
|
add, say, information from the request - say, the remote IP address and remote
|
||||||
|
user's username - to the ``LogRecord``, using the attribute names 'ip' and
|
||||||
|
'user' as in the ``LoggerAdapter`` example above. In that case, the same format
|
||||||
|
string can be used to get similar output to that shown above. Here's an example
|
||||||
|
script::
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
class ContextFilter(logging.Filter):
|
||||||
|
"""
|
||||||
|
This is a filter which injects contextual information into the log.
|
||||||
|
|
||||||
|
Rather than use actual contextual information, we just use random
|
||||||
|
data in this demo.
|
||||||
|
"""
|
||||||
|
|
||||||
|
USERS = ['jim', 'fred', 'sheila']
|
||||||
|
IPS = ['123.231.231.123', '127.0.0.1', '192.168.0.1']
|
||||||
|
|
||||||
|
def filter(self, record):
|
||||||
|
|
||||||
|
record.ip = choice(ContextFilter.IPS)
|
||||||
|
record.user = choice(ContextFilter.USERS)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
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 = logging.getLogger("a.b.c")
|
||||||
|
a2 = logging.getLogger("d.e.f")
|
||||||
|
|
||||||
|
f = ContextFilter()
|
||||||
|
a1.addFilter(f)
|
||||||
|
a2.addFilter(f)
|
||||||
|
a1.debug("A debug message")
|
||||||
|
a1.info("An info message with %s", "some parameters")
|
||||||
|
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")
|
||||||
|
|
||||||
|
which, when run, produces something like::
|
||||||
|
|
||||||
|
2010-09-06 22:38:15,292 a.b.c DEBUG IP: 123.231.231.123 User: fred A debug message
|
||||||
|
2010-09-06 22:38:15,300 a.b.c INFO IP: 192.168.0.1 User: sheila An info message with some parameters
|
||||||
|
2010-09-06 22:38:15,300 d.e.f CRITICAL IP: 127.0.0.1 User: sheila A message at CRITICAL level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,300 d.e.f ERROR IP: 127.0.0.1 User: jim A message at ERROR level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,300 d.e.f DEBUG IP: 127.0.0.1 User: sheila A message at DEBUG level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,300 d.e.f ERROR IP: 123.231.231.123 User: fred A message at ERROR level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,300 d.e.f CRITICAL IP: 192.168.0.1 User: jim A message at CRITICAL level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,300 d.e.f CRITICAL IP: 127.0.0.1 User: sheila A message at CRITICAL level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,300 d.e.f DEBUG IP: 192.168.0.1 User: jim A message at DEBUG level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,301 d.e.f ERROR IP: 127.0.0.1 User: sheila A message at ERROR level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,301 d.e.f DEBUG IP: 123.231.231.123 User: fred A message at DEBUG level with 2 parameters
|
||||||
|
2010-09-06 22:38:15,301 d.e.f INFO IP: 123.231.231.123 User: fred A message at INFO level with 2 parameters
|
||||||
|
|
||||||
|
|
||||||
.. _multiple-processes:
|
.. _multiple-processes:
|
||||||
|
|
||||||
Logging to a single file from multiple processes
|
Logging to a single file from multiple processes
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue