How to manage error reporting

При работе с публичным сайтом всегда следует отключать настройку 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, когда:

If those conditions are met, Django will email the users listed in the MANAGERS setting whenever your code raises a 404 and the request has a referer. It doesn’t bother to email for 404s that don’t have a referer – those are usually people typing in broken URLs or broken web bots. It also ignores 404s when the referer is equal to the requested URL, since this behavior is from broken web bots too.

Примечание

BrokenLinkEmailsMiddleware must appear before other middleware that intercepts 404 errors, such as LocaleMiddleware or FlatpageFallbackMiddleware. Put it toward the top of your MIDDLEWARE setting.

Вы можете указать 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 соответствующим образом.

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

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

Filtering sensitive data is a hard problem, and it’s nearly impossible to guarantee that sensitive data won’t leak into an error report. Therefore, error reports should only be available to trusted team members and you should avoid transmitting error reports unencrypted over the internet (such as through email).

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

Отчеты об ошибках очень полезны для отладки ошибок, поэтому обычно полезно записывать как можно больше релевантной информации об этих ошибках. Например, по умолчанию 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|HTTP_COOKIE', flags=re.IGNORECASE)
Changed in Django 4.2:

HTTP_COOKIE был добавлен.

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 и отчетов по электронной почте.

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

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

См.также

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

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