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

Thanks Preston Holmes for the review.
This commit is contained in:
Claude Paroz 2012-09-26 19:56:21 +02:00
parent a014ddfef2
commit f0f327bbfe
4 changed files with 71 additions and 18 deletions

View File

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

View File

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

View File

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

View File

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