1. .. _logging-how-to:
    
  2. 
    
  3. ================================
    
  4. How to configure and use logging
    
  5. ================================
    
  6. 
    
  7. .. seealso::
    
  8. 
    
  9.     * :ref:`Django logging reference <logging-ref>`
    
  10.     * :ref:`Django logging overview <logging-explanation>`
    
  11. 
    
  12. Django provides a working :ref:`default logging configuration
    
  13. <default-logging-configuration>` that is readily extended.
    
  14. 
    
  15. Make a basic logging call
    
  16. =========================
    
  17. 
    
  18. To send a log message from within your code, you place a logging call into it.
    
  19. 
    
  20. .. admonition:: Don't be tempted to use logging calls in ``settings.py``.
    
  21. 
    
  22.     The way that Django logging is configured as part of the ``setup()``
    
  23.     function means that logging calls placed in ``settings.py`` may not work as
    
  24.     expected, because *logging will not be set up at that point*. To explore
    
  25.     logging, use a view function as suggested in the example below.
    
  26. 
    
  27. First, import the Python logging library, and then obtain a logger instance
    
  28. with :py:func:`logging.getLogger`. Provide the ``getLogger()`` method with a
    
  29. name to identify it and the records it emits. A good option is to use
    
  30. ``__name__`` (see :ref:`naming-loggers` below for more on this) which will
    
  31. provide the name of the current Python module as a dotted path::
    
  32. 
    
  33.     import logging
    
  34. 
    
  35.     logger = logging.getLogger(__name__)
    
  36. 
    
  37. It's a good convention to perform this declaration at module level.
    
  38. 
    
  39. And then in a function, for example in a view, send a record to the logger::
    
  40. 
    
  41.     def some_view(request):
    
  42.         ...
    
  43.         if some_risky_state:
    
  44.             logger.warning('Platform is running at risk')
    
  45. 
    
  46. When this code is executed, a :py:class:`~logging.LogRecord` containing that
    
  47. message will be sent to the logger. If you're using Django's default logging
    
  48. configuration, the message will appear in the console.
    
  49. 
    
  50. The ``WARNING`` level used in the example above is one of several
    
  51. :ref:`logging severity levels <topic-logging-parts-loggers>`: ``DEBUG``,
    
  52. ``INFO``, ``WARNING``, ``ERROR``, ``CRITICAL``. So, another example might be::
    
  53. 
    
  54.     logger.critical('Payment system is not responding')
    
  55. 
    
  56. .. important::
    
  57. 
    
  58.     Records with a level lower than ``WARNING`` will not appear in the console
    
  59.     by default. Changing this behavior requires additional configuration.
    
  60. 
    
  61. Customize logging configuration
    
  62. ===============================
    
  63. 
    
  64. Although Django's logging configuration works out of the box, you can control
    
  65. exactly how your logs are sent to various destinations - to log files, external
    
  66. services, email and so on - with some additional configuration.
    
  67. 
    
  68. You can configure:
    
  69. 
    
  70. * logger mappings, to determine which records are sent to which handlers
    
  71. * handlers, to determine what they do with the records they receive
    
  72. * filters, to provide additional control over the transfer of records, and
    
  73.   even modify records in-place
    
  74. * formatters, to convert :class:`~logging.LogRecord` objects to a string or
    
  75.   other form for consumption by human beings or another system
    
  76. 
    
  77. There are various ways of configuring logging. In Django, the
    
  78. :setting:`LOGGING` setting is most commonly used. The setting uses the
    
  79. :ref:`dictConfig format <logging-config-dictschema>`, and extends the
    
  80. :ref:`default logging configuration <default-logging-definition>`.
    
  81. 
    
  82. See :ref:`configuring-logging` for an explanation of how your custom settings
    
  83. are merged with Django's defaults.
    
  84. 
    
  85. See the :mod:`Python logging documentation <python:logging.config>` for
    
  86. details of other ways of configuring logging. For the sake of simplicity, this
    
  87. documentation will only consider configuration via the ``LOGGING`` setting.
    
  88. 
    
  89. .. _basic-logger-configuration:
    
  90. 
    
  91. Basic logging configuration
    
  92. ---------------------------
    
  93. 
    
  94. When configuring logging, it makes sense to
    
  95. 
    
  96. Create a ``LOGGING`` dictionary
    
  97. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  98. 
    
  99. In your ``settings.py``::
    
  100. 
    
  101.     LOGGING = {
    
  102.         'version': 1,                       # the dictConfig format version
    
  103.         'disable_existing_loggers': False,  # retain the default loggers
    
  104.     }
    
  105. 
    
  106. It nearly always makes sense to retain and extend the default logging
    
  107. configuration by setting ``disable_existing_loggers`` to ``False``.
    
  108. 
    
  109. Configure a handler
    
  110. ~~~~~~~~~~~~~~~~~~~
    
  111. 
    
  112. This example configures a single handler named ``file``, that uses Python's
    
  113. :class:`~logging.FileHandler` to save logs of level ``DEBUG`` and higher to the
    
  114. file ``general.log`` (at the project root):
    
  115. 
    
  116. .. code-block:: python
    
  117.     :emphasize-lines: 3-8
    
  118. 
    
  119.     LOGGING = {
    
  120.         [...]
    
  121.         'handlers': {
    
  122.             'file': {
    
  123.                 'class': 'logging.FileHandler',
    
  124.                 'filename': 'general.log',
    
  125.             },
    
  126.         },
    
  127.     }
    
  128. 
    
  129. Different handler classes take different configuration options. For more
    
  130. information on available handler classes, see the
    
  131. :class:`~django.utils.log.AdminEmailHandler` provided by Django and the various
    
  132. :py:mod:`handler classes <logging.handlers>` provided by Python.
    
  133. 
    
  134. Logging levels can also be set on the handlers (by default, they accept log
    
  135. messages of all levels). Using the example above, adding:
    
  136. 
    
  137. .. code-block:: python
    
  138.     :emphasize-lines: 4
    
  139. 
    
  140.     {
    
  141.         'class': 'logging.FileHandler',
    
  142.         'filename': 'general.log',
    
  143.         'level': 'DEBUG',
    
  144.     }
    
  145. 
    
  146. would define a handler configuration that only accepts records of level
    
  147. ``DEBUG`` and higher.
    
  148. 
    
  149. Configure a logger mapping
    
  150. ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  151. 
    
  152. To send records to this handler, configure a logger mapping to use it for
    
  153. example:
    
  154. 
    
  155. .. code-block:: python
    
  156.     :emphasize-lines: 3-8
    
  157. 
    
  158.     LOGGING = {
    
  159.         [...]
    
  160.         'loggers': {
    
  161.             '': {
    
  162.                 'level': 'DEBUG',
    
  163.                 'handlers': ['file'],
    
  164.             },
    
  165.         },
    
  166.     }
    
  167. 
    
  168. The mapping's name determines which log records it will process. This
    
  169. configuration (``''``) is *unnamed*. That means that it will process records
    
  170. from *all* loggers (see :ref:`naming-loggers` below on how to use the mapping
    
  171. name to determine the loggers for which it will process records).
    
  172. 
    
  173. It will forward messages of levels ``DEBUG`` and higher to the handler named
    
  174. ``file``.
    
  175. 
    
  176. Note that a logger can forward messages to multiple handlers, so the relation
    
  177. between loggers and handlers is many-to-many.
    
  178. 
    
  179. If you execute::
    
  180. 
    
  181.     logger.debug('Attempting to connect to API')
    
  182. 
    
  183. in your code, you will find that message in the file ``general.log`` in the
    
  184. root of the project.
    
  185. 
    
  186. Configure a formatter
    
  187. ~~~~~~~~~~~~~~~~~~~~~
    
  188. 
    
  189. By default, the final log output contains the message part of each :class:`log
    
  190. record <logging.LogRecord>`. Use a formatter if you want to include additional
    
  191. data. First name and define your formatters - this example defines
    
  192. formatters named ``verbose`` and ``simple``:
    
  193. 
    
  194. .. code-block:: python
    
  195.     :emphasize-lines: 3-12
    
  196. 
    
  197.     LOGGING = {
    
  198.         [...]
    
  199.         'formatters': {
    
  200.             'verbose': {
    
  201.                 'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
    
  202.                 'style': '{',
    
  203.             },
    
  204.             'simple': {
    
  205.                 'format': '{levelname} {message}',
    
  206.                 'style': '{',
    
  207.             },
    
  208.         },
    
  209.     }
    
  210. 
    
  211. The ``style`` keyword allows you to specify ``{`` for :meth:`str.format` or
    
  212. ``$`` for :class:`string.Template` formatting; the default is ``$``.
    
  213. 
    
  214. See :ref:`logrecord-attributes` for the :class:`~logging.LogRecord` attributes
    
  215. you can include.
    
  216. 
    
  217. To apply a formatter to a handler, add a ``formatter`` entry to the handler's
    
  218. dictionary referring to the formatter by name, for example:
    
  219. 
    
  220. .. code-block:: python
    
  221.     :emphasize-lines: 5
    
  222. 
    
  223.     'handlers': {
    
  224.         'file': {
    
  225.             'class': 'logging.FileHandler',
    
  226.             'filename': 'general.log',
    
  227.             'formatter': 'verbose',
    
  228.         },
    
  229.     },
    
  230. 
    
  231. .. _naming-loggers:
    
  232. 
    
  233. Use logger namespacing
    
  234. ~~~~~~~~~~~~~~~~~~~~~~
    
  235. 
    
  236. The unnamed logging configuration ``''`` captures logs from any Python
    
  237. application. A named logging configuration will capture logs only from loggers
    
  238. with matching names.
    
  239. 
    
  240. The namespace of a logger instance is defined using
    
  241. :py:func:`~logging.getLogger`. For example in ``views.py`` of ``my_app``::
    
  242. 
    
  243.     logger = logging.getLogger(__name__)
    
  244. 
    
  245. will create a logger in the ``my_app.views`` namespace. ``__name__`` allows you
    
  246. to organize log messages according to their provenance within your project's
    
  247. applications automatically. It also ensures that you will not experience name
    
  248. collisions.
    
  249. 
    
  250. A logger mapping named ``my_app.views`` will capture records from this logger:
    
  251. 
    
  252. .. code-block:: python
    
  253.     :emphasize-lines: 4
    
  254. 
    
  255.     LOGGING = {
    
  256.         [...]
    
  257.         'loggers': {
    
  258.             'my_app.views': {
    
  259.                 ...
    
  260.             },
    
  261.         },
    
  262.     }
    
  263. 
    
  264. A logger mapping named ``my_app`` will be more permissive, capturing records
    
  265. from loggers anywhere within the ``my_app`` namespace (including
    
  266. ``my_app.views``, ``my_app.utils``, and so on):
    
  267. 
    
  268. .. code-block:: python
    
  269.     :emphasize-lines: 4
    
  270. 
    
  271.     LOGGING = {
    
  272.         [...]
    
  273.         'loggers': {
    
  274.             'my_app': {
    
  275.                 ...
    
  276.             },
    
  277.         },
    
  278.     }
    
  279. 
    
  280. You can also define logger namespacing explicitly::
    
  281. 
    
  282.     logger = logging.getLogger('project.payment')
    
  283. 
    
  284. and set up logger mappings accordingly.
    
  285. 
    
  286. .. _naming-loggers-hierarchy:
    
  287. 
    
  288. Using logger hierarchies and propagation
    
  289. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
  290. 
    
  291. Logger naming is *hierarchical*. ``my_app`` is the parent of ``my_app.views``,
    
  292. which is the parent of ``my_app.views.private``. Unless specified otherwise,
    
  293. logger mappings will propagate the records they process to their parents - a
    
  294. record from a logger in the ``my_app.views.private`` namespace will be handled
    
  295. by a mapping for both ``my_app`` and ``my_app.views``.
    
  296. 
    
  297. To manage this behavior, set the propagation key on the mappings you define::
    
  298. 
    
  299.     LOGGING = {
    
  300.         [...]
    
  301.         'loggers': {
    
  302.             'my_app': {
    
  303.                 [...]
    
  304.             },
    
  305.             'my_app.views': {
    
  306.                 [...]
    
  307.             },
    
  308.             'my_app.views.private': {
    
  309.                 [...]
    
  310.                 'propagate': False,
    
  311.             },
    
  312.         },
    
  313.     }
    
  314. 
    
  315. ``propagate`` defaults to ``True``. In this example, the logs from
    
  316. ``my_app.views.private`` will not be handled by the parent, but logs from
    
  317. ``my_app.views`` will.
    
  318. 
    
  319. Configure responsive logging
    
  320. ----------------------------
    
  321. 
    
  322. Logging is most useful when it contains as much information as possible, but
    
  323. not information that you don't need - and how much you need depends upon what
    
  324. you're doing. When you're debugging, you need a level of information that would
    
  325. be excessive and unhelpful if you had to deal with it in production.
    
  326. 
    
  327. You can configure logging to provide you with the level of detail you need,
    
  328. when you need it. Rather than manually change configuration to achieve this, a
    
  329. better way is to apply configuration automatically according to the
    
  330. environment.
    
  331. 
    
  332. For example, you could set an environment variable ``DJANGO_LOG_LEVEL``
    
  333. appropriately in your development and staging environments, and make use of it
    
  334. in a logger mapping thus::
    
  335. 
    
  336.     'level': os.getenv('DJANGO_LOG_LEVEL', 'WARNING')
    
  337. 
    
  338. \- so that unless the environment specifies a lower log level, this
    
  339. configuration will only forward records of severity ``WARNING`` and above to
    
  340. its handler.
    
  341. 
    
  342. Other options in the configuration (such as the ``level`` or ``formatter``
    
  343. option of handlers) can be similarly managed.