Sfoglia il codice sorgente

Fixed #18993 -- 'django' logger logs to console when DEBUG=True

Thanks Preston Holmes for the review.
Claude Paroz 12 anni fa
parent
commit
f0f327bbfe

+ 19 - 6
django/utils/log.py

@@ -24,18 +24,25 @@ except ImportError:
 
 getLogger = logging.getLogger
 
-# Default logging for Django. This sends an email to
-# the site admins on every HTTP 500 error. All other log
-# records are sent to the bit bucket.
+# Default logging for Django. This sends an email to the site admins on every
+# HTTP 500 error. Depending on DEBUG, all other log records are either sent to
+# the console (DEBUG=True) or discarded by mean of the NullHandler (DEBUG=False).
 DEFAULT_LOGGING = {
     'version': 1,
     'disable_existing_loggers': False,
     'filters': {
         'require_debug_false': {
             '()': 'django.utils.log.RequireDebugFalse',
-        }
+        },
+        'require_debug_true': {
+            '()': 'django.utils.log.RequireDebugTrue',
+        },
     },
     'handlers': {
+        'console':{
+            'level': 'INFO',
+            'class': 'logging.StreamHandler',
+        },
         'null': {
             'class': 'django.utils.log.NullHandler',
         },
@@ -47,12 +54,13 @@ DEFAULT_LOGGING = {
     },
     'loggers': {
         'django': {
-            'handlers': ['null'],
+            'handlers': ['console'],
+            'filters': ['require_debug_true'],
         },
         'django.request': {
             'handlers': ['mail_admins'],
             'level': 'ERROR',
-            'propagate': True,
+            'propagate': False,
         },
     }
 }
@@ -130,3 +138,8 @@ class CallbackFilter(logging.Filter):
 class RequireDebugFalse(logging.Filter):
     def filter(self, record):
         return not settings.DEBUG
+
+
+class RequireDebugTrue(logging.Filter):
+    def filter(self, record):
+       return settings.DEBUG

+ 4 - 0
docs/releases/1.5.txt

@@ -172,6 +172,10 @@ Django 1.5 also includes several smaller improvements worth noting:
 * An instance of :class:`~django.core.urlresolvers.ResolverMatch` is stored on
   the request as ``resolver_match``.
 
+* By default, all logging messages reaching the `django` logger when
+  :setting:`DEBUG` is `True` are sent to the console (unless you redefine the
+  logger in your :setting:`LOGGING` setting).
+
 Backwards incompatible changes in 1.5
 =====================================
 

+ 18 - 2
docs/topics/logging.txt

@@ -546,6 +546,13 @@ logging module.
             }
         },
 
+.. class:: RequireDebugTrue()
+
+   .. versionadded:: 1.5
+
+   This filter is similar to :class:`RequireDebugFalse`, except that records are
+   passed only when :setting:`DEBUG` is `True`.
+
 .. _default-logging-configuration:
 
 Django's default logging configuration
@@ -555,5 +562,14 @@ By default, Django configures the ``django.request`` logger so that all messages
 with ``ERROR`` or ``CRITICAL`` level are sent to :class:`AdminEmailHandler`, as
 long as the :setting:`DEBUG` setting is set to ``False``.
 
-All messages reaching the ``django`` catch-all logger are discarded
-(sent to ``NullHandler``).
+All messages reaching the ``django`` catch-all logger when :setting:`DEBUG` is
+`True` are sent ot the console. They are simply discarded (sent to
+``NullHandler``) when :setting:`DEBUG` is `False`.
+
+.. versionchanged:: 1.5
+
+    Before Django 1.5, all messages reaching the ``django`` logger were
+    discarded, regardless of :setting:`DEBUG`.
+
+See also :ref:`Configuring logging <configuring-logging>` to learn how you can
+complement or replace this default logging configuration.

+ 30 - 10
tests/regressiontests/logging_tests/tests.py

@@ -9,6 +9,7 @@ from django.core import mail
 from django.test import TestCase, RequestFactory
 from django.test.utils import override_settings
 from django.utils.log import CallbackFilter, RequireDebugFalse
+from django.utils.six import StringIO
 
 from ..admin_scripts.tests import AdminScriptTestCase
 
@@ -109,6 +110,28 @@ class PatchLoggingConfigTest(TestCase):
         self.assertEqual(config, new_config)
 
 
+class DefaultLoggingTest(TestCase):
+    def setUp(self):
+        self.logger = logging.getLogger('django')
+        self.old_stream = self.logger.handlers[0].stream
+
+    def tearDown(self):
+        self.logger.handlers[0].stream = self.old_stream
+
+    def test_django_logger(self):
+        """
+        The 'django' base logger only output anything when DEBUG=True.
+        """
+        output = StringIO()
+        self.logger.handlers[0].stream = output
+        self.logger.error("Hey, this is an error.")
+        self.assertEqual(output.getvalue(), '')
+
+        with self.settings(DEBUG=True):
+            self.logger.error("Hey, this is an error.")
+            self.assertEqual(output.getvalue(), 'Hey, this is an error.\n')
+
+
 class CallbackFilterTest(TestCase):
     def test_sense(self):
         f_false = CallbackFilter(lambda r: False)
@@ -131,6 +154,7 @@ class CallbackFilterTest(TestCase):
 
 
 class AdminEmailHandlerTest(TestCase):
+    logger = logging.getLogger('django.request')
 
     def get_admin_email_handler(self, logger):
         # Inspired from regressiontests/views/views.py: send_log()
@@ -156,14 +180,13 @@ class AdminEmailHandlerTest(TestCase):
         token1 = 'ping'
         token2 = 'pong'
 
-        logger = logging.getLogger('django.request')
-        admin_email_handler = self.get_admin_email_handler(logger)
+        admin_email_handler = self.get_admin_email_handler(self.logger)
         # Backup then override original filters
         orig_filters = admin_email_handler.filters
         try:
             admin_email_handler.filters = []
 
-            logger.error(message, token1, token2)
+            self.logger.error(message, token1, token2)
 
             self.assertEqual(len(mail.outbox), 1)
             self.assertEqual(mail.outbox[0].to, ['admin@example.com'])
@@ -187,15 +210,14 @@ class AdminEmailHandlerTest(TestCase):
         token1 = 'ping'
         token2 = 'pong'
 
-        logger = logging.getLogger('django.request')
-        admin_email_handler = self.get_admin_email_handler(logger)
+        admin_email_handler = self.get_admin_email_handler(self.logger)
         # Backup then override original filters
         orig_filters = admin_email_handler.filters
         try:
             admin_email_handler.filters = []
             rf = RequestFactory()
             request = rf.get('/')
-            logger.error(message, token1, token2,
+            self.logger.error(message, token1, token2,
                 extra={
                     'status_code': 403,
                     'request': request,
@@ -225,8 +247,7 @@ class AdminEmailHandlerTest(TestCase):
 
         self.assertEqual(len(mail.outbox), 0)
 
-        logger = logging.getLogger('django.request')
-        logger.error(message)
+        self.logger.error(message)
 
         self.assertEqual(len(mail.outbox), 1)
         self.assertFalse('\n' in mail.outbox[0].subject)
@@ -250,8 +271,7 @@ class AdminEmailHandlerTest(TestCase):
 
         self.assertEqual(len(mail.outbox), 0)
 
-        logger = logging.getLogger('django.request')
-        logger.error(message)
+        self.logger.error(message)
 
         self.assertEqual(len(mail.outbox), 1)
         self.assertEqual(mail.outbox[0].subject, expected_subject)