瀏覽代碼

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

Nasir Hussain 6 年之前
父節點
當前提交
25706d7285
共有 5 個文件被更改,包括 53 次插入4 次删除
  1. 3 3
      django/utils/log.py
  2. 8 0
      docs/releases/3.0.txt
  3. 21 1
      docs/topics/logging.txt
  4. 6 0
      tests/logging_tests/logconfig.py
  5. 15 0
      tests/logging_tests/tests.py

+ 3 - 3
django/utils/log.py

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

+ 8 - 0
docs/releases/3.0.txt

@@ -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
 ~~~~~~~~~~~~~~~~~~~
 

+ 21 - 1
docs/topics/logging.txt

@@ -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

+ 6 - 0
tests/logging_tests/logconfig.py

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

+ 15 - 0
tests/logging_tests/tests.py

@@ -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):
     """