Как управлять отчетами об ошибках

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

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

Отчеты по электронной почте

Ошибки сервера

Когда DEBUG равно False, Django будет отправлять письма пользователям, указанным в настройке ADMINS, всякий раз, когда ваш код вызывает необработанное исключение и приводит к внутренней ошибке сервера (строго говоря, для любого ответа с кодом состояния HTTP 500 или выше). Это дает администраторам немедленное уведомление о любых ошибках. Настройка ADMINS получит описание ошибки, полный трассировочный ответ Python и подробную информацию о HTTP-запросе, вызвавшем ошибку.

Примечание

Для того чтобы отправлять электронную почту, Django требует несколько параметров, указывающих, как подключиться к вашему почтовому серверу. Как минимум, вам нужно будет указать EMAIL_HOST и, возможно, EMAIL_HOST_USER и EMAIL_HOST_PASSWORD, хотя могут потребоваться и другие настройки в зависимости от конфигурации вашего почтового сервера. Полный список настроек, связанных с электронной почтой, приведен в the Django settings documentation.

По умолчанию Django будет отправлять электронную почту с адреса root@localhost. Однако некоторые почтовые провайдеры отклоняют все письма с этого адреса. Чтобы использовать другой адрес отправителя, измените параметр SERVER_EMAIL.

Чтобы активировать это поведение, поместите адреса электронной почты получателей в настройку ADMINS.

См.также

Письма об ошибках сервера отправляются с помощью фреймворка протоколирования, поэтому вы можете настроить это поведение с помощью customizing your logging configuration.

404 ошибки

Django также может быть настроен на отправку писем об ошибках неработающих ссылок (404 ошибки «страница не найдена»). Django отправляет электронные письма об ошибках 404, когда:

Если эти условия выполнены, Django будет отправлять письма пользователям, указанным в настройке MANAGERS, всякий раз, когда ваш код будет вызывать 404 и запрос будет иметь referer. Django не будет отправлять email для 404, у которых нет реферера - обычно это люди, набирающие неработающие URL или неработающие веб-боты. Он также игнорирует 404, когда referer равен запрашиваемому URL, поскольку такое поведение также характерно для неработающих веб-ботов.

Примечание

BrokenLinkEmailsMiddleware должен появляться перед другими промежуточными программами, перехватывающими 404 ошибку, такими как LocaleMiddleware или FlatpageFallbackMiddleware. Поместите его в начало вашей настройки MIDDLEWARE.

Вы можете указать Django прекратить сообщать о конкретных 404-х, изменив параметр IGNORABLE_404_URLS. Это должен быть список скомпилированных объектов регулярных выражений. Например:

import re
IGNORABLE_404_URLS = [
    re.compile(r'\.(php|cgi)$'),
    re.compile(r'^/phpmyadmin/'),
]

В этом примере 404 на любой URL, заканчивающийся на .php или .cgi, не будет сообщен. Также не будет сообщено о любом URL, начинающемся с .cgi.

В следующем примере показано, как исключить некоторые обычные URL, которые часто запрашивают браузеры и краулеры:

import re
IGNORABLE_404_URLS = [
    re.compile(r'^/apple-touch-icon.*\.png$'),
    re.compile(r'^/favicon\.ico$'),
    re.compile(r'^/robots\.txt$'),
]

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

Если вы хотите дополнительно настроить поведение django.middleware.common.BrokenLinkEmailsMiddleware (например, игнорировать запросы, поступающие от веб-краулеров), вам следует создать его подкласс и переопределить его методы.

См.также

Ошибки 404 записываются в журнал с помощью фреймворка протоколирования. По умолчанию эти записи журнала игнорируются, но вы можете использовать их для сообщения об ошибках, написав обработчик и configuring logging соответствующим образом.

Фильтрация отчетов об ошибках

Предупреждение

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

Фильтрация конфиденциальной информации

Отчеты об ошибках очень полезны для отладки ошибок, поэтому обычно полезно записывать как можно больше релевантной информации об этих ошибках. Например, по умолчанию Django записывает full traceback для вызванного исключения, локальные переменные каждого traceback frame и HttpRequest attributes.

