Ручной запуск отчета об ошибке электронной почты Django
Отчеты об ошибках Django обрабатывает неперехваченные исключения, отправляя электронное письмо, и (необязательно) показывает пользователю страницу с ошибкой 500.
Это работает очень хорошо, но в некоторых случаях я бы хотел, чтобы пользователи продолжали свой бизнес без перерывов, но все же Django отправил мне сообщение об ошибке электронной почты об исключении.
Итак, в основном: могу ли я вручную отправить отчет об ошибке электронной почты, даже если я поймаю исключение?
Конечно, я бы не хотел вручную генерировать сообщение об ошибке.
Ответы
Ответ 1
Вы можете использовать следующий код для отправки вручную электронной почты о request
и исключении e
:
import sys
import traceback
from django.core import mail
from django.views.debug import ExceptionReporter
def send_manually_exception_email(request, e):
exc_info = sys.exc_info()
reporter = ExceptionReporter(request, is_email=True, *exc_info)
subject = e.message.replace('\n', '\\n').replace('\r', '\\r')[:989]
message = "%s\n\n%s" % (
'\n'.join(traceback.format_exception(*exc_info)),
reporter.filter.get_request_repr(request)
)
mail.mail_admins(
subject, message, fail_silently=True,
html_message=reporter.get_traceback_html()
)
Вы можете протестировать его в таком виде:
def test_view(request):
try:
raise Exception
except Exception as e:
send_manually_exception_email(request, e)
Ответ 2
Просто настройте простой проводник в своих настройках.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
'app': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
}
}
а затем, на ваш взгляд, вы можете сделать что-нибудь
import logging
logger = logging.getLogger('app')
def some_view(request):
try:
# something
if something_wnet_wrong:
logger.error('Something went wrong!')
return some_http_response
except:
#something else
logger.error(sys.exc_info(), request)
return some_other_response
Если вам нужен подробный отчет об ошибке, вы можете попробовать что-то вроде этого.
Вам также необходимо позаботиться о конфиденциальной информации.
Ответ 3
Да, вы можете вручную отправить отчет об ошибке электронной почты, даже если вы поймаете исключение.
Есть несколько способов сделать это.
- Вы можете использовать существующую конфигурацию регистратора по умолчанию (и связанную с ней конфигурацию обработчика, зарегистрированную здесь) для django.request, которая отправляет все сообщения об ошибках обработчик mail_admins, который отправляет что-либо, зарегистрированное с помощью log.error из django.request, когда debug является ложным как электронная почта, используя AdminEmailHandler, чья существующая точка вызова в handle_uncaught_exception.
- Вы можете добавить дополнительную конфигурацию регистратора, которая использует тот же обработчик, чтобы уловить ваше исключение раньше, чем django.request и вызвать log.error раньше.
- Вы можете подклассифицировать django.request, в частности handle_uncaught_exception.
- Вы можете использовать специальное промежуточное программное обеспечение (например, StandardExceptionMiddleware) или ExceptionMiddleware
- Вы можете вручную вызвать содержимое emit в
AdminEmailHandler
или mail.mail_admins напрямую.
Из этих опций вариант 4, по-видимому, наиболее часто выполняется.
На основе дополнительной информации в вашем комментарии приведен пример кода из 2.
Сначала код, который будет добавлен для просмотра
from django.http import HttpResponse
import logging
logger = logging.getLogger(__name__)
def my_view(request):
try:
result = do_something()
return HttpResponse('<h1>Page was found' + result + '</h1>')
except Exception:
# Can have whatever status_code and title you like, but I was just matching the existing call.
logger.error('Internal Server Error: %s', request.path,
exc_info=sys.exc_info(),
extra={
'status_code': 500,
'request': request
}
)
return HttpResponse('<h1>Page was found, and exception was mailed to admins.</h1>')
Это основано документация Django для записи в виде заметок и и введение в Django, но не был протестирован.
Затем дополнительная конфигурация регистратора добавляется к записи в журнал (согласно здесь)
'nameofdjangoapplicationgoeshere': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
Ответ 4
В основном я использую этот шаблон со стандартными сообщениями об ошибках.
import logging
logger = logging.getLogger('django.request')
#code block in view
try:
#code that can raise exception
except:
logger.exception('Information')
#continue as nothing happend
Он будет запускать встроенные отчеты об ошибках и
logger.exception поймает фрейм стека. https://docs.djangoproject.com/en/1.8/topics/logging/#making-logging-calls
изменить:
Я заметил, что в электронном письме отсутствовала какая-либо информация, и чтобы получить точную трассировку, поскольку вместо этого можно использовать встроенную в нее:
logger.exception('Internal Server Error: %s', request.path,
extra={'status_code': 500, 'request': request})
Дополнительная информация найдена здесь:
Как отправить журнал ошибок django вручную?
Ответ 5
Основываясь на ответе @JuniorCompressor, это код, который я использую:
import sys
from django.core import mail
from django.views.debug import ExceptionReporter
def send_exception_email(request, exception, subject_prefix=''):
exc_info = sys.exc_info()
reporter = ExceptionReporter(request, *exc_info, is_email=True)
def exception_name():
if exc_info[0]:
return exc_info[0].__name__
return 'Exception'
def subject_suffix():
if request:
return '{} at {}'.format(
exception_name(),
request.path_info
)
return exception_name()
def subject():
return '{}{}'.format(
subject_prefix,
subject_suffix()
)
mail.mail_admins(
subject=subject(),
message=reporter.get_traceback_text(),
fail_silently=True,
html_message=reporter.get_traceback_html()
)