mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #18993 -- 'django' logger logs to console when DEBUG=True
Thanks Preston Holmes for the review.
This commit is contained in:
		| @@ -24,18 +24,25 @@ except ImportError: | |||||||
|  |  | ||||||
| getLogger = logging.getLogger | getLogger = logging.getLogger | ||||||
|  |  | ||||||
| # Default logging for Django. This sends an email to | # Default logging for Django. This sends an email to the site admins on every | ||||||
| # the site admins on every HTTP 500 error. All other log | # HTTP 500 error. Depending on DEBUG, all other log records are either sent to | ||||||
| # records are sent to the bit bucket. | # the console (DEBUG=True) or discarded by mean of the NullHandler (DEBUG=False). | ||||||
| DEFAULT_LOGGING = { | DEFAULT_LOGGING = { | ||||||
|     'version': 1, |     'version': 1, | ||||||
|     'disable_existing_loggers': False, |     'disable_existing_loggers': False, | ||||||
|     'filters': { |     'filters': { | ||||||
|         'require_debug_false': { |         'require_debug_false': { | ||||||
|             '()': 'django.utils.log.RequireDebugFalse', |             '()': 'django.utils.log.RequireDebugFalse', | ||||||
|         } |         }, | ||||||
|  |         'require_debug_true': { | ||||||
|  |             '()': 'django.utils.log.RequireDebugTrue', | ||||||
|  |         }, | ||||||
|     }, |     }, | ||||||
|     'handlers': { |     'handlers': { | ||||||
|  |         'console':{ | ||||||
|  |             'level': 'INFO', | ||||||
|  |             'class': 'logging.StreamHandler', | ||||||
|  |         }, | ||||||
|         'null': { |         'null': { | ||||||
|             'class': 'django.utils.log.NullHandler', |             'class': 'django.utils.log.NullHandler', | ||||||
|         }, |         }, | ||||||
| @@ -47,12 +54,13 @@ DEFAULT_LOGGING = { | |||||||
|     }, |     }, | ||||||
|     'loggers': { |     'loggers': { | ||||||
|         'django': { |         'django': { | ||||||
|             'handlers': ['null'], |             'handlers': ['console'], | ||||||
|  |             'filters': ['require_debug_true'], | ||||||
|         }, |         }, | ||||||
|         'django.request': { |         'django.request': { | ||||||
|             'handlers': ['mail_admins'], |             'handlers': ['mail_admins'], | ||||||
|             'level': 'ERROR', |             'level': 'ERROR', | ||||||
|             'propagate': True, |             'propagate': False, | ||||||
|         }, |         }, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -130,3 +138,8 @@ class CallbackFilter(logging.Filter): | |||||||
| class RequireDebugFalse(logging.Filter): | class RequireDebugFalse(logging.Filter): | ||||||
|     def filter(self, record): |     def filter(self, record): | ||||||
|         return not settings.DEBUG |         return not settings.DEBUG | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RequireDebugTrue(logging.Filter): | ||||||
|  |     def filter(self, record): | ||||||
|  |        return settings.DEBUG | ||||||
|   | |||||||
| @@ -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 | * An instance of :class:`~django.core.urlresolvers.ResolverMatch` is stored on | ||||||
|   the request as ``resolver_match``. |   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 | Backwards incompatible changes in 1.5 | ||||||
| ===================================== | ===================================== | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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: | .. _default-logging-configuration: | ||||||
|  |  | ||||||
| Django's 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 | with ``ERROR`` or ``CRITICAL`` level are sent to :class:`AdminEmailHandler`, as | ||||||
| long as the :setting:`DEBUG` setting is set to ``False``. | long as the :setting:`DEBUG` setting is set to ``False``. | ||||||
|  |  | ||||||
| All messages reaching the ``django`` catch-all logger are discarded | All messages reaching the ``django`` catch-all logger when :setting:`DEBUG` is | ||||||
| (sent to ``NullHandler``). | `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. | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ from django.core import mail | |||||||
| from django.test import TestCase, RequestFactory | from django.test import TestCase, RequestFactory | ||||||
| from django.test.utils import override_settings | from django.test.utils import override_settings | ||||||
| from django.utils.log import CallbackFilter, RequireDebugFalse | from django.utils.log import CallbackFilter, RequireDebugFalse | ||||||
|  | from django.utils.six import StringIO | ||||||
|  |  | ||||||
| from ..admin_scripts.tests import AdminScriptTestCase | from ..admin_scripts.tests import AdminScriptTestCase | ||||||
|  |  | ||||||
| @@ -109,6 +110,28 @@ class PatchLoggingConfigTest(TestCase): | |||||||
|         self.assertEqual(config, new_config) |         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): | class CallbackFilterTest(TestCase): | ||||||
|     def test_sense(self): |     def test_sense(self): | ||||||
|         f_false = CallbackFilter(lambda r: False) |         f_false = CallbackFilter(lambda r: False) | ||||||
| @@ -131,6 +154,7 @@ class CallbackFilterTest(TestCase): | |||||||
|  |  | ||||||
|  |  | ||||||
| class AdminEmailHandlerTest(TestCase): | class AdminEmailHandlerTest(TestCase): | ||||||
|  |     logger = logging.getLogger('django.request') | ||||||
|  |  | ||||||
|     def get_admin_email_handler(self, logger): |     def get_admin_email_handler(self, logger): | ||||||
|         # Inspired from regressiontests/views/views.py: send_log() |         # Inspired from regressiontests/views/views.py: send_log() | ||||||
| @@ -156,14 +180,13 @@ class AdminEmailHandlerTest(TestCase): | |||||||
|         token1 = 'ping' |         token1 = 'ping' | ||||||
|         token2 = 'pong' |         token2 = 'pong' | ||||||
|  |  | ||||||
|         logger = logging.getLogger('django.request') |         admin_email_handler = self.get_admin_email_handler(self.logger) | ||||||
|         admin_email_handler = self.get_admin_email_handler(logger) |  | ||||||
|         # Backup then override original filters |         # Backup then override original filters | ||||||
|         orig_filters = admin_email_handler.filters |         orig_filters = admin_email_handler.filters | ||||||
|         try: |         try: | ||||||
|             admin_email_handler.filters = [] |             admin_email_handler.filters = [] | ||||||
|  |  | ||||||
|             logger.error(message, token1, token2) |             self.logger.error(message, token1, token2) | ||||||
|  |  | ||||||
|             self.assertEqual(len(mail.outbox), 1) |             self.assertEqual(len(mail.outbox), 1) | ||||||
|             self.assertEqual(mail.outbox[0].to, ['admin@example.com']) |             self.assertEqual(mail.outbox[0].to, ['admin@example.com']) | ||||||
| @@ -187,15 +210,14 @@ class AdminEmailHandlerTest(TestCase): | |||||||
|         token1 = 'ping' |         token1 = 'ping' | ||||||
|         token2 = 'pong' |         token2 = 'pong' | ||||||
|  |  | ||||||
|         logger = logging.getLogger('django.request') |         admin_email_handler = self.get_admin_email_handler(self.logger) | ||||||
|         admin_email_handler = self.get_admin_email_handler(logger) |  | ||||||
|         # Backup then override original filters |         # Backup then override original filters | ||||||
|         orig_filters = admin_email_handler.filters |         orig_filters = admin_email_handler.filters | ||||||
|         try: |         try: | ||||||
|             admin_email_handler.filters = [] |             admin_email_handler.filters = [] | ||||||
|             rf = RequestFactory() |             rf = RequestFactory() | ||||||
|             request = rf.get('/') |             request = rf.get('/') | ||||||
|             logger.error(message, token1, token2, |             self.logger.error(message, token1, token2, | ||||||
|                 extra={ |                 extra={ | ||||||
|                     'status_code': 403, |                     'status_code': 403, | ||||||
|                     'request': request, |                     'request': request, | ||||||
| @@ -225,8 +247,7 @@ class AdminEmailHandlerTest(TestCase): | |||||||
|  |  | ||||||
|         self.assertEqual(len(mail.outbox), 0) |         self.assertEqual(len(mail.outbox), 0) | ||||||
|  |  | ||||||
|         logger = logging.getLogger('django.request') |         self.logger.error(message) | ||||||
|         logger.error(message) |  | ||||||
|  |  | ||||||
|         self.assertEqual(len(mail.outbox), 1) |         self.assertEqual(len(mail.outbox), 1) | ||||||
|         self.assertFalse('\n' in mail.outbox[0].subject) |         self.assertFalse('\n' in mail.outbox[0].subject) | ||||||
| @@ -250,8 +271,7 @@ class AdminEmailHandlerTest(TestCase): | |||||||
|  |  | ||||||
|         self.assertEqual(len(mail.outbox), 0) |         self.assertEqual(len(mail.outbox), 0) | ||||||
|  |  | ||||||
|         logger = logging.getLogger('django.request') |         self.logger.error(message) | ||||||
|         logger.error(message) |  | ||||||
|  |  | ||||||
|         self.assertEqual(len(mail.outbox), 1) |         self.assertEqual(len(mail.outbox), 1) | ||||||
|         self.assertEqual(mail.outbox[0].subject, expected_subject) |         self.assertEqual(mail.outbox[0].subject, expected_subject) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user