Refs #32880 -- Created a new logging how-to document.

Moved how-to material from topic document into a new document, and
added new material. Introduced minor improvements to logging
reference document.
This commit is contained in:
Daniele Procida 2021-07-03 22:31:26 +02:00 committed by Mariusz Felisiak
parent 5848b3a1d7
commit 013a1824d3
4 changed files with 364 additions and 103 deletions

View file

@ -1,10 +1,13 @@
.. _logging-explanation:
=======
Logging
=======
.. seealso::
:ref:`Django logging reference <logging_ref>`.
* :ref:`logging-how-to`
* :ref:`Django logging reference <logging-ref>`
Python programmers will often use ``print()`` in their code as a quick and
convenient debugging tool. Using the logging framework is only a little more
@ -163,10 +166,6 @@ and has access to the information, and so on.
Configuring logging
===================
It isn't enough to just put logging calls into your code. You also need to
configure the loggers, handlers, filters, and formatters to ensure you can use
the logging output.
Python's logging library provides several techniques to configure
logging, ranging from a programmatic interface to configuration files.
By default, Django uses the :ref:`dictConfig format
@ -457,96 +456,3 @@ Note that the default configuration process only calls
configuring the logging in your settings file will load your logging config
immediately. As such, your logging config must appear *after* any settings on
which it depends.
.. _logging-how-to:
How to use logging
==================
Django provides a :ref:`default logging configuration
<default-logging-configuration>`, so you don't need to provide any additional
configuration in order to start using logging (it's the default configuration
that for example generates the messages that appear in the console when using
the :djadmin:`runserver`).
Make a basic logging call
-------------------------
To send a log message from within your code, you place a logging call into it.
.. admonition:: Don't be tempted to use logging calls in ``settings.py``
The way that Django logging is configured as part of the ``setup()``
function means that logging calls placed in ``settings.py`` may not work as
expected, because *logging will not be set up at that point*. To explore
logging, use a view function as suggested in the example below.
First, import the Python logging library, and then obtain a logger instance
with :py:func:`logging.getLogger`. The ``getLogger()`` method must be provided
with a name. A good option is to use ``__name__``, which will provide the name
of the current Python module (see :ref:`naming-loggers` for use of explicit
naming)::
import logging
logger = logging.getLogger(__name__)
And then in a function, for example in a view, send a message to the logger::
def some_view(request):
...
if some_risky_state:
logger.warning('Platform is running at risk')
When this code is executed, that message will be sent to the logger (and if
you're using Django's default logging configuration, it will appear in the
console).
The ``WARNING`` level used in the example above is one of several
:ref:`logging severity levels <topic-logging-parts-loggers>`: ``DEBUG``,
``INFO``, ``WARNING``, ``ERROR``, ``CRITICAL``. So, another example might be::
logger.critical('Payment system is not responding')
The default logging configuration, which Django inherits from the Python
logging module, prints all messages of level ``WARNING`` and higher to the
console. Django's own defaults will *not* pass ``INFO`` or lower severity
messages from applications other than Django itself to the console - that will
need to be configured explicitly.
.. _naming-loggers:
Name logger instances
---------------------
Every logger instance has a name. By convention, the logger name is usually
``__name__``, the name of the Python module in which
:func:`logging.getLogger()` is called. This allows you to filter and handle
logging calls on a per-module basis. However, if you have some other way of
organizing your logging messages, you can provide any dot-separated name to
identify your logger::
# Get an instance of a specific named logger
logger = logging.getLogger('project.interesting.stuff')
.. _naming-loggers-hierarchy:
Logger hierarchy
~~~~~~~~~~~~~~~~
The dotted paths of logger names define a hierarchy. The
``project.interesting`` logger is considered to be a parent of the
``project.interesting.stuff`` logger; the ``project`` logger is a parent of the
``project.interesting`` logger. (Note that this hierarchy does not need to
reflect the actual Python module hierarchy.)
Why is the hierarchy important? Well, because loggers can be set to
*propagate* their logging calls to their parents. In this way, you can
define a single set of handlers at the root of a logger tree, and
capture all logging calls in the subtree of loggers. A logger defined
in the ``project`` namespace will catch all logging messages issued on
the ``project.interesting`` and ``project.interesting.stuff`` loggers.
This propagation can be controlled on a per-logger basis. If
you don't want a particular logger to propagate to its parents, you
can turn off this behavior.