diff --git a/docs/topics/logging.txt b/docs/topics/logging.txt index 731b8f3954..b9a47ff324 100644 --- a/docs/topics/logging.txt +++ b/docs/topics/logging.txt @@ -6,6 +6,12 @@ Logging :ref:`Django logging reference `. +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 +effort than that, but it's much more elegant and flexible. As well as being +useful for debugging, logging can also provide you with more - and better +structured - information about the state and health of your application. + Overview ======== @@ -117,125 +123,40 @@ of a Python formatting string containing :ref:`LogRecord attributes `; however, you can also write custom formatters to implement specific formatting behavior. -.. _logging-how-to: +.. _logging-security-implications: -How to use logging -================== +Security implications +===================== -Django provides a :ref:`default logging configuration -`, that for example generates the messages that -appear in the console when using the :djadmin:`runserver`. +The logging system handles potentially sensitive information. For example, the +log record may contain information about a web request or a stack trace, while +some of the data you collect in your own loggers may also have security +implications. You need to be sure you know: -Make a basic logging call -------------------------- +* what information is collected +* where it will subsequently be stored +* how it will be transferred +* who might have access to it. -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 -effort than that, but it's much more elegant and flexible. As well as being -useful for debugging, logging can also provide you with more - and better -structured - information about the state and health of your application. +To help control the collection of sensitive information, you can explicitly +designate certain sensitive information to be filtered out of error reports -- +read more about how to :ref:`filter error reports `. -To send a log message from within your code, you place a logging call into it. +``AdminEmailHandler`` +--------------------- -.. admonition:: Don't be tempted to use logging calls in ``settings.py`` +The built-in :class:`~django.utils.log.AdminEmailHandler` deserves a mention in +the context of security. If its ``include_html`` option is enabled, the email +message it sends will contain a full traceback, with names and values of local +variables at each level of the stack, plus the values of your Django settings +(in other words, the same level of detail that is exposed in a web page when +:setting:`DEBUG` is ``True``). - 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 `: ``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: - -Naming loggers --------------- - -The call to :func:`logging.getLogger()` obtains (creating, if -necessary) an instance of a logger. The logger instance is identified -by a name. This name is used to identify the logger for configuration -purposes. - -By convention, the logger name is usually ``__name__``, the name of -the Python module that contains the logger. 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. - -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. - -Making logging calls --------------------- - -The logger instance contains an entry method for each of the default -log levels: - -* ``logger.debug()`` -* ``logger.info()`` -* ``logger.warning()`` -* ``logger.error()`` -* ``logger.critical()`` - -There are two other logging calls available: - -* ``logger.log()``: Manually emits a logging message with a - specific log level. - -* ``logger.exception()``: Creates an ``ERROR`` level logging - message wrapping the current exception stack frame. +It's generally not considered a good idea to send such potentially sensitive +information over email. Consider instead using one of the many third-party +services to which detailed logs can be sent to get the best of multiple worlds +-- the rich information of full tracebacks, clear management of who is notified +and has access to the information, and so on. .. _configuring-logging: @@ -537,37 +458,95 @@ 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-security-implications: +.. _logging-how-to: -Security implications -===================== +How to use logging +================== -The logging system handles potentially sensitive information. For example, the -log record may contain information about a web request or a stack trace, while -some of the data you collect in your own loggers may also have security -implications. You need to be sure you know: +Django provides a :ref:`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`). -* what information is collected -* where it will subsequently be stored -* how it will be transferred -* who might have access to it. +Make a basic logging call +------------------------- -To help control the collection of sensitive information, you can explicitly -designate certain sensitive information to be filtered out of error reports -- -read more about how to :ref:`filter error reports `. +To send a log message from within your code, you place a logging call into it. -``AdminEmailHandler`` +.. 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 `: ``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 --------------------- -The built-in :class:`~django.utils.log.AdminEmailHandler` deserves a mention in -the context of security. If its ``include_html`` option is enabled, the email -message it sends will contain a full traceback, with names and values of local -variables at each level of the stack, plus the values of your Django settings -(in other words, the same level of detail that is exposed in a web page when -:setting:`DEBUG` is ``True``). +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:: -It's generally not considered a good idea to send such potentially sensitive -information over email. Consider instead using one of the many third-party -services to which detailed logs can be sent to get the best of multiple worlds --- the rich information of full tracebacks, clear management of who is notified -and has access to the information, and so on. + # 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.