Ведение журнала ¶
Краткое введение в ведение журнала ¶
Django использует logging
встроенный модуль Python для ведения системного журнала. Использование этого модуля подробно обсуждается в собственной документации Python. Однако, если вы никогда раньше не использовали (или даже не использовали) систему протоколирования Python, вот краткое изложение.
Актеры в игре ¶
Настройка ведения журнала Python состоит из четырех частей:
Логгеры ¶
Регистратор - это точка входа в систему регистрации. Каждый регистратор - это именованный приемник, в который записываются сообщения для обработки.
Журналист настраивается с уровнем ведения журнала («уровень журнала»). Этот уровень определяет серьезность сообщений, обрабатываемых регистратором. Python определяет следующие уровни ведения журнала:
DEBUG
: системная информация низкого уровня для целей отладкиINFO
: общая информация о системеWARNING
: информация, описывающая наличие незначительной проблемы.ERROR
: информация, описывающая наличие серьезной проблемы.CRITICAL
: информация, описывающая наличие критической проблемы.
Каждое сообщение, записанное в регистратор, является «записью журнала». Каждая из этих записей также имеет уровень журнала, указывающий серьезность конкретного сообщения. Запись журнала также может содержать полезные метаданные, описывающие регистрируемое событие. Это может включать такие подробности, как трассировка отладки или код ошибки.
Когда сообщение передается регистратору, уровень регистрации сообщения сравнивается с уровнем регистратора. Если уровень регистрации сообщений совпадает или превышает уровень регистратора, сообщение продолжает обрабатываться. В противном случае сообщение игнорируется.
Как только журналист определил, что сообщение следует обработать, оно пересылается менеджеру («обработчику»).
Менеджеры ¶
Обработчик - это движущая сила того, что должно происходить с каждым сообщением от регистратора. Он описывает конкретное поведение ведения журнала, такое как запись сообщения на экран, в файл или в сетевой соединитель.
Как и регистраторы, менеджеры также имеют уровень ведения журнала. Если уровень ведения журнала записи журнала, по крайней мере, не эквивалентен уровню менеджера, менеджер игнорирует сообщение.
У регистратора может быть несколько обработчиков, и уровень ведения журнала для каждого обработчика может быть разным. Таким образом, можно предоставлять различные формы уведомлений в зависимости от важности сообщения. Например, вы можете установить обработчик, который перенаправляет сообщения уровня ERROR
и сообщений CRITICAL
в службу подкачки, в то время как другой менеджер будет отправлять все сообщения (включая уровни ERROR
и сообщения CRITICAL
) в файл для последующего анализа.
Фильтры ¶
Фильтр используется для добавления дополнительного контроля над выбором записей журнала, когда они передаются от регистратора к менеджеру.
По умолчанию обрабатывается любое сообщение журнала с достаточным уровнем ведения журнала. Однако, установив фильтр, вы можете установить дополнительные критерии в процессе регистрации. Например, вы можете установить фильтр, который ограничивает отправку сообщений уровня ERROR
определенному источнику.
Фильтры также могут иметь возможность изменять запись журнала перед ее выпуском. Например, вы можете написать фильтр, который понижает уровень ведения журнала сообщений с ERROR
до, WARNING
если соблюдены определенные критерии.
Фильтры могут быть установлены как для логгеров, так и для менеджеров; также возможно объединить несколько фильтров в цепочку для выполнения различных действий по фильтрации.
Тренеры ¶
Наконец, запись журнала должна быть создана в виде текста. Тренеры указывают точный формат этого текста. Как правило, тренер представляет собой строку формата Python, содержащую атрибуты LogRecord ; однако вы вполне можете написать свои собственные средства форматирования для реализации определенного поведения форматирования.
Ведение журнала на практике ¶
После того, как вы настроили регистраторы, обработчики, фильтры и инструкторы, остается разместить вызовы регистрации в вашем коде. Система ведения журнала работает следующим образом:
# import the logging library
import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)
def my_view(request, arg1, arg):
...
if bad_mojo:
# Log an error message
logger.error('Something went wrong!')
Это оно ! Каждый раз при вводе условия bad_mojo
в журнал будет вставляться строка с ошибкой.
Именование логгеров ¶
Вызов для logging.getLogger()
получения (и, при необходимости, создания) экземпляра регистратора. Этот экземпляр идентифицируется по имени. Это имя используется для идентификации регистратора конфигурации.
По соглашению, имя регистратора обычно __name__
является именем модуля Python, содержащего регистратор. Это позволяет фильтровать и обрабатывать вызовы журналирования в соответствии с модулями. Однако, если вы организовываете свои сообщения журнала другим способом, вы можете указать любое имя в записи с точками для идентификации регистратора:
# Get an instance of a specific named logger
logger = logging.getLogger('project.interesting.stuff')
Пунктирная запись имен регистраторов определяет иерархию. Регистратор project.interesting
считается родительским для регистратора project.interesting.stuff
. Регистратор project
является родительским для регистратора project.interesting
.
Почему важна эта иерархия? Ну, потому что регистраторы могут быть настроены для передачи получаемых ими вызовов журнала своим родителям. Таким образом, вы можете определить единый набор обработчиков в корне дерева регистратора и захватывать все вызовы регистрации в поддереве регистратора. Регистратор определен в пространстве имен project
перехватывает все сообщения журнала , выданные на project.interesting
и уровне регистраторов project.interesting.stuff
.
Это распространение можно контролировать для каждого регистратора индивидуально. Если вы хотите, чтобы конкретный журналист не передавал сообщения своим родителям, вы можете отключить это поведение.
Запись звонков ¶
Каждый экземпляр регистратора содержит метод вызова, соответствующий каждому уровню ведения журнала по умолчанию:
logger.debug()
logger.info()
logger.warning()
logger.error()
logger.critical()
Доступны два других вызова журнала:
logger.log()
: Вручную создать сообщение журнала на указанном уровне.logger.exception()
: Создает сообщение журнала уровня,ERROR
охватывающее текущий стек исключений.
Настройка логирования ¶
Недостаточно просто поместить в код вызовы логирования. Вам также необходимо настроить средства ведения журнала, обработчики, фильтры и средства форматирования, чтобы обеспечить возможность использования вывода журнала.
Библиотека журналов Python предоставляет несколько методов настройки либо через программируемый интерфейс, либо через файлы конфигурации. По умолчанию Django использует формат dictConfig .
Для настройки логирования необходимо определить словарь настроек логирования в LOGGING
. Эти настройки описывают регистраторы, менеджеры, фильтры и обучающие программы, которые вы хотите настроить, а также уровни ведения журнала и другие свойства, которые вы хотите назначить этим компонентам.
По умолчанию этот параметр LOGGING
объединен с конфигурацией ведения журнала Django по умолчанию на основе следующих принципов.
Если ключ disable_existing_loggers
словаря LOGGING
содержит True
(что используется по умолчанию, dictConfig
если ключ отсутствует), все средства ведения журнала в конфигурации по умолчанию будут отключены. Отключение регистратора не эквивалентно его удалению; регистратор все еще существует, но он молча отбрасывает все полученные сообщения, даже не передавая их родительскому регистратору. Поэтому вам следует с осторожностью относиться к настройке ; он часто делает не то, что нам хотелось бы. Тем не менее, вы можете установить , чтобы и переопределить некоторые или все регистраторы по умолчанию. Другая стратегия заключается в создании в и сделать конфигурацию протоколирования самостоятельно .'disable_existing_loggers': True
disable_existing_loggers
False
LOGGING_CONFIG
None
Ведение журнала настраивается как часть setup()
общей функции Django. Таким образом, вы можете быть уверены, что регистраторы всегда готовы к использованию кодом вашего проекта.
Примеры ¶
Полная документация по формату dictConfig - лучший источник информации о словарях конфигурации журналирования. Однако, чтобы дать вам немного почувствовать, чего можно достичь, вот несколько примеров.
Для начала, вот небольшая конфигурация, которая будет отображать все сообщения журнала в консоли:
import os
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'WARNING',
},
}
Это настраивает родительский регистратор root
для отправки сообщений уровня WARNING
или выше диспетчеру консоли. Установив уровень на INFO
или DEBUG
, вы можете просматривать больше сообщений. Это может быть полезно во время разработки.
Затем мы можем добавить более точное ведение журнала. Вот пример того, как заставить систему ведения журнала создавать больше сообщений для регистратора, специально названного django :
import os
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'WARNING',
},
'loggers': {
'django': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
'propagate': False,
},
},
}
По умолчанию эта конфигурация отправляет на консоль сообщения регистратора django
уровня INFO
или выше. Это тот же уровень, что и в конфигурации ведения журнала по умолчанию Django, за исключением того, что Django отображает сообщения журнала только в том случае, если DEBUG=True
. Django не генерирует так много сообщений уровня INFO
. Однако с этой конфигурацией вы также можете установить переменную среды DJANGO_LOG_LEVEL=DEBUG
для просмотра всех сообщений отладки, регистрируемых Django, что очень многословно, потому что все запросы к базе данных включены.
Вам не нужно отправлять журнал на консоль. Вот конфигурация, которая записывает все журналы, поступающие из регистратора с именем django, в локальный файл:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/path/to/django/debug.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
Если вы используете этот пример, не забудьте заменить путь 'filename'
местоположением, доступным для записи пользователю, запускающему приложение Django.
Наконец, вот пример довольно сложной настройки ведения журнала:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
},
'filters': {
'special': {
'()': 'project.logging.SpecialFilter',
'foo': 'bar',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['special']
}
},
'loggers': {
'django': {
'handlers': ['console'],
'propagate': True,
},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'myproject.custom': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
'filters': ['special']
}
}
}
Эта конфигурация ведения журнала выполняет следующие действия:
Он определяет конфигурацию как имеющуюся в формате «dictConfig версии 1». В настоящее время это единственная версия формата dictConfig.
Он определяет двух тренеров:
simple
который отображает имя уровня журнала (напримерDEBUG
) и сообщение журнала.Строка
format
- это обычная строка формата Python, описывающая подробности того, что должно отображаться для каждой строки журнала. Полный список деталей, которые можно просмотреть, можно найти в объектах Formatter .verbose
который отображает имя уровня журнала, сообщение журнала и время, процесс, поток и модуль, сгенерировавший сообщение.
Он определяет два фильтра:
project.logging.SpecialFilter
по псевдонимуspecial
. Если для этого фильтра требуются дополнительные параметры, их можно указать в качестве дополнительных ключей в словаре конфигурации фильтра. В этом случае параметрfoo
получает значениеbar
при создании экземпляраSpecialFilter
.django.utils.log.RequireDebugTrue
, который пересылает сообщения дальше, когдаDEBUG
стоитTrue
.
Он определяет двух менеджеров:
console
, обработчик дляStreamHandler
вывода сообщенияINFO
об ошибке любого уровня или выше (sys.stderr
). Этот менеджер использует формат отображенияsimple
.mail_admins
, менеджер,AdminEmailHandler
который уведомляетADMINS
сайт по электронной почте о любом уровне сообщенияERROR
или выше. Этот менеджер использует фильтр отображенияspecial
.
Он настраивает три регистратора:
django
, который пересылает все сообщения менеджеруconsole
.django.request
который пересылает все сообщения уровняERROR
менеджеруmail_admins
. Кроме того, этот регистратор не настроен для распространения сообщений. Это означает, что сообщенияdjango.request
не будут обрабатываться родительским журналистомdjango
.myproject.custom
который пересылает все сообщения уровняINFO
или выше и соответствующие фильтруspecial
двум менеджерам,console
иmail_admins
. Это означает, чтоINFO
в консоли будут отображаться все сообщения уровня или выше. Сообщения на уровеньERROR
иCRITICAL
также будут отправлены по электронной почте.
Пользовательская конфигурация ведения журнала ¶
Если вы не хотите использовать формат dictConfig
Python для настройки ведения журнала, вы можете указать альтернативную систему конфигурации.
Этот параметр LOGGING_CONFIG
определяет исполняемый файл, используемый для настройки регистраторов Django. По умолчанию это указывает на функцию logging.config.dictConfig()
Python. Однако, если вы хотите использовать другой метод конфигурации, вы можете указать любой другой исполняемый файл, который принимает один параметр. Содержимое LOGGING
будет предоставлено как значение этого параметра при настройке ведения журнала.
Отключение конфигурации ведения журнала ¶
Если вы не хотите настраивать ведение журнала (или хотите сделать это вручную по-своему), вы можете установить LOGGING_CONFIG
значение None
. Это отключит процесс установки журнала Django по умолчанию . Вот пример, который отключает конфигурацию ведения журнала Django, а затем вручную настраивает ведение журнала:
LOGGING_CONFIG = None
import logging.config
logging.config.dictConfig(...)
Установив LOGGING_CONFIG
на None
, вы только отключив автоматический процесс настройки, а не сам протоколирования. Даже если вы отключите процесс настройки, Django продолжает использовать ведение журнала, которое затем будет вести себя так, как установлено по умолчанию.
Расширения журналирования Django ¶
Django предоставляет ряд утилит для обработки особых требований к журналированию в контексте среды веб-сервера.
Логгеры ¶
Django предоставляет несколько встроенных логгеров:
django
¶
«Всеохватывающий» регистратор сообщений из иерархии django
. Никакое сообщение с этим именем не отправляется, но использует один из следующих регистраторов.
django.request
¶
Журнал сообщений, связанных с обработкой запросов. Ответы 5xx отображаются как сообщения ERROR
. Ответы 4xx представлены как сообщения WARNING
. Запросы, в django.security
которые выполняется вход, не регистрируются django.request
.
Сообщения, отправленные в этот регистратор, имеют следующий дополнительный контекст:
status_code
: код ответа HTTP, связанный с запросом.request
: объект запроса, создавший сообщение журнала.
django.server
¶
Журнал сообщений, связанных с обработкой запросов, полученных сервером, запрошенных командой runserver
. Ответы HTTP 5xx регистрируются как сообщения ERROR
. Ответы 4xx регистрируются как сообщения WARNING
, а все остальное - как сообщения INFO
.
Сообщения, отправленные в этот регистратор, имеют следующий дополнительный контекст:
status_code
: код ответа HTTP, связанный с запросом.request
: объект запроса, создавший сообщение журнала.
django.template
¶
Журнал сообщений, связанных с отображением шаблонов.
- Отсутствующие переменные контекста регистрируются как сообщения типа
DEBUG
.
django.db.backends
¶
Сообщения, относящиеся к взаимодействию между кодом и базой данных. Например, каждый оператор SQL уровня приложения, выполняемый запросом, отправляется в регистратор этого уровня DEBUG
.
Сообщения, отправленные в этот регистратор, имеют следующий дополнительный контекст:
duration
: время выполнения соответствующего оператора SQL.sql
: оператор SQL выполнен.params
: параметры, используемые в вызове SQL.
По соображениям производительности ведение журнала SQL включается, только если для settings.DEBUG
него установлено значение True
, независимо от уровня ведения журнала или установленных менеджеров.
Это ведение журнала не связано с инициализацией уровня инфраструктуры (например ) или запросами управления транзакциями (например , или ). Включите ведение журнала запросов на уровне базы данных, если вы хотите видеть все запросы к базе данных.SET TIMEZONE
BEGIN
COMMIT
ROLLBACK
django.security.*
¶
Регистраторы security
получают сообщения о каждом возникновении SuspiciousOperation
и других ошибках, связанных с безопасностью. Есть суб-сериализатор для каждого подтипа ошибки безопасности, включая все SuspiciousOperation
. Уровень регистрируемых событий зависит от того, где обрабатывается исключение. Большинство событий регистрируются как предупреждения, в то время как любое исключение, SuspiciousOperation
достигшее обработчика WSGI, регистрируется как ошибка. Например, когда HTTP-заголовок, Host
содержащийся в запросе клиента, не совпадает ALLOWED_HOSTS
, Django возвращает ответ 400, и в регистраторе регистрируется сообщение об ошибке django.security.DisallowedHost
.
Эти события журнала по умолчанию попадают в средство ведения журнала django
, которое отправляет администраторам сообщения об ошибках по электронной почте DEBUG=False
. Запросы, которые приводят к ответу 400 из-за ошибки SuspiciousOperation
, не регистрируются django.request
, а только в регистраторе django.security
.
Чтобы отключить определенный тип SuspiciousOperation
, вы можете переопределить соответствующий регистратор, следуя этому примеру:
'handlers': {
'null': {
'class': 'logging.NullHandler',
},
},
'loggers': {
'django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
},
Другие django.security
логгеры, не основанные на базе SuspiciousOperation
данных:
django.security.csrf
: для сбоев CSRF .
django.db.backends.schema
¶
Регистрирует SQL-запросы, выполняемые во время изменений схемы базы данных, выполненных системой миграции . Обратите внимание, что запросы, выполняемые пользователем RunPython
, не регистрируются. Сообщения от этого регистратора имеют params
и sql
в дополнительном контексте (но не по продолжительности django.db.backends
). Эти значения имеют то же значение, что объясняет django.db.backends .
Менеджеры ¶
Django предлагает менеджер журналов в дополнение к тем, которые предлагает модуль logging
Python.
-
class
AdminEmailHandler
( include_html = False , email_backend = None , reporter_class = None ) ¶ Этот менеджер отправляет электронное письмо администраторам сайта (
ADMINS
) для каждого сообщения журнала, которое он получает.Если сообщение журнала содержит атрибут
request
, полная информация о запросе будет включена в электронное письмо. Тема электронного письма будет содержать «внутренний IP-адрес», если IP-адрес клиента указан в настройкеINTERNAL_IPS
; в противном случае он будет содержать «ВНЕШНИЙ IP».Если строка журнала содержит информацию о трассировке отладки, она включается в электронное письмо.
Параметр
include_html
inAdminEmailHandler
используется для управления тем, должно ли электронное письмо, содержащее трассировку отладки, включать в себя HTML-вложение, содержащее веб-страницу, полную отладки, которая была бы отображена, если бы этот параметрDEBUG
имел значениеTrue
. Чтобы установить это значение в вашей конфигурации, включите этот параметр в определение обработчика дляdjango.utils.log.AdminEmailHandler
, например:'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, } },
Обратите внимание, что эта HTML-версия электронного письма содержит полную трассировку отладки с именами и значениями локальных переменных на каждом уровне трассировки в дополнение к значениям ваших настроек Django. Эта информация может содержать очень конфиденциальные элементы, и не всегда рекомендуется отправлять ее по электронной почте. Рассмотрите возможность использования такой службы, как Sentry, чтобы получить лучшее из обоих миров, богатую информацию с полными трассировками отладки, но с безопасностью, не отправляя эту информацию по электронной почте. Вы также можете явно указать определенную конфиденциальную информацию, которая будет исключена из отчетов об ошибках; см. Отчеты об ошибках фильтрации для более подробной информации.
Установив параметр
email_backend
вAdminEmailHandler
, то система обмена сообщениями , используемый менеджером может быть перегружен, как это:'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'email_backend': 'django.core.mail.backends.filebased.EmailBackend', } },
По умолчанию используется экземпляр механизма обмена сообщениями, указанный в
EMAIL_BACKEND
.Параметр
reporter_class
изAdminEmailHandler
позволяет обеспечить подкласс ,django.views.debug.ExceptionReporter
чтобы настроить текст трассировки ошибок , переданный в теле письма. Укажите путь импорта в виде строки для класса, который вы хотите использовать, например'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, 'reporter_class': 'somepackage.error_reporter.CustomErrorReporter' } },
Новое в Django 3.0:Параметр
reporter_class
добавлен.-
send_mail
( тема , сообщение , * аргументы , ** kwargs ) ¶ Отправляет электронные письма администраторам. Чтобы настроить это поведение, вы можете создать подкласс
AdminEmailHandler
и переопределить этот метод.
-
Фильтры ¶
Django предлагает несколько фильтров журналирования в дополнение к тем, которые предлагает модуль logging
Python.
-
класс
CallbackFilter
( обратный вызов ) ¶ Этот фильтр принимает функцию обратного вызова (которая должна принимать только один параметр - запись, которая должна регистрироваться) и вызывает ее для каждой записи, проходящей через этот фильтр. Обработка записи останавливается, если функция обратного вызова возвращается
False
.Например, чтобы исключить
UnreadablePostError
(генерируется, когда пользователь отменяет загрузку) из писем, отправленных администраторам, можно создать эту функцию фильтра:from django.http import UnreadablePostError def skip_unreadable_post(record): if record.exc_info: exc_type, exc_value = record.exc_info[:2] if isinstance(exc_value, UnreadablePostError): return False return True
затем добавил в конфигурацию ведения журнала:
'filters': { 'skip_unreadable_posts': { '()': 'django.utils.log.CallbackFilter', 'callback': skip_unreadable_post, } }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'filters': ['skip_unreadable_posts'], 'class': 'django.utils.log.AdminEmailHandler' } },
-
класс
RequireDebugFalse
¶ Этот фильтр разрешает пропускать записи только тогда, когда они того
settings.DEBUG
стоятFalse
.Этот фильтр используется, как показано в приведенном ниже примере, в конфигурации по умолчанию,
LOGGING
чтобы гарантироватьAdminEmailHandler
отправку сообщений об ошибках администраторам толькоDEBUG
в следующих случаяхFalse
:'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse', } }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler' } },
-
класс
RequireDebugTrue
¶ Этот фильтр аналогичен фильтру
RequireDebugFalse
, за исключением того, что записи передаются повторно только тогда, когда ониDEBUG
стоятTrue
.
Конфигурация журналирования по умолчанию в Django ¶
По умолчанию Django настраивает следующие журналы:
Когда DEBUG
это True
:
- Регистратор
django
отправляет сообщения с уровня иерархииdjango
(кромеdjango.server
)INFO
или выше на консоль.
Когда DEBUG
это False
:
- Регистратор
django
отправляет сообщения на уровень иерархииdjango
(кромеdjango.server
)ERROR
илиCRITICAL
наAdminEmailHandler
.
Независимо от стоимости DEBUG
:
- Django.server регистратор отправляет уровень сообщений
INFO
и выше на консоль.
Все регистраторы, кроме django.server, передают ведение журнала своим родителям, вплоть до корневого регистратораdjango
. Обработчики console
и mail_admins
связаны с корневым регистратором для обеспечения описанного выше поведения.
Смотрите также Logging Конфигурация для того, как дополнить или заменить эту конфигурацию регистрации по умолчанию, определенный в Джанго / Utils / log.py .