Как настроить и использовать протоколирование

Django предоставляет рабочий default logging configuration, который легко расширяется.

Выполните базовый звонок для регистрации

Чтобы отправить сообщение журнала из вашего кода, вы помещаете в него вызов регистрации.

Не поддавайтесь искушению использовать вызовы логирования в settings.py.

То, что логирование в Django настроено как часть функции setup(), означает, что вызовы логирования, размещенные в settings.py, могут работать не так, как ожидается, потому что логирование не будет настроено в этот момент. Чтобы изучить ведение журнала, используйте функцию представления, как показано в примере ниже.

Сначала импортируйте библиотеку Python logging, а затем получите экземпляр логгера с помощью logging.getLogger(). Дайте методу getLogger() имя, чтобы идентифицировать его и записи, которые он выдает. Хорошим вариантом является использование __name__ (подробнее об этом см. ниже Используйте интервалы между именами регистраторов), который предоставит имя текущего модуля Python в виде точечного пути:

import logging

logger = logging.getLogger(__name__)

Это хорошая традиция - выполнять это объявление на уровне модуля.

А затем в функции, например, в представлении, отправьте запись в регистратор:

def some_view(request):
    ...
    if some_risky_state:
        logger.warning('Platform is running at risk')

Когда этот код будет выполнен, в логгер будет отправлено сообщение LogRecord, содержащее это сообщение. Если вы используете стандартную конфигурацию логирования Django, сообщение появится в консоли.

Уровень WARNING, используемый в приведенном выше примере, является одним из нескольких logging severity levels: DEBUG, INFO, WARNING, ERROR, CRITICAL. Другим примером может быть:

logger.critical('Payment system is not responding')

Важно

Записи с уровнем ниже WARNING по умолчанию не отображаются в консоли. Изменение этого поведения требует дополнительной настройки.

Настройка конфигурации протоколирования

Хотя конфигурация ведения журналов в Django работает из коробки, вы можете контролировать, как именно ваши журналы отправляются в различные места назначения - в файлы журналов, внешние сервисы, электронную почту и так далее - с помощью некоторых дополнительных настроек.

Вы можете настроить:

  • сопоставления регистраторов, чтобы определить, какие записи отправляются в какие обработчики
  • обработчики, чтобы определить, что они делают с полученными записями
  • фильтры, чтобы обеспечить дополнительный контроль над передачей записей и даже изменять записи на месте
  • форматеры, для преобразования объектов LogRecord в строку или другую форму для потребления человеком или другой системой

Существуют различные способы настройки протоколирования. В Django чаще всего используется настройка LOGGING. Эта настройка использует dictConfig format, и расширяет default logging configuration.

Смотрите Настройка протоколирования для объяснения того, как ваши пользовательские настройки объединяются с настройками Django по умолчанию.

Подробности о других способах настройки протоколирования см. в Python logging documentation. Для простоты в данной документации рассматривается только настройка с помощью параметра LOGGING.

Базовая конфигурация ведения журнала

При настройке протоколирования имеет смысл

Создайте словарь LOGGING

В вашем settings.py:

LOGGING = {
    'version': 1,                       # the dictConfig format version
    'disable_existing_loggers': False,  # retain the default loggers
}

Почти всегда имеет смысл сохранить и расширить конфигурацию протоколирования по умолчанию, установив disable_existing_loggers в False.

Настройка обработчика

Этот пример настраивает единственный обработчик с именем file, который использует Python FileHandler для сохранения журналов уровня DEBUG и выше в файл general.log (в корне проекта):

LOGGING = {
    [...]
    'handlers': {
        'file': {
            'class': 'logging.FileHandler',
            'filename': 'general.log',
        },
    },
}

Различные классы обработчиков принимают различные параметры конфигурации. Для получения дополнительной информации о доступных классах обработчиков смотрите AdminEmailHandler, предоставляемые Django, и различные handler classes, предоставляемые Python.

Уровни протоколирования также могут быть установлены на обработчиках (по умолчанию они принимают протокольные сообщения всех уровней). Используя приведенный выше пример, добавьте:

{
    'class': 'logging.FileHandler',
    'filename': 'general.log',
    'level': 'DEBUG',
}

определяет конфигурацию обработчика, который принимает только записи уровня DEBUG и выше.

Настройка сопоставления регистраторов

Чтобы отправить записи в этот обработчик, настройте сопоставление регистратора для его использования, например:

LOGGING = {
    [...]
    'loggers': {
        '': {
            'level': 'DEBUG',
            'handlers': ['file'],
        },
    },
}

