2015-04-01 16 views
25

Django error reporting behandelt nicht abgefangene Ausnahmen durch Senden einer E-Mail und (optional) zeigt Benutzer eine nette 500-Fehlerseite.Django E-Mail-Fehlerbericht manuell auslösen

Das funktioniert sehr gut, aber in ein paar Fällen möchte ich Benutzern erlauben, mit ihrem Geschäft ohne Unterbrechung fortzufahren, aber immer noch Django senden Sie mir den E-Mail-Fehlerbericht über die Ausnahme.

Also im Grunde: kann ich manuell E-Mail-Fehlerbericht senden, auch wenn ich die Ausnahme abfangen?

Natürlich möchte ich vermeiden, manuell die Fehlermeldung E-Mail zu generieren.

Antwort

27

können Sie den folgenden Code verwenden e manuell eine E-Mail über eine request und eine Ausnahme senden:

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

Sie können es in einer wie diese Ansicht testen:

def test_view(request): 
    try: 
     raise Exception 
    except Exception as e: 
     send_manually_exception_email(request, e) 
+0

Süßeste! Und obwohl keine Antwort genau den Fehlerbericht erzeugt, der automatisch generiert wird, gab dieser Ansatz die meisten Informationen. Es ist ähnlich wie die Fehlerseite Django zeigt mit 'DEBUG = True' – frnhr

+0

Ich bekomme einen Fehler in Zeile Nr. 9. Es heißt:' 'Exception' Objekt hat kein Attribut 'Nachricht'' –

+0

hinzugefügt eine Bearbeitung, damit es funktioniert python 3 – maxbellec

3

Ja, Sie können E-Mail-Fehlerbericht manuell senden, auch wenn Sie die Ausnahme abfangen.

Es gibt mehrere Möglichkeiten, wie Sie das erreichen können.

  1. Sie können die vorhandenen Standardlogger Konfiguration verwenden (und die zugehörige Verarbeitungsroutine Konfiguration dokumentiert here) für django.request, die alle Fehlermeldungen an den mail_admins Handler sendet, die die etwas mit log.error von django angemeldet sendet. Anfrage, wenn das Debugging falsch ist, als E-Mail unter Verwendung von AdminEmailHandler, dessen bestehender Anrufpunkt in handle_uncaught_exception liegt.
  2. Sie können zusätzliche Loggerkonfiguration hinzufügen, die denselben Handler verwendet, um Ihre Ausnahme früher als django.request abzufangen und log.error früher aufzurufen.
  3. Sie können django.request spezifisch ableiten, nämlich handle_uncaught_exception.
  4. Sie können eine eigene Middleware (for example StandardExceptionMiddleware) verwenden oder ExceptionMiddleware
  5. Sie können den Inhalt von emit in AdminEmailHandler oder mail.mail_admins direkt manuell aufrufen.

Von diesen Optionen scheint Option 4 am häufigsten zu sein.

Basierend auf den zusätzlichen Informationen in Ihrem Kommentar ein Codebeispiel von 2 ist unten.

Zuerst wird der Code, der diese

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

basiert von Django documentation for view writing und and introduction to Django logging, aber wurde nicht geprüft sehen hinzugefügt werden würde.

Dann wird die zusätzliche Logger-Konfiguration wird auf dem auf den Logger Eintrag hinzufügen (per here)

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

Ich möchte den Fehlerbericht von einer Ansicht auslösen und dann mit den Dingen wie gewohnt fortfahren (dh zulassen, dass die Ansicht eine HttpResponse zurückgibt), also glaube ich nicht, dass eine Middleware das tun wird. Oder fehlt mir smth, @Brandon's Kommentar zeigt auch Middleware an? Die Optionen 1 und 2 scheinen die Antwort zu sein. Möchten Sie ein Codebeispiel hinzufügen? – frnhr

6

Nur Setup eines einfacher Protokollhandler in Ihren Einstellungen.

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, 
     }, 
    } 
} 

und dann Ihrer Meinung nach kann man alles

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 

tun Wenn Sie detaillierte Fehlermeldung möchten, können Sie something like this versuchen.

Sie müssen auch auf sensitive information aufpassen.

1

ich meistens verwenden dieses Muster mit der Standardfehlermeldung.

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 

Es wird die Meldung in Fehler gebaut auslösen und logger.exception den Stapelrahmen fangen. https://docs.djangoproject.com/en/1.8/topics/logging/#making-logging-calls

edit:

ich einige Informationen bemerkt wurde in der E-Mail fehlt und eine genaue Rückverfolgung wie die in den folgenden integrierten bekommen können stattdessen verwendet werden:

logger.exception('Internal Server Error: %s', request.path, 
       extra={'status_code': 500, 'request': request}) 

Mehr Informationen finden Sie hier: How to send django exception log manually?

Verwandte Themen