Ведение журнала

Модуль логирования Django расширяет встроенный модуль Python logging.

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

Конфигурация протоколирования по умолчанию в Django

По умолчанию Django использует logging.config.dictConfig format в Python.

Условия ведения журнала по умолчанию

Полный набор условий ведения журнала по умолчанию следующий:

Когда 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 прикрепляются к корневому логгеру для обеспечения описанного выше поведения.

Собственные настройки Python по умолчанию отправляют записи уровня WARNING и выше на консоль.

Определение протоколирования по умолчанию

Конфигурация логирования по умолчанию в Django наследует настройки по умолчанию в Python. Она доступна в виде django.utils.log.DEFAULT_LOGGING и определена в django/utils/log.py:

{
    "version": 1,
    "disable_existing_loggers": False,
    "filters": {
        "require_debug_false": {
            "()": "django.utils.log.RequireDebugFalse",
        },
        "require_debug_true": {
            "()": "django.utils.log.RequireDebugTrue",
        },
    },
    "formatters": {
        "django.server": {
            "()": "django.utils.log.ServerFormatter",
            "format": "[{server_time}] {message}",
            "style": "{",
        }
    },
    "handlers": {
        "console": {
            "level": "INFO",
            "filters": ["require_debug_true"],
            "class": "logging.StreamHandler",
        },
        "django.server": {
            "level": "INFO",
            "class": "logging.StreamHandler",
            "formatter": "django.server",
        },
        "mail_admins": {
            "level": "ERROR",
            "filters": ["require_debug_false"],
            "class": "django.utils.log.AdminEmailHandler",
        },
    },
    "loggers": {
        "django": {
            "handlers": ["console", "mail_admins"],
            "level": "INFO",
        },
        "django.server": {
            "handlers": ["django.server"],
            "level": "INFO",
            "propagate": False,
        },
    },
}

Смотрите Настройка протоколирования о том, как дополнить или заменить эту конфигурацию протоколирования по умолчанию.

Расширения для ведения логов в Django

Django предоставляет ряд утилит для обработки особых требований к ведению журнала в среде веб-сервера.

Логеры

Django предоставляет несколько встроенных регистраторов.

django

Родительский логгер для сообщений в django named logger hierarchy. 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: объект запроса (a socket.socket), сгенерировавший сообщение для протоколирования.

django.template

Сообщения журнала, связанные с отрисовкой шаблонов.

  • Отсутствующие контекстные переменные регистрируются в виде сообщений DEBUG.

django.db.backends

Сообщения, относящиеся к взаимодействию кода с базой данных. Например, каждый SQL-оператор прикладного уровня, выполняемый запросом, регистрируется на уровне DEBUG в этом регистраторе.

Сообщения этого регистратора имеют следующий дополнительный контекст:

  • duration: Время, затраченное на выполнение оператора SQL.
  • sql: Оператор SQL, который был выполнен.
  • params: Параметры, которые были использованы в вызове SQL.
  • alias: Псевдоним базы данных, используемый в вызове SQL.

По соображениям производительности, протоколирование SQL включается только при установке settings.DEBUG в значение True, независимо от уровня протоколирования или установленных обработчиков.

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

Changed in Django 4.2:

Добавлена поддержка протоколирования запросов управления транзакциями (BEGIN, COMMIT и ROLLBACK).

django.security.*

Регистраторы безопасности будут получать сообщения о любом появлении SuspiciousOperation и других ошибок, связанных с безопасностью. Для каждого подтипа ошибки безопасности, включая все SuspiciousOperations, существует свой поджурнал. Уровень события журнала зависит от того, как обрабатывается исключение. Большинство случаев регистрируется как предупреждение, в то время как любая SuspiciousOperation>, которая достигает обработчика WSGI, регистрируется как ошибка. Например, если в запрос от клиента включен заголовок HTTP Host, который не соответствует ALLOWED_HOSTS, Django вернет ответ 400, а сообщение об ошибке будет записано в журнал django.security.DisallowedHost.

