Fixed #29714 -- Allowed using ExceptionReporter subclass with AdminEmailHandler.

This commit is contained in:
Nasir Hussain 2019-02-24 20:10:14 +05:00 committed by Mariusz Felisiak
parent 3c6a4fdb6d
commit 25706d7285
5 changed files with 53 additions and 4 deletions

View File

@ -7,7 +7,6 @@ from django.core import mail
from django.core.mail import get_connection
from django.core.management.color import color_style
from django.utils.module_loading import import_string
from django.views.debug import ExceptionReporter
request_logger = logging.getLogger('django.request')
@ -83,10 +82,11 @@ class AdminEmailHandler(logging.Handler):
request data will be provided in the email report.
"""
def __init__(self, include_html=False, email_backend=None):
def __init__(self, include_html=False, email_backend=None, reporter_class=None):
super().__init__()
self.include_html = include_html
self.email_backend = email_backend
self.reporter_class = import_string(reporter_class or 'django.views.debug.ExceptionReporter')
def emit(self, record):
try:
@ -116,7 +116,7 @@ class AdminEmailHandler(logging.Handler):
else:
exc_info = (None, record.getMessage(), None)
reporter = ExceptionReporter(request, is_email=True, *exc_info)
reporter = self.reporter_class(request, is_email=True, *exc_info)
message = "%s\n\n%s" % (self.format(no_exc_record), reporter.get_traceback_text())
html_message = reporter.get_traceback_html() if self.include_html else None
self.send_mail(subject, message, fail_silently=True, html_message=html_message)

View File

@ -259,6 +259,14 @@ Internationalization
language cookies. The default values of these settings preserve the previous
behavior.
Logging
~~~~~~~
* The new ``reporter_class`` parameter of
:class:`~django.utils.log.AdminEmailHandler` allows providing an
``django.views.debug.ExceptionReporter`` subclass to customize the traceback
text sent to site :setting:`ADMINS` when :setting:`DEBUG` is ``False``.
Management Commands
~~~~~~~~~~~~~~~~~~~

View File

@ -595,7 +595,7 @@ Handlers
Django provides one log handler in addition to those provided by the
Python logging module.
.. class:: AdminEmailHandler(include_html=False, email_backend=None)
.. class:: AdminEmailHandler(include_html=False, email_backend=None, reporter_class=None)
This handler sends an email to the site :setting:`ADMINS` for each log
message it receives.
@ -652,6 +652,26 @@ Python logging module.
By default, an instance of the email backend specified in
:setting:`EMAIL_BACKEND` will be used.
The ``reporter_class`` argument of ``AdminEmailHandler`` allows providing
an ``django.views.debug.ExceptionReporter`` subclass to customize the
traceback text sent in the email body. You provide a string import path to
the class you wish to use, like this:
.. code-block:: python
'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'include_html': True,
'reporter_class': 'somepackage.error_reporter.CustomErrorReporter'
}
},
.. versionadded:: 3.0
The ``reporter_class`` argument was added.
.. method:: send_mail(subject, message, *args, **kwargs)
Sends emails to admin users. To customize this behavior, you can

View File

@ -2,6 +2,7 @@ import logging
from django.conf import settings
from django.core.mail.backends.base import BaseEmailBackend
from django.views.debug import ExceptionReporter
class MyHandler(logging.Handler):
@ -13,3 +14,8 @@ class MyHandler(logging.Handler):
class MyEmailBackend(BaseEmailBackend):
def send_messages(self, email_messages):
pass
class CustomExceptionReporter(ExceptionReporter):
def get_traceback_text(self):
return 'custom traceback text'

View File

@ -16,6 +16,7 @@ from django.utils.log import (
DEFAULT_LOGGING, AdminEmailHandler, CallbackFilter, RequireDebugFalse,
RequireDebugTrue, ServerFormatter,
)
from django.views.debug import ExceptionReporter
from . import views
from .logconfig import MyEmailBackend
@ -431,6 +432,20 @@ class AdminEmailHandlerTest(SimpleTestCase):
finally:
admin_email_handler.include_html = old_include_html
def test_default_exception_reporter_class(self):
admin_email_handler = self.get_admin_email_handler(self.logger)
self.assertEqual(admin_email_handler.reporter_class, ExceptionReporter)
@override_settings(ADMINS=[('A.N.Admin', 'admin@example.com')])
def test_custom_exception_reporter_is_used(self):
record = self.logger.makeRecord('name', logging.ERROR, 'function', 'lno', 'message', None, None)
record.request = self.request_factory.get('/')
handler = AdminEmailHandler(reporter_class='logging_tests.logconfig.CustomExceptionReporter')
handler.emit(record)
self.assertEqual(len(mail.outbox), 1)
msg = mail.outbox[0]
self.assertEqual(msg.body, 'message\n\ncustom traceback text')
class SettingsConfigTest(AdminScriptTestCase):
"""