手动触发Django电子邮件错误报告

时间:2015-04-01 13:37:29

标签: python django exception-handling django-email django-errors

Django error reporting通过发送电子邮件处理未捕获的异常,并(可选)向用户显示一个不错的500错误页面。

这非常有效,但在一些情况下,我希望允许用户不间断地继续他们的业务,但仍然让Django向我发送有关异常的电子邮件错误报告。

基本上如此:即使我发现异常,我还可以手动发送电子邮件错误报告吗?

当然,我想避免手动生成错误报告电子邮件。

5 个答案:

答案 0 :(得分:35)

您可以使用以下代码手动发送有关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)

答案 1 :(得分:6)

只需在您的设置中设置一个简单的日志处理程序。

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

如果您需要详细的错误报告,可以尝试something like this

您还需要照顾sensitive information

答案 2 :(得分:4)

是的,即使您发现异常,也可以手动发送电子邮件错误报告。

有几种方法可以解决这个问题。

  1. 您可以使用django.request的现有默认记录器配置(及其关联的处理程序配置,记录为here),它将所有错误消息发送到mail_admins处理程序,该处理程序从django发送使用log.error记录的任何内容.request使用AdminEmailHandler作为电子邮件时为false,其现有的受理点位于handle_uncaught_exception
  2. 您可以添加使用相同处理程序的其他记录器配置,以便在早于django.request之前捕获异常,并在之前调用log.error。
  3. 您可以继承django.request,特别是handle_uncaught_exception。
  4. 您可以使用自定义中间件(for example StandardExceptionMiddleware)或ExceptionMiddleware
  5. 您可以直接手动调用AdminEmailHandler或mail.mail_admins中的emit内容。
  6. 在这些选项中,选项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 documentation for view writingand introduction to Django logging,但尚未经过测试。

    然后将额外的记录器配置添加到记录器条目中(根据here

    'nameofdjangoapplicationgoeshere': {
                'handlers': ['mail_admins'],
                'level': 'ERROR',
                'propagate': False,
            },
    

答案 3 :(得分:0)

以@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()
    )

答案 4 :(得分:0)

这里是@gitaarik解决方案的精简版,适用于Python 3:

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()

    exception_name = exc_info[0].__name__ if exc_info[0] else 'Exception'
    request_path = f" at {request.path_info}" if request else ''

    reporter = ExceptionReporter(request, *exc_info, is_email=True)

    mail.mail_admins(
        subject=f"{subject_prefix}{exception_name}{request_path}",
        message=reporter.get_traceback_text(),
        fail_silently=True,
        html_message=reporter.get_traceback_html(),
    )