diff --git a/django/conf/__init__.py b/django/conf/__init__.py
index 6272f4e..ad8a1cf 100644
a
|
b
|
class Settings(BaseSettings):
|
143 | 143 | # Backwards-compatibility shim for #16288 fix |
144 | 144 | compat_patch_logging_config(self.LOGGING) |
145 | 145 | |
| 146 | def check_in_dict(key1, key2): |
| 147 | if not key2 in self.LOGGING.get(key1, {}): |
| 148 | self.LOGGING[key1][key2] = global_settings.LOGGING[key1][key2] |
| 149 | check_in_dict('filters', 'require_debug_true') |
| 150 | check_in_dict('handlers', 'console') |
| 151 | check_in_dict('loggers', 'django') |
| 152 | |
146 | 153 | # ... then invoke it with the logging settings |
147 | 154 | logging_config_func(self.LOGGING) |
148 | 155 | |
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index 13f7991..2274f9a 100644
a
|
b
|
LOGGING = {
|
559 | 559 | 'filters': { |
560 | 560 | 'require_debug_false': { |
561 | 561 | '()': 'django.utils.log.RequireDebugFalse', |
562 | | } |
| 562 | }, |
| 563 | 'require_debug_true': { |
| 564 | '()': 'django.utils.log.RequireDebugTrue', |
| 565 | }, |
563 | 566 | }, |
564 | 567 | 'handlers': { |
| 568 | 'console':{ |
| 569 | 'level': 'INFO', |
| 570 | 'class': 'logging.StreamHandler', |
| 571 | }, |
565 | 572 | 'mail_admins': { |
566 | 573 | 'level': 'ERROR', |
567 | 574 | 'filters': ['require_debug_false'], |
… |
… |
LOGGING = {
|
569 | 576 | } |
570 | 577 | }, |
571 | 578 | 'loggers': { |
| 579 | 'django': { |
| 580 | 'handlers': ['console'], |
| 581 | 'filters': ['require_debug_true'], |
| 582 | }, |
572 | 583 | 'django.request': { |
573 | 584 | 'handlers': ['mail_admins'], |
574 | 585 | 'level': 'ERROR', |
diff --git a/django/utils/log.py b/django/utils/log.py
index df2089f..2400de2 100644
a
|
b
|
try:
|
21 | 21 | except ImportError: |
22 | 22 | from django.utils.dictconfig import dictConfig |
23 | 23 | |
| 24 | # This is a remainder of an old 2.4 shim: to be deprecated or simply removed |
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 |
28 | | # 'No handlers could be found for logger "django"' messages |
29 | | logger = getLogger('django') |
30 | | if not logger.handlers: |
31 | | logger.addHandler(NullHandler()) |
32 | | |
33 | | |
34 | 27 | class AdminEmailHandler(logging.Handler): |
35 | 28 | """An exception log handler that emails log entries to site admins. |
36 | 29 | |
… |
… |
class CallbackFilter(logging.Filter):
|
103 | 96 | class RequireDebugFalse(logging.Filter): |
104 | 97 | def filter(self, record): |
105 | 98 | return not settings.DEBUG |
| 99 | |
| 100 | |
| 101 | class RequireDebugTrue(logging.Filter): |
| 102 | def filter(self, record): |
| 103 | return settings.DEBUG |
diff --git a/tests/regressiontests/logging_tests/tests.py b/tests/regressiontests/logging_tests/tests.py
index f444e0f..dd2fc82 100644
a
|
b
|
from django.core import mail
|
9 | 9 | from django.test import TestCase, RequestFactory |
10 | 10 | from django.test.utils import override_settings |
11 | 11 | from django.utils.log import CallbackFilter, RequireDebugFalse |
| 12 | from django.utils.six import StringIO |
12 | 13 | |
13 | 14 | |
14 | 15 | # logging config prior to using filter with mail_admins |
… |
… |
class PatchLoggingConfigTest(TestCase):
|
107 | 108 | self.assertEqual(config, new_config) |
108 | 109 | |
109 | 110 | |
| 111 | class DefaultLoggingTest(TestCase): |
| 112 | def setUp(self): |
| 113 | self.logger = logging.getLogger('django') |
| 114 | self.old_stream = self.logger.handlers[0].stream |
| 115 | |
| 116 | def tearDown(self): |
| 117 | self.logger.handlers[0].stream = self.old_stream |
| 118 | |
| 119 | def test_django_logger(self): |
| 120 | """ |
| 121 | The 'django' base logger only output anything when DEBUG=True. |
| 122 | """ |
| 123 | output = StringIO() |
| 124 | self.logger.handlers[0].stream = output |
| 125 | self.logger.error("Hey, this is an error.") |
| 126 | self.assertEqual(output.getvalue(), '') |
| 127 | |
| 128 | with self.settings(DEBUG=True): |
| 129 | self.logger.error("Hey, this is an error.") |
| 130 | self.assertEqual(output.getvalue(), 'Hey, this is an error.\n') |
| 131 | |
| 132 | |
110 | 133 | class CallbackFilterTest(TestCase): |
111 | 134 | def test_sense(self): |
112 | 135 | f_false = CallbackFilter(lambda r: False) |
… |
… |
class CallbackFilterTest(TestCase):
|
129 | 152 | |
130 | 153 | |
131 | 154 | class AdminEmailHandlerTest(TestCase): |
| 155 | def setUp(self): |
| 156 | self.logger = logging.getLogger('django.request') |
| 157 | self.old_propagate = self.logger.propagate |
| 158 | self.logger.propagate = False |
| 159 | |
| 160 | def tearDown(self): |
| 161 | self.logger.propagate = self.old_propagate |
132 | 162 | |
133 | 163 | def get_admin_email_handler(self, logger): |
134 | 164 | # Inspired from regressiontests/views/views.py: send_log() |
… |
… |
class AdminEmailHandlerTest(TestCase):
|
154 | 184 | token1 = 'ping' |
155 | 185 | token2 = 'pong' |
156 | 186 | |
157 | | logger = logging.getLogger('django.request') |
158 | | admin_email_handler = self.get_admin_email_handler(logger) |
| 187 | admin_email_handler = self.get_admin_email_handler(self.logger) |
159 | 188 | # Backup then override original filters |
160 | 189 | orig_filters = admin_email_handler.filters |
161 | 190 | try: |
162 | 191 | admin_email_handler.filters = [] |
163 | 192 | |
164 | | logger.error(message, token1, token2) |
| 193 | self.logger.error(message, token1, token2) |
165 | 194 | |
166 | 195 | self.assertEqual(len(mail.outbox), 1) |
167 | 196 | self.assertEqual(mail.outbox[0].to, ['admin@example.com']) |
… |
… |
class AdminEmailHandlerTest(TestCase):
|
185 | 214 | token1 = 'ping' |
186 | 215 | token2 = 'pong' |
187 | 216 | |
188 | | logger = logging.getLogger('django.request') |
189 | | admin_email_handler = self.get_admin_email_handler(logger) |
| 217 | admin_email_handler = self.get_admin_email_handler(self.logger) |
190 | 218 | # Backup then override original filters |
191 | 219 | orig_filters = admin_email_handler.filters |
192 | 220 | try: |
193 | 221 | admin_email_handler.filters = [] |
194 | 222 | rf = RequestFactory() |
195 | 223 | request = rf.get('/') |
196 | | logger.error(message, token1, token2, |
| 224 | self.logger.error(message, token1, token2, |
197 | 225 | extra={ |
198 | 226 | 'status_code': 403, |
199 | 227 | 'request': request, |
… |
… |
class AdminEmailHandlerTest(TestCase):
|
223 | 251 | |
224 | 252 | self.assertEqual(len(mail.outbox), 0) |
225 | 253 | |
226 | | logger = logging.getLogger('django.request') |
227 | | logger.error(message) |
| 254 | self.logger.error(message) |
228 | 255 | |
229 | 256 | self.assertEqual(len(mail.outbox), 1) |
230 | 257 | self.assertFalse('\n' in mail.outbox[0].subject) |
… |
… |
class AdminEmailHandlerTest(TestCase):
|
248 | 275 | |
249 | 276 | self.assertEqual(len(mail.outbox), 0) |
250 | 277 | |
251 | | logger = logging.getLogger('django.request') |
252 | | logger.error(message) |
| 278 | self.logger.error(message) |
253 | 279 | |
254 | 280 | self.assertEqual(len(mail.outbox), 1) |
255 | 281 | self.assertEqual(mail.outbox[0].subject, expected_subject) |
diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
index 2836d1b..f4e7a5c 100644
a
|
b
|
def raises_template_does_not_exist(request):
|
119 | 119 | |
120 | 120 | def send_log(request, exc_info): |
121 | 121 | logger = getLogger('django.request') |
| 122 | logger.propagate = False |
122 | 123 | # The default logging config has a logging filter to ensure admin emails are |
123 | 124 | # only sent with DEBUG=False, but since someone might choose to remove that |
124 | 125 | # filter, we still want to be able to test the behavior of error emails |
… |
… |
class Klass(object):
|
227 | 228 | return technical_500_response(request, *exc_info) |
228 | 229 | |
229 | 230 | def sensitive_method_view(request): |
230 | | return Klass().method(request) |
231 | | No newline at end of file |
| 231 | return Klass().method(request) |