Guide to Examples¶
The prelogging distribution contains a number of examples, in the top-level
examples/
directory. You must download the repository in order to run them:
they are not installed.
Running the examples¶
Run the programs in the examples/
directory from that directory.
On *nix, all the top-level modules of the examples are marked executable
and contain shebangs, so, for example, the following works:
$ cd path/to/examples
$ ./mproc.py
Of course, python ./mproc.py
works too. On Windows, use:
$ cd path\to\examples
$ python ./mproc.py
Programs in the examples/
directory¶
This section catalogs the example programs by category and briefly describes each one, sometimes in the imperative a la docstrings.
Simple examples¶
root_logger.py
¶
Create a root logger with a stdout console handler at loglevel
INFO
, and a file handler at default loglevelNOTSET
. Root loglevel isINFO
.
Logfile: examples/_log/root_logger/logfile.log
child_logger_main.py
¶
Uses modules
child_logger_sub_prop.py
andchild_logger_sub_noprop.py
.Create a non-root logger with two child loggers, one propagating and one not. The parent logger has a stderr handler and a file handler, shared by the propagating logger. The non-propagating logger creates its own stderr handler by cloning its parent’s stderr handler; however, it uses the same file handler as its parent (and its sibling).
Observe how the loglevels of the handlers and loggers determine what gets written to the two destinations.
Logfile: examples/_log/child_loggers/child_loggers.log
child_logger2_main.py
¶
Uses
child_logger2_sub_prop.py
,child_logger2_sub_noprop.py
.Give the root logger a stderr handler and a file handler. Create two loggers, one propagating and the other not. The non-propagating logger creates its own stderr handler by cloning the root’s stderr handler; however, it uses the same file handler used by the root (and its sibling).
Observe how the loglevels of the handlers and loggers determine what gets written to the two destinations.
Logfile: examples/_log/child_loggers2/child_loggers2.log
dateformat.py
¶
A small example showing two uses of thedateformat
parameter ofadd_formatter
.
dictConfig-can-kill-existing-root-configuration.py¶
This example helps make the case for
LCDictBuilderABC
.A call to
logging.config.dictConfig(d)
kills existing handlers on any logger that’s configured ind
– even with'disable_existing_loggers': False
. The root logger always get configured ifd['root']
is nonempty. Thus, multiple calls tologging.config.dictConfig(d)
can leave the root with only the handlers specified for it in the last logging config dict passed, or with no handlers at all.The same is of course true of
LCDict.config()
.This program demonstrates the phenomenon, using either prelogging or pure logging APIs depending on the value of the constant
USE_PRELOGGING
. When thePRESERVE_ROOT
constant is True, the'root'
subdict is set to{}
, preserving the root’s configuration, including its handlers.Thus, it’s chancy to do “collaborative configuration” by having separate “areas” of a program build their own
LCDict
s and each callconfig()
on them. Not only does that approach sacrifice prelogging’s consistency checking, but it also opens the door to hard-to-diagnose logging bugs.
Handler examples¶
use_library.py
(use of a null handler)¶
A main program which configures logging, and uses a package (
library
) which also configures logging in its__init__
module. The package sets up logging with a non-root logger at loglevelINFO
which uses a null handler; package methods log messages with that logger. The program adds a stdout handler to the root, with loglevelDEBUG
; the root loglevel is the default,WARNING
.The package’s logger propagates, therefore messages logged by the package with loglevel at least
INFO
are written.
SMTP_handler_just_one.py
and SMTP_handler_two.py
¶
These programs use
add_email_handler
to add SMTP handlers.SMTP_handler_just_one.py
adds a single SMTP handler;SMTP_handler_two.py
adds two, one with a filter, in order to send different email messages for different loglevels.Attention
For these examples to work properly, you must edit
examples/_smtp_credentials.py
to contain a valid username, password and SMTP server.
syslog.py
¶
(OS X aka macOS only) Set the root logger level to
DEBUG
, and add handlers:
- add a stdout handler with loglevel
WARNING
, and- use
add_syslog_handler
to add a syslog handler with default loglevelNOTSET
.Also see the example
mproc_deco_syslog.py
, described below.
queue_handler_listener.py
¶
An example that illustrates how to use a QueueListener with prelogging so that messages can be logged on a separate thread. In this way, handlers that block and take long to complete (e.g. SMTP handlers, which send emails) won’t make other threads (e.g. the UI thread) stall and stutter.
For motivation, see Dealing with handlers that block in the logging Cookbook. We’ve adapted the code in that section to prelogging.
Another approach can be found in the example
mproc_approach__queue_handler_logging_thread.py
, described below.
Filter examples¶
filter-class-extra-static-data.py
¶
Passing extra static data to a class filter via keyword arguments to
add_class_filter
to specify how different instances will filter messages.Described and walked through in the section on providing extra, static data to a class filter of the “Further Topics and Recipes” chapter.
filter-callable-extra-static-data.py
¶
The analogous construction – passing extra static data to a callable filter via keyword arguments to
add_class_filter
to specify how it will filter messages.Namedropped but not described in the section on providing extra, static data to a callable filter of “Further Topics and Recipes”.
filter-adding-fields--custom-formatter-keywords-for-fields.py
¶
This example illustrates adding custom fields and data to logged messages. It uses a custom formatter with two new keywords,
user
andip
, and a class filter created with a callable data source – static initializing data for the filter, but a source of dynamic data. The filter’sfilter
method adds attributes of the same names as the keywords to eachLogRecord
passed to it, calling the data source to obtain current values for these attributes.Loosely adapts the section Using Filters to impart contextual information of The Logging Cookbook.
Custom formatter examples¶
custom_class_formatter.py¶
How to configure and use a subclass oflogging.Formatter
as a formatter.
custom_callable_formatter.py¶
How to configure and use a callable as a formatter.
Multiprocessing examples¶
Except for the
mproc_approach_*.py
examples, the programs described in this section all take command line arguments which tell them whether or not to use locking handlers.Usage for the programs that take command line parameters:
./program_name [--LOCKING | --NOLOCKING] ./program_name -h | --help Options (case-insensitive, initial letter suffices, e.g. "--L" or "--n" or even -L): -L, --LOCKING Use locking handlers [default: True] -N, --NOLOCKING Use non-locking handlers [default: False] -h, --help Write this help message and exit.When run without locking, the multiprocessing examples will eventually misbehave –
NUL
(0) bytes will appear in the logged output, and messages logged by different processes will barge in on each other. The directoryexamples/_log saved
contains subdirectories_log--2.7-runs
,_log--3.x-runs (I)
and_log--3.x-runs (II)
which capture several instances of this misbehavior. Though your mileage may vary, experience has shown that this expected misbehavior is more likely when these examples are run individually than when they’re run viarun_examples.py
orrun_all.py
.After running any of these examples, you can use
check_for_NUL.py
to check whether or not its logfile output is garbled:$ ./check_for_NUL.py
filenamereports which if any lines of a text file filename contain
NUL
bytes. Here, filename would be the name of the logfile that the program wrote to.
mproc.py
¶
A basic multiprocessing example that uses a non-propagating logger with a stdout handler and a file handler. The handlers are locking by default, non-locking if the
-N
command line flag is given.
Logfiles: examples/_log/mproc/mproc_LOCKING.log
examples/_log/mproc/mproc_NONLOCKING.log
mproc2.py
¶
Another basic multiprocessing example that adds a stdout handler and a file handler to the root logger. The handlers are locking by default, optionally non-locking as explained above.
Logfiles: examples/_log/mproc2/mproc2_LOCKING.log
examples/_log/mproc2/mproc2_NONLOCKING.log
mproc_deco.py
¶
Just like
mproc2.py
but using the deco package to set up multiprocessing.
Logfiles: examples/_log/mproc_deco/logfile (LOCKING).log
examples/_log/mproc_deco/logfile (NONLOCKING).log
mproc_deco_rot_fh.py
¶
Adds a stdout handler and a rotating file handler to the root logger. The handlers are locking by default, optionally non-locking as explained above. This example uses deco to set up multiprocessing,
Logfiles: examples/_log/mproc_deco_rot_fh/LOCKING/rot_fh.log
examples/_log/mproc_deco_rot_fh/LOCKING/rot_fh.log.1
...
examples/_log/mproc_deco_rot_fh/LOCKING/rot_fh.log.10
examples/_log/mproc_deco_rot_fh/NONLOCKING/rot_fh.log
examples/_log/mproc_deco_rot_fh/NONLOCKING/rot_fh.log.1
...
examples/_log/mproc_deco_rot_fh/NONLOCKING/rot_fh.log.10
mproc_deco_syslog.py
¶
Adds a stdout handler and a syslog handler to the root logger. The handlers are locking by default, optionally non-locking as explained above. This example uses deco to set up multiprocessing,
mproc_approach__locking_handlers.py
and mproc_approach__queue_handler_logging_thread.py
¶
These two programs illustrate two approaches to logging in the presence of multiprocessing: one uses prelogging’s native locking handlers; the other uses a queue handler and a logging thread.
See Using QueueHandlers (Python 3 only) in the chapter Further Topics and Recipes for (much) more about the latter.
locking handler logfiles: examples/_log/mproc_LH/mplog.log
,examples/_log/mproc_LH/mplog-errors.log
,examples/_log/mproc_LH/mplog-foo.log
queue handler logfiles: examples/_log/mproc_QHLT/mplog.log
,examples/_log/mproc_QHLT/mplog-errors.log
,examples/_log/mproc_QHLT/mplog-foo.log