Spec-Zone.ru › Django 4.1

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

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

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

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

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

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

Примечание

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

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

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

См. также

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

Ошибки 404

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

  • DEBUG установлена на False;
  • Настройка MIDDLEWARE включает django.middleware.common.BrokenLinkEmailsMiddleware.

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

Примечание

BrokenLinkEmailsMiddleware должен стоять перед другими middleware, которые перехватывают ошибки 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, начинающийся с /phpmyadmin/.

Следующий пример показывает, как исключить некоторые стандартные 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 регистрируются с помощью фреймворка журналов. По умолчанию записи этих журналов игнорируются, но вы можете использовать их для отчётов об ошибках, написав обработчик и соответственно настроив логирование.

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

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

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

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

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

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

В приведённом выше примере значения параметров pass_word и credit_card_number POST будут скрыты и заменены звёздочками (**********) в представлении запроса внутри отчётов об ошибках, а значение параметра 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'

Вы также можете более точно управлять фильтром, который использовать в конкретном представлении, установив атрибут HttpRequest объекта exception_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-версии страницы ошибки HTTP 500.

get_traceback_text()

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

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

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

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

См. также

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

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.1/howto/error-reporting/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API