Подтвердить что ты не робот

Ручной запуск отчета об ошибке электронной почты Django

Отчеты об ошибках Django обрабатывает неперехваченные исключения, отправляя электронное письмо, и (необязательно) показывает пользователю страницу с ошибкой 500.

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

Итак, в основном: могу ли я вручную отправить отчет об ошибке электронной почты, даже если я поймаю исключение?

Конечно, я бы не хотел вручную генерировать сообщение об ошибке.

4b9b3361

Ответ 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()
    )