summaryrefslogtreecommitdiffstats
path: root/Doc/howto
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/howto')
-rw-r--r--Doc/howto/logging-cookbook.rst87
1 files changed, 87 insertions, 0 deletions
diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst
index 674695b..563da9d 100644
--- a/Doc/howto/logging-cookbook.rst
+++ b/Doc/howto/logging-cookbook.rst
@@ -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
Python used.
+
+.. _custom-handlers:
+
.. currentmodule:: logging.config
Customizing handlers with :func:`dictConfig`
@@ -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
string. That’s because the __ notation is just syntax sugar for a constructor
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.
+