[back to the tutorial] [Python logging documentation]
This page is an exerpt from the Python logging documentation, with edits to make it apply to the R logging module. it introduces the concepts of Logger, Handler and Formatter objects. In Python you will also find Filter objects, but I have not implemented them in the R logging module.
The logging library takes a modular approach and offers the several categories of components: loggers, handlers, and formatters. Loggers expose the interface that application code directly uses. Handlers send the log records to the appropriate destination. Formatters specify the layout of the resultant log record.
Logger objects have a threefold job. First, the library exposes several methods to application code so that applications can log messages at runtime. Second, logger objects determine which log messages to act upon based upon severity (the default filtering facility) or filter objects. Third, logger objects pass along relevant log messages to all interested log handlers.
The most widely used functions on logger objects fall into two categories: configuration and message sending. Configuration means: setting the level.
With the logger object configured, the following functions create log messages:
logdebug(), loginfo(), logwarn(), and logerror() all create log records with a message and a level that corresponds to their respective method names. The message is actually a format string, which may contain the standard string substitution syntax of %s, %d, %f, and so on. The rest of their arguments is a list of objects that correspond with the substitution fields in the message.
loglevel() takes a log level as an explicit argument. This is a little more verbose for logging messages than using the log level convenience methods listed above, but this is how to log at custom log levels.
getLogger() returns a reference to a logger instance with the specified name if it is provided, or root if not. The names are period-separated hierarchical structures. Multiple calls to getLogger() with the same name will return a reference to the same logger object. Loggers that are further down in the hierarchical list are children of loggers higher up in the list. For example, given a logger with a name of foo, loggers with names of foo.bar, foo.bar.baz, and foo.bam are all descendants of foo. Child loggers propagate messages up to the handlers associated with their ancestor loggers. Because of this, it is unnecessary to define and configure handlers for all the loggers an application uses. It is sufficient to configure handlers for a top-level logger and create child loggers as needed.
Handler objects are responsible for dispatching the appropriate log messages (based on the log messages' severity) to the handler's specified destination. You can add zero or more handler objects to Logger objects with the addHandler() function. As an example scenario, an application may want to send all log messages to a log file, all log messages of error or higher to stdout, and all messages of critical to an email address. This scenario requires three individual handlers where each handler is responsible for sending messages of a specific severity to a specific location.
There are very few handler related functions in the logging library for application developers to concern themselves with. The only handler methods that seem relevant for application developers who are using the built-in handler objects (that is, not creating custom handlers) are the following configuration methods:
Formatter functions configure the final order, structure, and contents of the log message. R logging formatters work in a quite differnt way than the Python formatters, so I'm not quoting this section.