Однако иногда некоторые типы информации могут быть слишком чувствительными и, следовательно, не могут быть уместны для отслеживания, например, пароль пользователя или номер кредитной карты. Поэтому в дополнение к фильтрации параметров, которые кажутся чувствительными, как описано в документации DEBUG, Django предлагает набор декораторов функций, чтобы помочь вам контролировать, какая информация должна быть отфильтрована из отчетов об ошибках в производственной среде (то есть, когда DEBUG установлен на False): sensitive_variables() и sensitive_post_parameters().

sensitive_variables(*variables)[исходный код]

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

from django.views.decorators.debug import sensitive_variables

@sensitive_variables('user', 'pw', 'cc')
def process_info(user):
    pw = user.pass_word
    cc = user.credit_card_number
    name = user.name
    ...

В приведенном выше примере значения переменных user, pw и cc будут скрыты и заменены звездочками (**********) в отчетах об ошибках, тогда как значение переменной name будет раскрыто.

Чтобы систематически скрывать все локальные переменные функции от журналов ошибок, не предоставляйте никаких аргументов декоратору sensitive_variables:

@sensitive_variables()
def my_function():
    ...

При использовании нескольких декораторов

Если переменная, которую вы хотите скрыть, также является аргументом функции (например, „user“ в следующем примере), и если декорируемая функция имеет несколько декораторов, то убедитесь, что @sensitive_variables находится в верхней части цепочки декораторов. Таким образом, аргумент функции будет скрыт при прохождении через другие декораторы:

@sensitive_variables('user', 'pw', 'cc')
@some_decorator
@another_decorator
def process_info(user):
    ...
sensitive_post_parameters(*parameters)[исходный код]

Если одно из ваших представлений получает объект HttpRequest с параметрами POST parameters, которые могут содержать конфиденциальную информацию, вы можете предотвратить включение значений этих параметров в отчеты об ошибках с помощью декоратора sensitive_post_parameters:

from django.views.decorators.debug import sensitive_post_parameters

@sensitive_post_parameters('pass_word', 'credit_card_number')
def record_user_profile(request):
    UserProfile.create(
        user=request.user,
        password=request.POST['pass_word'],
        credit_card=request.POST['credit_card_number'],
        name=request.POST['name'],
    )
    ...

В приведенном выше примере значения POST-параметров pass_word и credit_card_number будут скрыты и заменены звездочками (**********) в представлении запроса в отчетах об ошибках, тогда как значение параметра name будет раскрыто.

Чтобы систематически скрывать все POST-параметры запроса в отчетах об ошибках, не предоставляйте никаких аргументов декоратору sensitive_post_parameters:

@sensitive_post_parameters()
def my_view(request):
    ...

Все параметры POST систематически отфильтровываются из отчетов об ошибках для определенных представлений django.contrib.auth.views (login, password_reset_confirm, password_change, и add_view и user_change_password в админке auth), чтобы предотвратить утечку конфиденциальной информации, такой как пароли пользователей.

Пользовательские отчеты об ошибках

Все, что делают sensitive_variables() и sensitive_post_parameters(), это, соответственно, аннотируют декорированную функцию именами чувствительных переменных и аннотируют объект HttpRequest именами чувствительных POST-параметров, так что эта чувствительная информация может быть впоследствии отфильтрована из отчетов при возникновении ошибки. Фактическая фильтрация выполняется стандартным фильтром отчетов об ошибках Django: django.views.debug.SafeExceptionReporterFilter. Этот фильтр использует аннотации декораторов для замены соответствующих значений на звездочки (**********), когда создаются отчеты об ошибках. Если вы хотите отменить или настроить это поведение по умолчанию для всего вашего сайта, вам нужно определить свой собственный класс фильтра и указать Django использовать его с помощью настройки DEFAULT_EXCEPTION_REPORTER_FILTER:

DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter'

