diff --git a/django/utils/log.py b/django/utils/log.py
index df2089f..4a63e40 100644
a
|
b
|
|
1 | 1 | import logging |
| 2 | import sys |
2 | 3 | import traceback |
3 | 4 | |
4 | 5 | from django.conf import settings |
… |
… |
except ImportError:
|
23 | 24 | |
24 | 25 | getLogger = logging.getLogger |
25 | 26 | |
26 | | # Ensure the creation of the Django logger |
27 | | # with a null handler. This ensures we don't get any |
| 27 | |
| 28 | class RequireDebugFalse(logging.Filter): |
| 29 | def filter(self, record): |
| 30 | return not settings.DEBUG |
| 31 | |
| 32 | class RequireDebugTrue(logging.Filter): |
| 33 | def filter(self, record): |
| 34 | return settings.DEBUG |
| 35 | |
| 36 | |
| 37 | # Ensure the creation of the Django logger with at least one handler. |
| 38 | # This ensures we don't get any |
28 | 39 | # 'No handlers could be found for logger "django"' messages |
29 | 40 | logger = getLogger('django') |
30 | 41 | if not logger.handlers: |
31 | | logger.addHandler(NullHandler()) |
| 42 | stream_h = logging.StreamHandler() |
| 43 | stream_h.addFilter(RequireDebugTrue()) |
| 44 | logger.addHandler(stream_h) |
32 | 45 | |
33 | 46 | |
34 | 47 | class AdminEmailHandler(logging.Handler): |
… |
… |
class CallbackFilter(logging.Filter):
|
98 | 111 | if self.callback(record): |
99 | 112 | return 1 |
100 | 113 | return 0 |
101 | | |
102 | | |
103 | | class RequireDebugFalse(logging.Filter): |
104 | | def filter(self, record): |
105 | | return not settings.DEBUG |
diff --git a/docs/topics/logging.txt b/docs/topics/logging.txt
index 28baf87..20fe94f 100644
a
|
b
|
Django provides three built-in loggers.
|
424 | 424 | ``django`` is the catch-all logger. No messages are posted directly to |
425 | 425 | this logger. |
426 | 426 | |
| 427 | .. versionchanged:: 1.5 |
| 428 | |
| 429 | Previously, all messages reaching this logger were discarded unless the |
| 430 | logger had been customized. In Django 1.5, and when :setting:`DEBUG` is |
| 431 | ``True``, all messages are printed to ``stderr`` by default. |
| 432 | |
427 | 433 | ``django.request`` |
428 | 434 | ~~~~~~~~~~~~~~~~~~ |
429 | 435 | |
… |
… |
logging module.
|
567 | 573 | 'class': 'django.utils.log.AdminEmailHandler' |
568 | 574 | } |
569 | 575 | }, |
| 576 | |
| 577 | .. class:: RequireDebugTrue() |
| 578 | |
| 579 | .. versionadded:: 1.5 |
| 580 | |
| 581 | This filter will only pass on records when settings.DEBUG is True. |
diff --git a/tests/regressiontests/logging_tests/tests.py b/tests/regressiontests/logging_tests/tests.py
index 4ae3c1b..7ba5126 100644
a
|
b
|
|
1 | 1 | from __future__ import unicode_literals |
2 | 2 | |
3 | 3 | import copy |
| 4 | import logging |
| 5 | import sys |
4 | 6 | import warnings |
5 | 7 | |
6 | 8 | from django.conf import compat_patch_logging_config |
… |
… |
from django.core import mail
|
8 | 10 | from django.test import TestCase, RequestFactory |
9 | 11 | from django.test.utils import override_settings |
10 | 12 | from django.utils.log import CallbackFilter, RequireDebugFalse, getLogger |
| 13 | from django.utils.six import StringIO |
11 | 14 | |
12 | 15 | |
13 | 16 | # logging config prior to using filter with mail_admins |
… |
… |
class PatchLoggingConfigTest(TestCase):
|
106 | 109 | self.assertEqual(config, new_config) |
107 | 110 | |
108 | 111 | |
| 112 | class DefaultLoggingTest(TestCase): |
| 113 | def setUp(self): |
| 114 | self.logger = logging.getLogger('django') |
| 115 | self.old_stream = self.logger.handlers[0].stream |
| 116 | |
| 117 | def tearDown(self): |
| 118 | self.logger.handlers[0].stream = self.old_stream |
| 119 | |
| 120 | def test_django_logger(self): |
| 121 | """ |
| 122 | The 'django' base logger only output anything when DEBUG=True. |
| 123 | """ |
| 124 | output = StringIO() |
| 125 | self.logger.handlers[0].stream = output |
| 126 | self.logger.error("Hey, this is an error.") |
| 127 | self.assertEqual(output.getvalue(), '') |
| 128 | |
| 129 | with self.settings(DEBUG=True): |
| 130 | self.logger.error("Hey, this is an error.") |
| 131 | self.assertEqual(output.getvalue(), 'Hey, this is an error.\n') |
| 132 | |
| 133 | |
109 | 134 | class CallbackFilterTest(TestCase): |
110 | 135 | def test_sense(self): |
111 | 136 | f_false = CallbackFilter(lambda r: False) |