Commit 554f22ff authored by Vinay Sajip's avatar Vinay Sajip

Added cookbook entry on logging filter configuration using dictConfig().

parent 57839a63
...@@ -1694,6 +1694,9 @@ When the above script is run, it prints:: ...@@ -1694,6 +1694,9 @@ When the above script is run, it prints::
Note that the order of items might be different according to the version of Note that the order of items might be different according to the version of
Python used. Python used.
.. _custom-handlers:
.. currentmodule:: logging.config .. currentmodule:: logging.config
Customizing handlers with :func:`dictConfig` Customizing handlers with :func:`dictConfig`
...@@ -1948,3 +1951,87 @@ handler. So the only slightly unusual thing which might trip you up is that the ...@@ -1948,3 +1951,87 @@ handler. So the only slightly unusual thing which might trip you up is that the
parentheses go around the format string and the arguments, not just the format parentheses go around the format string and the arguments, not just the format
string. That’s because the __ notation is just syntax sugar for a constructor string. That’s because the __ notation is just syntax sugar for a constructor
call to one of the ``XXXMessage`` classes shown above. call to one of the ``XXXMessage`` classes shown above.
.. _filters-dictconfig:
.. currentmodule:: logging.config
Configuring filters with :func:`dictConfig`
-------------------------------------------
You *can* configure filters using :func:`~logging.config.dictConfig`, though it
might not be obvious at first glance how to do it (hence this recipe). Since
:class:`~logging.Filter` is the only filter class included in the standard
library, and it is unlikely to cater to many requirements (it's only there as a
base class), you will typically need to define your own :class:`~logging.Filter`
subclass with an overridden :meth:`~logging.Filter.filter` method. To do this,
specify the ``()`` key in the configuration dictionary for the filter,
specifying a callable which will be used to create the filter (a class is the
most obvious, but you can provide any callable which returns a
:class:`~logging.Filter` instance). Here is a complete example::
import logging
import logging.config
import sys
class MyFilter(logging.Filter):
def __init__(self, param=None):
self.param = param
def filter(self, record):
if self.param is None:
allow = True
else:
allow = self.param not in record.msg
if allow:
record.msg = 'changed: ' + record.msg
return allow
LOGGING = {
'version': 1,
'filters': {
'myfilter': {
'()': MyFilter,
'param': 'noshow',
}
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'filters': ['myfilter']
}
},
'root': {
'level': 'DEBUG',
'handlers': ['console']
},
}
if __name__ == '__main__':
logging.config.dictConfig(LOGGING)
logging.debug('hello')
logging.debug('hello - noshow')
This example shows how you can pass configuration data to the callable which
constructs the instance, in the form of keyword parameters. When run, the above
script will print::
changed: hello
which shows that the filter is working as configured.
A couple of extra points to note:
* If you can't refer to the callable directly in the configuration (e.g. if it
lives in a different module, and you can't import it directly where the
configuration dictionary is), you can use the form ``ext://...`` as described
in :ref:`logging-config-dict-externalobj`. For example, you could have used
the text ``'ext://__main__.MyFilter'`` instead of ``MyFilter`` in the above
example.
* As well as for filters, this technique can also be used to configure custom
handlers and formatters. See :ref:`logging-config-dict-userdef` for more
information on how logging supports using user-defined objects in its
configuration, and see the other cookbook recipe :ref:`custom-handlers` above.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment