Issue #18759: Improved cross-references in logging documentation.

This commit is contained in:
Vinay Sajip 2013-08-17 00:38:48 +01:00
parent 88b174c977
commit 10b513098a
4 changed files with 78 additions and 69 deletions

View File

@ -97,11 +97,11 @@ The output looks like this::
Multiple handlers and formatters Multiple handlers and formatters
-------------------------------- --------------------------------
Loggers are plain Python objects. The :func:`addHandler` method has no minimum Loggers are plain Python objects. The :meth:`~Logger.addHandler` method has no
or maximum quota for the number of handlers you may add. Sometimes it will be minimum or maximum quota for the number of handlers you may add. Sometimes it
beneficial for an application to log all messages of all severities to a text will be beneficial for an application to log all messages of all severities to a
file while simultaneously logging errors or above to the console. To set this text file while simultaneously logging errors or above to the console. To set
up, simply configure the appropriate handlers. The logging calls in the this up, simply configure the appropriate handlers. The logging calls in the
application code will remain unchanged. Here is a slight modification to the application code will remain unchanged. Here is a slight modification to the
previous simple module-based configuration example:: previous simple module-based configuration example::
@ -395,8 +395,9 @@ printed on the console; on the server side, you should see something like::
Note that there are some security issues with pickle in some scenarios. If Note that there are some security issues with pickle in some scenarios. If
these affect you, you can use an alternative serialization scheme by overriding these affect you, you can use an alternative serialization scheme by overriding
the :meth:`makePickle` method and implementing your alternative there, as the :meth:`~handlers.SocketHandler.makePickle` method and implementing your
well as adapting the above script to use your alternative serialization. alternative there, as well as adapting the above script to use your alternative
serialization.
.. _context-info: .. _context-info:
@ -404,6 +405,8 @@ well as adapting the above script to use your alternative serialization.
Adding contextual information to your logging output Adding contextual information to your logging output
---------------------------------------------------- ----------------------------------------------------
.. currentmodule:: logging
Sometimes you want logging output to contain contextual information in Sometimes you want logging output to contain contextual information in
addition to the parameters passed to the logging call. For example, in a addition to the parameters passed to the logging call. For example, in a
networked application, it may be desirable to log client-specific information networked application, it may be desirable to log client-specific information
@ -445,9 +448,9 @@ information in the delegated call. Here's a snippet from the code of
msg, kwargs = self.process(msg, kwargs) msg, kwargs = self.process(msg, kwargs)
self.logger.debug(msg, *args, **kwargs) self.logger.debug(msg, *args, **kwargs)
The :meth:`process` method of :class:`LoggerAdapter` is where the contextual The :meth:`~LoggerAdapter.process` method of :class:`LoggerAdapter` is where the
information is added to the logging output. It's passed the message and contextual information is added to the logging output. It's passed the message
keyword arguments of the logging call, and it passes back (potentially) and keyword arguments of the logging call, and it passes back (potentially)
modified versions of these to use in the call to the underlying logger. The modified versions of these to use in the call to the underlying logger. The
default implementation of this method leaves the message alone, but inserts default implementation of this method leaves the message alone, but inserts
an 'extra' key in the keyword argument whose value is the dict-like object an 'extra' key in the keyword argument whose value is the dict-like object
@ -459,8 +462,8 @@ merged into the :class:`LogRecord` instance's __dict__, allowing you to use
customized strings with your :class:`Formatter` instances which know about customized strings with your :class:`Formatter` instances which know about
the keys of the dict-like object. If you need a different method, e.g. if you the keys of the dict-like object. If you need a different method, e.g. if you
want to prepend or append the contextual information to the message string, want to prepend or append the contextual information to the message string,
you just need to subclass :class:`LoggerAdapter` and override :meth:`process` you just need to subclass :class:`LoggerAdapter` and override
to do what you need. Here is a simple example:: :meth:`~LoggerAdapter.process` to do what you need. Here is a simple example::
class CustomAdapter(logging.LoggerAdapter): class CustomAdapter(logging.LoggerAdapter):
""" """
@ -569,25 +572,23 @@ threads in a single process *is* supported, logging to a single file from
*multiple processes* is *not* supported, because there is no standard way to *multiple processes* is *not* supported, because there is no standard way to
serialize access to a single file across multiple processes in Python. If you serialize access to a single file across multiple processes in Python. If you
need to log to a single file from multiple processes, one way of doing this is need to log to a single file from multiple processes, one way of doing this is
to have all the processes log to a :class:`SocketHandler`, and have a separate to have all the processes log to a :class:`~handlers.SocketHandler`, and have a
process which implements a socket server which reads from the socket and logs separate process which implements a socket server which reads from the socket
to file. (If you prefer, you can dedicate one thread in one of the existing and logs to file. (If you prefer, you can dedicate one thread in one of the
processes to perform this function.) :ref:`This section <network-logging>` existing processes to perform this function.)
documents this approach in more detail and includes a working socket receiver :ref:`This section <network-logging>` documents this approach in more detail and
which can be used as a starting point for you to adapt in your own includes a working socket receiver which can be used as a starting point for you
applications. to adapt in your own applications.
If you are using a recent version of Python which includes the If you are using a recent version of Python which includes the
:mod:`multiprocessing` module, you could write your own handler which uses the :mod:`multiprocessing` module, you could write your own handler which uses the
:class:`Lock` class from this module to serialize access to the file from :class:`~multiprocessing.Lock` class from this module to serialize access to the
your processes. The existing :class:`FileHandler` and subclasses do not make file from your processes. The existing :class:`FileHandler` and subclasses do
use of :mod:`multiprocessing` at present, though they may do so in the future. not make use of :mod:`multiprocessing` at present, though they may do so in the
Note that at present, the :mod:`multiprocessing` module does not provide future. Note that at present, the :mod:`multiprocessing` module does not provide
working lock functionality on all platforms (see working lock functionality on all platforms (see
http://bugs.python.org/issue3770). http://bugs.python.org/issue3770).
.. currentmodule:: logging.handlers
Using file rotation Using file rotation
------------------- -------------------
@ -599,7 +600,7 @@ Sometimes you want to let a log file grow to a certain size, then open a new
file and log to that. You may want to keep a certain number of these files, and file and log to that. You may want to keep a certain number of these files, and
when that many files have been created, rotate the files so that the number of when that many files have been created, rotate the files so that the number of
files and the size of the files both remain bounded. For this usage pattern, the files and the size of the files both remain bounded. For this usage pattern, the
logging package provides a :class:`RotatingFileHandler`:: logging package provides a :class:`~handlers.RotatingFileHandler`::
import glob import glob
import logging import logging
@ -650,7 +651,7 @@ An example dictionary-based configuration
Below is an example of a logging configuration dictionary - it's taken from Below is an example of a logging configuration dictionary - it's taken from
the `documentation on the Django project <https://docs.djangoproject.com/en/1.3/topics/logging/#configuring-logging>`_. the `documentation on the Django project <https://docs.djangoproject.com/en/1.3/topics/logging/#configuring-logging>`_.
This dictionary is passed to :func:`~logging.config.dictConfig` to put the configuration into effect:: This dictionary is passed to :func:`~config.dictConfig` to put the configuration into effect::
LOGGING = { LOGGING = {
'version': 1, 'version': 1,

View File

@ -469,12 +469,13 @@ Handlers
:class:`~logging.Handler` objects are responsible for dispatching the :class:`~logging.Handler` objects are responsible for dispatching the
appropriate log messages (based on the log messages' severity) to the handler's appropriate log messages (based on the log messages' severity) to the handler's
specified destination. Logger objects can add zero or more handler objects to specified destination. :class:`Logger` objects can add zero or more handler
themselves with an :func:`addHandler` method. As an example scenario, an objects to themselves with an :meth:`~Logger.addHandler` method. As an example
application may want to send all log messages to a log file, all log messages scenario, an application may want to send all log messages to a log file, all
of error or higher to stdout, and all messages of critical to an email address. log messages of error or higher to stdout, and all messages of critical to an
This scenario requires three individual handlers where each handler is email address. This scenario requires three individual handlers where each
responsible for sending messages of a specific severity to a specific location. handler is responsible for sending messages of a specific severity to a specific
location.
The standard library includes quite a few handler types (see The standard library includes quite a few handler types (see
:ref:`useful-handlers`); the tutorials use mainly :class:`StreamHandler` and :ref:`useful-handlers`); the tutorials use mainly :class:`StreamHandler` and
@ -485,16 +486,17 @@ themselves with. The only handler methods that seem relevant for application
developers who are using the built-in handler objects (that is, not creating developers who are using the built-in handler objects (that is, not creating
custom handlers) are the following configuration methods: custom handlers) are the following configuration methods:
* The :meth:`Handler.setLevel` method, just as in logger objects, specifies the * The :meth:`~Handler.setLevel` method, just as in logger objects, specifies the
lowest severity that will be dispatched to the appropriate destination. Why lowest severity that will be dispatched to the appropriate destination. Why
are there two :func:`setLevel` methods? The level set in the logger are there two :func:`setLevel` methods? The level set in the logger
determines which severity of messages it will pass to its handlers. The level determines which severity of messages it will pass to its handlers. The level
set in each handler determines which messages that handler will send on. set in each handler determines which messages that handler will send on.
* :func:`setFormatter` selects a Formatter object for this handler to use. * :meth:`~Handler.setFormatter` selects a Formatter object for this handler to
use.
* :func:`addFilter` and :func:`removeFilter` respectively configure and * :meth:`~Handler.addFilter` and :meth:`~Handler.removeFilter` respectively
deconfigure filter objects on handlers. configure and deconfigure filter objects on handlers.
Application code should not directly instantiate and use instances of Application code should not directly instantiate and use instances of
:class:`Handler`. Instead, the :class:`Handler` class is a base class that :class:`Handler`. Instead, the :class:`Handler` class is a base class that
@ -918,16 +920,16 @@ Logged messages are formatted for presentation through instances of the
use with the % operator and a dictionary. use with the % operator and a dictionary.
For formatting multiple messages in a batch, instances of For formatting multiple messages in a batch, instances of
:class:`BufferingFormatter` can be used. In addition to the format string (which :class:`~handlers.BufferingFormatter` can be used. In addition to the format
is applied to each message in the batch), there is provision for header and string (which is applied to each message in the batch), there is provision for
trailer format strings. header and trailer format strings.
When filtering based on logger level and/or handler level is not enough, When filtering based on logger level and/or handler level is not enough,
instances of :class:`Filter` can be added to both :class:`Logger` and instances of :class:`Filter` can be added to both :class:`Logger` and
:class:`Handler` instances (through their :meth:`addFilter` method). Before :class:`Handler` instances (through their :meth:`~Handler.addFilter` method).
deciding to process a message further, both loggers and handlers consult all Before deciding to process a message further, both loggers and handlers consult
their filters for permission. If any filter returns a false value, the message all their filters for permission. If any filter returns a false value, the
is not processed further. message is not processed further.
The basic :class:`Filter` functionality allows filtering by specific logger The basic :class:`Filter` functionality allows filtering by specific logger
name. If this feature is used, messages sent to the named logger and its name. If this feature is used, messages sent to the named logger and its
@ -945,19 +947,20 @@ in production. This is so that errors which occur while handling logging events
cause the application using logging to terminate prematurely. cause the application using logging to terminate prematurely.
:class:`SystemExit` and :class:`KeyboardInterrupt` exceptions are never :class:`SystemExit` and :class:`KeyboardInterrupt` exceptions are never
swallowed. Other exceptions which occur during the :meth:`emit` method of a swallowed. Other exceptions which occur during the :meth:`~Handler.emit` method
:class:`Handler` subclass are passed to its :meth:`handleError` method. of a :class:`Handler` subclass are passed to its :meth:`~Handler.handleError`
method.
The default implementation of :meth:`handleError` in :class:`Handler` checks The default implementation of :meth:`~Handler.handleError` in :class:`Handler`
to see if a module-level variable, :data:`raiseExceptions`, is set. If set, a checks to see if a module-level variable, :data:`raiseExceptions`, is set. If
traceback is printed to :data:`sys.stderr`. If not set, the exception is swallowed. set, a traceback is printed to :data:`sys.stderr`. If not set, the exception is
swallowed.
.. note:: The default value of :data:`raiseExceptions` is ``True``. This is .. note:: The default value of :data:`raiseExceptions` is ``True``. This is
because during development, you typically want to be notified of any because during development, you typically want to be notified of any
exceptions that occur. It's advised that you set :data:`raiseExceptions` to exceptions that occur. It's advised that you set :data:`raiseExceptions` to
``False`` for production usage. ``False`` for production usage.
.. currentmodule:: logging
.. _arbitrary-object-messages: .. _arbitrary-object-messages:
@ -967,11 +970,11 @@ Using arbitrary objects as messages
In the preceding sections and examples, it has been assumed that the message In the preceding sections and examples, it has been assumed that the message
passed when logging the event is a string. However, this is not the only passed when logging the event is a string. However, this is not the only
possibility. You can pass an arbitrary object as a message, and its possibility. You can pass an arbitrary object as a message, and its
:meth:`__str__` method will be called when the logging system needs to convert :meth:`~object.__str__` method will be called when the logging system needs to
it to a string representation. In fact, if you want to, you can avoid convert it to a string representation. In fact, if you want to, you can avoid
computing a string representation altogether - for example, the computing a string representation altogether - for example, the
:class:`SocketHandler` emits an event by pickling it and sending it over the :class:`~handlers.SocketHandler` emits an event by pickling it and sending it
wire. over the wire.
Optimization Optimization
@ -980,9 +983,10 @@ Optimization
Formatting of message arguments is deferred until it cannot be avoided. Formatting of message arguments is deferred until it cannot be avoided.
However, computing the arguments passed to the logging method can also be However, computing the arguments passed to the logging method can also be
expensive, and you may want to avoid doing it if the logger will just throw expensive, and you may want to avoid doing it if the logger will just throw
away your event. To decide what to do, you can call the :meth:`isEnabledFor` away your event. To decide what to do, you can call the
method which takes a level argument and returns true if the event would be :meth:`~Logger.isEnabledFor` method which takes a level argument and returns
created by the Logger for that level of call. You can write code like this:: true if the event would be created by the Logger for that level of call.
You can write code like this::
if logger.isEnabledFor(logging.DEBUG): if logger.isEnabledFor(logging.DEBUG):
logger.debug('Message with %s, %s', expensive_func1(), logger.debug('Message with %s, %s', expensive_func1(),

View File

@ -104,8 +104,9 @@ in :mod:`logging` itself) and defining handlers which are declared either in
configurations. If no port is specified, the module's default configurations. If no port is specified, the module's default
:const:`DEFAULT_LOGGING_CONFIG_PORT` is used. Logging configurations will be :const:`DEFAULT_LOGGING_CONFIG_PORT` is used. Logging configurations will be
sent as a file suitable for processing by :func:`fileConfig`. Returns a sent as a file suitable for processing by :func:`fileConfig`. Returns a
:class:`Thread` instance on which you can call :meth:`start` to start the :class:`~threading.Thread` instance on which you can call
server, and which you can :meth:`join` when appropriate. To stop the server, :meth:`~threading.Thread.start` to start the server, and which you can
:meth:`~threading.Thread.join` when appropriate. To stop the server,
call :func:`stopListening`. call :func:`stopListening`.
To send a configuration to the socket, read in the configuration file and To send a configuration to the socket, read in the configuration file and
@ -169,11 +170,11 @@ otherwise, the context is used to determine what to instantiate.
* *formatters* - the corresponding value will be a dict in which each * *formatters* - the corresponding value will be a dict in which each
key is a formatter id and each value is a dict describing how to key is a formatter id and each value is a dict describing how to
configure the corresponding Formatter instance. configure the corresponding :class:`~logging.Formatter` instance.
The configuring dict is searched for keys ``format`` and ``datefmt`` The configuring dict is searched for keys ``format`` and ``datefmt``
(with defaults of ``None``) and these are used to construct a (with defaults of ``None``) and these are used to construct a
:class:`logging.Formatter` instance. :class:`~logging.Formatter` instance.
* *filters* - the corresponding value will be a dict in which each key * *filters* - the corresponding value will be a dict in which each key
is a filter id and each value is a dict describing how to configure is a filter id and each value is a dict describing how to configure
@ -711,8 +712,9 @@ format string, with a comma separator. An example time in ISO8601 format is
The ``class`` entry is optional. It indicates the name of the formatter's class The ``class`` entry is optional. It indicates the name of the formatter's class
(as a dotted module and class name.) This option is useful for instantiating a (as a dotted module and class name.) This option is useful for instantiating a
:class:`Formatter` subclass. Subclasses of :class:`Formatter` can present :class:`~logging.Formatter` subclass. Subclasses of
exception tracebacks in an expanded or condensed format. :class:`~logging.Formatter` can present exception tracebacks in an expanded or
condensed format.
.. note:: Due to the use of :func:`eval` as described above, there are .. note:: Due to the use of :func:`eval` as described above, there are
potential security risks which result from using the :func:`listen` to send potential security risks which result from using the :func:`listen` to send

View File

@ -53,8 +53,8 @@ and :meth:`flush` methods).
.. method:: flush() .. method:: flush()
Flushes the stream by calling its :meth:`flush` method. Note that the Flushes the stream by calling its :meth:`flush` method. Note that the
:meth:`close` method is inherited from :class:`Handler` and so does :meth:`close` method is inherited from :class:`~logging.Handler` and so
no output, so an explicit :meth:`flush` call may be needed at times. does no output, so an explicit :meth:`flush` call may be needed at times.
.. _file-handler: .. _file-handler:
@ -142,8 +142,8 @@ new stream.
This handler is not appropriate for use under Windows, because under Windows This handler is not appropriate for use under Windows, because under Windows
open log files cannot be moved or renamed - logging opens the files with open log files cannot be moved or renamed - logging opens the files with
exclusive locks - and so there is no need for such a handler. Furthermore, exclusive locks - and so there is no need for such a handler. Furthermore,
*ST_INO* is not supported under Windows; :func:`stat` always returns zero for *ST_INO* is not supported under Windows; :func:`~os.stat` always returns zero
this value. for this value.
.. class:: WatchedFileHandler(filename[,mode[, encoding[, delay]]]) .. class:: WatchedFileHandler(filename[,mode[, encoding[, delay]]])
@ -305,7 +305,8 @@ sends logging output to a network socket. The base class uses a TCP socket.
binary format. If there is an error with the socket, silently drops the binary format. If there is an error with the socket, silently drops the
packet. If the connection was previously lost, re-establishes the packet. If the connection was previously lost, re-establishes the
connection. To unpickle the record at the receiving end into a connection. To unpickle the record at the receiving end into a
:class:`LogRecord`, use the :func:`makeLogRecord` function. :class:`~logging.LogRecord`, use the :func:`~logging.makeLogRecord`
function.
.. method:: handleError() .. method:: handleError()
@ -383,7 +384,8 @@ over UDP sockets.
Pickles the record's attribute dictionary and writes it to the socket in Pickles the record's attribute dictionary and writes it to the socket in
binary format. If there is an error with the socket, silently drops the binary format. If there is an error with the socket, silently drops the
packet. To unpickle the record at the receiving end into a packet. To unpickle the record at the receiving end into a
:class:`LogRecord`, use the :func:`makeLogRecord` function. :class:`~logging.LogRecord`, use the :func:`~logging.makeLogRecord`
function.
.. method:: makeSocket() .. method:: makeSocket()