Вы также можете более детально контролировать, какой фильтр использовать в данном представлении, задавая атрибут HttpRequestexception_reporter_filter:

def my_view(request):
    if request.user.is_authenticated:
        request.exception_reporter_filter = CustomExceptionReporterFilter()
    ...

Ваш пользовательский класс фильтра должен наследоваться от django.views.debug.SafeExceptionReporterFilter и может переопределять следующие атрибуты и методы:

class SafeExceptionReporterFilter[исходный код]
cleansed_substitute

Строковое значение, на которое следует заменить чувствительное значение. По умолчанию он заменяет значения чувствительных переменных на звездочки (**********).

hidden_settings

Скомпилированный объект регулярного выражения, используемый для сопоставления настроек и значений request.META, считающихся чувствительными. По умолчанию эквивалентен:

import re

re.compile(r'API|TOKEN|KEY|SECRET|PASS|SIGNATURE', flags=re.IGNORECASE)
is_active(request)[исходный код]

Возвращает True для активации фильтрации в get_post_parameters() и get_traceback_frame_variables(). По умолчанию фильтр активен, если DEBUG равен False. Обратите внимание, что чувствительные значения request.META всегда фильтруются вместе с чувствительными значениями настроек, как описано в документации DEBUG.

get_post_parameters(request)[исходный код]

Возвращает отфильтрованный словарь POST-параметров. Чувствительные значения заменяются на cleansed_substitute.

get_traceback_frame_variables(request, tb_frame)[исходный код]

Возвращает отфильтрованный словарь локальных переменных для заданного фрейма трассировки. Чувствительные значения заменяются на cleansed_substitute.

Если вам нужно настроить отчеты об ошибках помимо фильтрации, вы можете указать пользовательский класс отчета об ошибках, определив параметр DEFAULT_EXCEPTION_REPORTER:

DEFAULT_EXCEPTION_REPORTER = 'path.to.your.CustomExceptionReporter'

Ответственность за составление данных отчета об исключениях и их форматирование в виде текста или HTML несет составитель отчета об исключениях. (При подготовке данных отчета об исключениях репортер исключений использует DEFAULT_EXCEPTION_REPORTER_FILTER).

Ваш пользовательский класс репортера должен наследоваться от django.views.debug.ExceptionReporter.

class ExceptionReporter[исходный код]
html_template_path

Свойство, возвращающее pathlib.Path, представляющее абсолютный путь к файловой системе шаблона для отображения HTML-представления исключения. По умолчанию используется шаблон, предоставленный Django.

text_template_path

Свойство, которое возвращает pathlib.Path, представляющее абсолютный путь к файловой системе шаблона для отображения текстового представления исключения. По умолчанию используется шаблон, предоставленный Django.

get_traceback_data()[исходный код]

Возвращает словарь, содержащий информацию об обратном проходе.

Это основная точка расширения для настройки отчетов об исключениях, например:

from django.views.debug import ExceptionReporter


class CustomExceptionReporter(ExceptionReporter):
    def get_traceback_data(self):
        data = super().get_traceback_data()
        # ... remove/add something here ...
        return data
get_traceback_html()[исходный код]

Возвращает HTML-версию отчета об исключениях.

Используется для HTML-версии отладочной страницы ошибки 500 HTTP.

get_traceback_text()[исходный код]

Возвращает текстовую версию отчета об исключениях.

Используется для текстовой версии отладочной страницы ошибки 500 HTTP и отчетов по электронной почте.

Как и в случае с классом фильтра, вы можете контролировать, какой класс регистратора исключений будет использоваться в любом данном представлении, устанавливая атрибут HttpRequest exception_reporter_class:

def my_view(request):
    if request.user.is_authenticated:
        request.exception_reporter_class = CustomExceptionReporter()
    ...

См.также

Вы также можете настроить пользовательское информирование об ошибках, написав пользовательскую часть exception middleware. Если вы пишете пользовательскую обработку ошибок, хорошей идеей будет подражать встроенной обработке ошибок Django и сообщать/заносить ошибки в журнал только если DEBUG является False.

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