Как управлять отчётами об ошибках
При работе с общедоступным сайтом всегда следует выключать настройку 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, и у запроса есть referer. Он не беспокоится об отправке писем для 404, у которых нет referer – это обычно люди, вводящие неверные URL-адреса или нерабочие веб-боты. Он также игнорирует 404, когда referer равен запрошенному 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’s атрибутов.
Однако иногда определённые типы информации могут быть слишком конфиденциальными и не должны храниться, например, пароль пользователя или номер кредитной карты. Поэтому, помимо фильтрации настроек, которые кажутся конфиденциальными, как описано в документации 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_numberPOST будут скрыты и заменены звёздочками (**********) в представлении запроса внутри сообщений об ошибках, в то время как значение параметра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 -
Строковое значение, которым будут заменены конфиденциальные значения. По умолчанию значения конфиденциальных переменных заменяются звёздочками (
**********).
-
Компилированный объект регулярного выражения, используемый для сопоставления настроек и
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 -
Новое в Django 3.2.
Свойство, возвращающее
pathlib.Path, представляющий абсолютный путь к файловой системе к шаблону для рендеринга HTML-представления исключения. По умолчанию используется шаблон, предоставленный Django.
-
text_template_path -
Новое в Django 3.2.
Свойство, возвращающее
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()
...
См. также
Вы также можете настроить обработку ошибок, написав свой собственный обработчик исключений средства обработки исключений. Если вы пишете собственную обработку ошибок, рекомендуется эмулировать встроенную обработку ошибок Django и сообщать/логировать ошибки только если DEBUG имеет значение False.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.0/howto/error-reporting/