web-dev-qa-db-ja.com

手動でトリガーDjangoメールエラーレポート

Djangoエラーレポート 電子メールを送信することでキャッチされなかった例外を処理し、(オプションで)ユーザーにNice500エラーページを表示します。

これは非常にうまく機能しますが、いくつかの例では、ユーザーがビジネスを中断することなく続行できるようにしたいのですが、それでもDjango例外に関するメールエラーレポートを送ってください。

つまり、基本的に、例外をキャッチした場合でも、手動で電子メールエラーレポートを送信できますか?

もちろん、エラーレポートの電子メールを手動で生成することは避けたいと思います。

33
frnhr

次のコードを使用して、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)
35

設定で簡単なログハンドラーを設定するだけです。

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

詳細なエラーレポートが必要な場合は、 このようなもの を試すことができます。

機密情報 にも注意する必要があります。

6
ChillarAnand

はい、例外をキャッチした場合でも、手動で電子メールエラーレポートを送信できます。

これについては、いくつかの方法があります。

  1. Django.requestには既存のデフォルトのロガー構成(および関連するハンドラー構成、文書化 ここ )を使用できます。これにより、すべてのエラーメッセージがmail_adminsハンドラーに送信され、log.errorでログに記録されたものはすべてDjangoから送信されます。 .requestは、既存の呼び出しポイントが handle_uncaught_exception にある AdminEmailHandler を使用する電子メールとしてデバッグがfalseの場合。
  2. 同じハンドラーを使用するロガー構成を追加して、Django.requestよりも早く例外をキャッチし、log.errorを早く呼び出すことができます。
  3. Django.request、具体的にはhandle_uncaught_exceptionをサブクラス化できます。
  4. カスタムミドルウェア( たとえばStandardExceptionMiddleware )または ExceptionMiddleware を使用できます
  5. AdminEmailHandlerまたはmail.mail_adminsのemitの内容を手動で直接呼び出すことができます。

これらのオプションのうち、オプション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
Appleman1234

私は主にこのパターンを標準のエラー報告で使用します。

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例外ログを手動で送信する方法

3
Daniel Backman

@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()
    )
0
gitaarik