По умолчанию эти события журнала будут поступать в регистратор django, который отправляет администраторам сообщения об ошибках при DEBUG=False. Запросы, приводящие к ответу 400 из-за ошибки SuspiciousOperation, не будут регистрироваться в журнале django.request, а только в журнале django.security.

Чтобы заглушить определенный тип SuspiciousOperation, вы можете переопределить этот конкретный регистратор, следуя следующему примеру:

LOGGING = {
    # ...
    "handlers": {
        "null": {
            "class": "logging.NullHandler",
        },
    },
    "loggers": {
        "django.security.DisallowedHost": {
            "handlers": ["null"],
            "propagate": False,
        },
    },
    # ...
}

Другими регистраторами django.security, не основанными на SuspiciousOperation, являются:

django.db.backends.schema

Регистрирует SQL-запросы, которые выполняются во время изменения схемы базы данных командой migrations framework. Обратите внимание, что он не будет регистрировать запросы, выполняемые RunPython. Сообщения этого логгера имеют params и sql в дополнительном контексте (но, в отличие от django.db.backends, не продолжительность). Значения имеют тот же смысл, который объясняется в django.db.backends.

Обработчики

Django предоставляет один обработчик журналов в дополнение к those provided by the Python logging module.

class AdminEmailHandler(include_html=False, email_backend=None, reporter_class=None)[исходный код]

Этот обработчик отправляет письмо на сайт ADMINS для каждого полученного им сообщения журнала.

Если запись журнала содержит атрибут request, в письмо будет включена полная информация о запросе. Тема письма будет включать фразу «internal IP», если IP-адрес клиента находится в настройках INTERNAL_IPS; если нет, она будет включать «EXTERNAL IP».

Если запись журнала содержит информацию о трассировке стека, эта трассировка стека будет включена в письмо.

Аргумент include_html в AdminEmailHandler используется для управления тем, включает ли письмо с обратным отслеживанием HTML-вложение, содержащее полное содержимое отладочной веб-страницы, которая была бы создана, если бы DEBUG было True. Чтобы установить это значение в вашей конфигурации, включите его в определение обработчика для django.utils.log.AdminEmailHandler, например, так:

"handlers": {
    "mail_admins": {
        "level": "ERROR",
        "class": "django.utils.log.AdminEmailHandler",
        "include_html": True,
    },
}

Будьте внимательны к security implications of logging при использовании AdminEmailHandler.

Установив аргумент email_backend в AdminEmailHandler, можно переопределить email backend, используемый обработчиком, следующим образом:

"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",
    },
}
send_mail(subject, message, *args, **kwargs)[исходный код]

Отправляет электронные письма пользователям-администраторам. Чтобы настроить это поведение, вы можете использовать подкласс класса AdminEmailHandler и переопределить этот метод.

Фильтры

Django предоставляет некоторые фильтры журналов в дополнение к тем, которые предоставляет модуль протоколирования Python.

class CallbackFilter(callback)[исходный код]

Этот фильтр принимает функцию обратного вызова (которая должна принимать единственный аргумент - запись, которая должна быть зарегистрирована) и вызывает ее для каждой записи, которая проходит через фильтр. Обработка этой записи не будет продолжена, если обратный вызов вернет 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

а затем добавьте его в конфигурацию протоколирования:

LOGGING = {
    # ...
    "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",
        },
    },
    # ...
}
class RequireDebugFalse[исходный код]

Этот фильтр будет пропускать записи только в том случае, если settings.DEBUG имеет значение False.

Этот фильтр используется следующим образом в конфигурации LOGGING по умолчанию, чтобы гарантировать, что AdminEmailHandler отправляет администраторам электронные письма с ошибками только тогда, когда DEBUG является False:

LOGGING = {
    # ...
    "filters": {
        "require_debug_false": {
            "()": "django.utils.log.RequireDebugFalse",
        },
    },
    "handlers": {
        "mail_admins": {
            "level": "ERROR",
            "filters": ["require_debug_false"],
            "class": "django.utils.log.AdminEmailHandler",
        },
    },
    # ...
}
class RequireDebugTrue[исходный код]

Этот фильтр аналогичен RequireDebugFalse, за исключением того, что записи передаются только тогда, когда DEBUG и True.

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