Déclencher manuellement le rapport D'erreur D'email Django

Django error reporting gère les exceptions non récupérées en envoyant un email, et (optionnellement) montre à l'utilisateur une page d'erreur nice 500.

Cela fonctionne très bien, mais dans quelques cas, j'aimerais permettre aux utilisateurs de continuer leur activité, sans interruption, mais encore Django m'envoyer l'e-mail de rapport d'erreur à propos de l'exception.

donc essentiellement: Est-ce que je peux envoyer manuellement un rapport d'erreur de courriel même si j'attrape l'exception?

bien sûr, j'aimerais éviter de générer manuellement le courriel de rapport d'erreur.

26
demandé sur frnhr 2015-04-01 16:37:28

4 réponses

vous pouvez utiliser le code suivant pour envoyer manuellement un email au sujet d'un request et une exception 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()
    )

vous pouvez le tester dans une vue comme celle-ci:

def test_view(request):
    try:
        raise Exception
    except Exception as e:
        send_manually_exception_email(request, e)
28
répondu JuniorCompressor 2015-04-28 17:53:56

il suffit de configurer un gestionnaire de journalisation simple dans vos paramètres.

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

et alors, à votre avis, vous ne pouvez rien faire

 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

si vous voulez un rapport d'erreur détaillé, vous pouvez essayer quelque chose comme ceci .

Vous avez également besoin de prendre soin de "1519110920 des" informations sensibles .

6
répondu ChillarAnand 2016-11-17 21:27:53

Oui vous pouvez envoyer manuellement un rapport d'erreur par courriel même si vous avez saisi l'exception.

il y a plusieurs façons d'y arriver.

  1. vous pouvez utiliser la configuration par défaut de l'enregistreur (et sa configuration de gestionnaire associée, documentée ici ) pour django.requête qui envoie tous les messages d'erreur au gestionnaire mail_adms, qui envoie tout ce qui est enregistré avec log.erreur de django.demande lors de la debug est faux en tant qu'email en utilisant AdminEmailHandler , dont le point d'appel existant est handle_uncaught_exception .
  2. vous pouvez ajouter une configuration logger supplémentaire qui utilise le même gestionnaire, pour attraper votre exception plus tôt que django.demande et journal des appels.erreur plus tôt.
  3. vous pouvez classer django.demande, plus précisément handle_uncaught_exception.
  4. vous pouvez utiliser un middleware ( par exemple StandardExceptionMiddleware ) ou ExceptionMiddleware
  5. vous pouvez appeler manuellement le contenu d'emit dans AdminEmailHandler ou par la poste.mail_admins directement.

parmi ces options, L'Option 4 semble être la plus courante.

D'après les renseignements supplémentaires contenus dans votre commentaire, un exemple de code 2 est présenté ci-dessous.

First le code qui serait ajouté pour voir

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

basé sur la documentation Django pour l'écriture de vue et et l'introduction à la journalisation de Django , mais n'a pas été testé.

puis la configuration de logger supplémentaire est ajoutée à l'entrée de loggers (selon ici )

'nameofdjangoapplicationgoeshere': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': False,
        },
3
répondu Appleman1234 2015-04-23 09:27:20

j'utilise principalement Ce modèle avec le rapport d'erreur standard.

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

il va déclencher le rapport d'erreur intégré et enregistreur.exception va attraper le cadre de pile. https://docs.djangoproject.com/en/1.8/topics/logging/#making-logging-calls

edit:

j'ai remarqué que certaines informations manquaient dans l'email et pour obtenir un retraçage exact car le construit dans ce qui suit peut être utilisé à la place:

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

plus d'informations trouvées ici: comment envoyer le journal des exceptions django manuellement?

1
répondu Daniel Backman 2017-05-23 11:47:10