Имя связки определяет, какие записи журнала она будет обрабатывать. Данная конфигурация ('') является неименованной. Это означает, что она будет обрабатывать записи от всех регистраторов (см. ниже Используйте интервалы между именами регистраторов о том, как использовать имя связки для определения регистраторов, для которых она будет обрабатывать записи).

Он будет пересылать сообщения уровней DEBUG и выше в обработчик с именем file.

Обратите внимание, что регистратор может передавать сообщения нескольким обработчикам, поэтому отношения между регистраторами и обработчиками являются отношениями «многие ко многим».

Если вы выполните:

logger.debug('Attempting to connect to API')

в вашем коде, вы найдете это сообщение в файле general.log в корне проекта.

Настройка форматера

По умолчанию конечный вывод журнала содержит часть сообщения каждого log record. Если вы хотите включить дополнительные данные, используйте форматтер. Сначала назовите и определите свои форматтеры - в данном примере определены форматтеры с именами verbose и simple:

LOGGING = {
    [...]
    'formatters': {
        'verbose': {
            'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
}

Ключевое слово style позволяет указать { для форматирования str.format() или $ для форматирования string.Template; по умолчанию используется $.

Смотрите LogRecord attributes для атрибутов LogRecord, которые вы можете включить.

Чтобы применить форматер к обработчику, добавьте в словарь обработчика запись formatter, ссылающуюся на форматер по имени, например:

'handlers': {
    'file': {
        'class': 'logging.FileHandler',
        'filename': 'general.log',
        'formatter': 'verbose',
    },
},

Используйте интервалы между именами регистраторов

Конфигурация журналирования без имени '' захватывает журналы из любого приложения Python. Именованная конфигурация регистрации будет перехватывать журналы только от регистраторов с совпадающими именами.

Пространство имен экземпляра логгера определяется с помощью getLogger(). Например, в views.py из my_app:

logger = logging.getLogger(__name__)

создаст логгер в пространстве имен my_app.views. __name__ позволяет вам автоматически организовывать сообщения журнала в соответствии с их происхождением в приложениях вашего проекта. Это также гарантирует, что вы не столкнетесь с коллизиями имен.

Сопоставление регистратора с именем my_app.views будет захватывать записи из этого регистратора:

LOGGING = {
    [...]
    'loggers': {
        'my_app.views': {
            ...
        },
    },
}

Отображение регистратора с именем my_app будет более свободным, оно будет захватывать записи из регистраторов в любом месте пространства имен my_app (включая my_app.views, my_app.utils и так далее):

LOGGING = {
    [...]
    'loggers': {
        'my_app': {
            ...
        },
    },
}

Вы также можете задать интервалы между именами регистраторов в явном виде:

logger = logging.getLogger('project.payment')

и соответствующим образом настройте сопоставление регистраторов.

Использование иерархий регистраторов и распространения

Именование регистраторов является иерархическим. my_app является родителем my_app.views, который является родителем my_app.views.private. Если не указано иное, отображения регистраторов будут распространять обрабатываемые ими записи на их родителей - запись от регистратора в пространстве имен my_app.views.private будет обработана отображением для my_app и my_app.views.

Чтобы управлять этим поведением, установите ключ распространения для определенных вами сопоставлений:

LOGGING = {
    [...]
    'loggers': {
        'my_app': {
            [...]
        },
        'my_app.views': {
            [...]
        },
        'my_app.views.private': {
            [...]
            'propagate': False,
        },
    },
}

По умолчанию propagate имеет значение True. В этом примере журналы от my_app.views.private не будут обрабатываться родителем, а журналы от my_app.views будут.

Настройте ведение оперативного журнала

Ведение журнала наиболее полезно, когда он содержит как можно больше информации, но не той, которая вам не нужна - и то, сколько вам нужно, зависит от того, что вы делаете. При отладке вам нужен такой уровень информации, который был бы чрезмерным и бесполезным, если бы вам пришлось иметь дело с этим в производстве.

Вы можете настроить ведение журнала так, чтобы обеспечить необходимый вам уровень детализации, когда вам это нужно. Вместо того чтобы вручную изменять конфигурацию для достижения этой цели, лучшим способом является автоматическое применение конфигурации в зависимости от среды.

Например, вы можете установить переменную окружения DJANGO_LOG_LEVEL соответствующим образом в средах разработки и постановки, и использовать ее в отображении регистратора таким образом:

'level': os.getenv('DJANGO_LOG_LEVEL', 'WARNING')

- так что если окружение не укажет более низкий уровень журнала, эта конфигурация будет передавать своему обработчику только записи со степенью серьезности WARNING и выше.

Другие опции в конфигурации (такие как level или formatter опция обработчиков) могут управляться аналогичным образом.

Вернуться на верх