Merge lp:~rvb/maas/fix-loggers into lp:~maas-committers/maas/trunk

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 1660
Proposed branch: lp:~rvb/maas/fix-loggers
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 239 lines (+48/-58)
5 files modified
src/maasserver/forms_settings.py (+0/-16)
src/maasserver/middleware.py (+19/-5)
src/maasserver/models/config.py (+0/-3)
src/maasserver/tests/test_forms_settings.py (+0/-14)
src/maasserver/tests/test_middleware.py (+29/-20)
To merge this branch: bzr merge lp:~rvb/maas/fix-loggers
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+189114@code.launchpad.net

Commit message

Fix the DebuggingLoggerMiddleware. Remove the custom response_log_debug/request_log_debug config items and integrate DebuggingLoggerMiddleware with the standard logging system.

Description of the change

This branch does 3 things:
- it fixes bug 1227543.
- it fixes bug 1227558.
- it refactors the DebuggingLoggerMiddleware to integrate it with the standard logging system instead of using custom config items for enabling/disabling the debug output.

At first, I wanted to do this in two steps but Gavin "convinced" me to do otherwise and to do all in one branch. Anyway, the diff is not really big so I hope you won't mind.

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

Lovely :)

review: Approve
Revision history for this message
Julian Edwards (julian-edwards) wrote :

On 04/10/13 01:26, Raphaël Badin wrote:
> - it refactors the DebuggingLoggerMiddleware to integrate it with the standard logging system instead of using custom config items for enabling/disabling the debug output.

How does that now allow us to use an API call to turn the debug logging
on and off?

If you removed that functionality, please put it back!

Revision history for this message
Raphaël Badin (rvb) wrote :

> How does that now allow us to use an API call to turn the debug logging
> on and off?

It's not there anymore, but now it uses what the rest of the code is using: the log level defined in MAAS' configuration file.

> If you removed that functionality, please put it back!

If we want this (as opposed to just doing [0]), then I think we should add an API call to change the log level.

[0]

- edit /etc/maas/maas_config to change the log level
- sudo service apache2 reload

Revision history for this message
Julian Edwards (julian-edwards) wrote :

On 08/10/13 17:19, Raphaël Badin wrote:
>> How does that now allow us to use an API call to turn the debug logging
>> on and off?
>
> It's not there anymore, but now it uses what the rest of the code is using: the log level defined in MAAS' configuration file.
>
>> If you removed that functionality, please put it back!
>
> If we want this (as opposed to just doing [0]), then I think we should add an API call to change the log level.
>
> [0]
>
> - edit /etc/maas/maas_config to change the log level
> - sudo service apache2 reload
>
>

Ok this needs fixing then. There are a few things I dislike:

 * editing configs
 * restarting services
 * having to configure files and restart *every appserver instance* on a
multi appserver installation

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/forms_settings.py'
2--- src/maasserver/forms_settings.py 2013-09-19 13:34:46 +0000
3+++ src/maasserver/forms_settings.py 2013-10-03 15:20:34 +0000
4@@ -190,22 +190,6 @@
5 'invalid_choice': INVALID_DISTRO_SERIES_MESSAGE},
6 }
7 },
8- 'request_log_debug': {
9- 'default': False,
10- 'form': forms.BooleanField,
11- 'form_kwargs': {
12- 'label': "Log the requests information (debug option)",
13- 'required': False,
14- }
15- },
16- 'response_log_debug': {
17- 'default': False,
18- 'form': forms.BooleanField,
19- 'form_kwargs': {
20- 'label': "Log the responses information (debug option)",
21- 'required': False,
22- }
23- },
24 }
25
26
27
28=== modified file 'src/maasserver/middleware.py'
29--- src/maasserver/middleware.py 2013-09-06 07:52:39 +0000
30+++ src/maasserver/middleware.py 2013-10-03 15:20:34 +0000
31@@ -23,6 +23,7 @@
32 )
33 import httplib
34 import json
35+import logging
36 import re
37
38 from django.conf import settings
39@@ -38,13 +39,13 @@
40 HttpResponseForbidden,
41 HttpResponseRedirect,
42 )
43+from django.http.request import build_request_repr
44 from django.utils.http import urlquote_plus
45 from maasserver import logger
46 from maasserver.exceptions import (
47 ExternalComponentException,
48 MAASAPIException,
49 )
50-from maasserver.models import Config
51
52
53 def get_relative_path(path):
54@@ -217,15 +218,28 @@
55
56 class DebuggingLoggerMiddleware:
57
58+ log_level = logging.DEBUG
59+
60 def process_request(self, request):
61- if Config.objects.get_config("request_log_debug"):
62+ if logger.isEnabledFor(self.log_level):
63 header = " Request dump ".center(79, "#")
64- logger.info("%s\n%r\n%s", header, request, request.content)
65+ logger.log(
66+ self.log_level,
67+ "%s\n%s", header, build_request_repr(request))
68 return None # Allow request processing to continue unabated.
69
70 def process_response(self, request, response):
71- if Config.objects.get_config("response_log_debug"):
72+ if logger.isEnabledFor(self.log_level):
73 header = " Response dump ".center(79, "#")
74 content = getattr(response, "content", "{no content}")
75- logger.info("%s\n%r\n%s", header, response, content)
76+ try:
77+ decoded_content = content.decode('utf-8')
78+ except UnicodeDecodeError:
79+ logger.log(
80+ self.log_level,
81+ "%s\n%s", header, "** non-utf-8 (binary?) content **")
82+ else:
83+ logger.log(
84+ self.log_level,
85+ "%s\n%s", header, decoded_content)
86 return response # Return response unaltered.
87
88=== modified file 'src/maasserver/models/config.py'
89--- src/maasserver/models/config.py 2013-08-27 07:49:11 +0000
90+++ src/maasserver/models/config.py 2013-10-03 15:20:34 +0000
91@@ -54,9 +54,6 @@
92 'default_distro_series': DISTRO_SERIES.precise,
93 'commissioning_distro_series': DISTRO_SERIES.precise,
94 'http_proxy': None,
95- # Miscellaneous configuration.
96- 'request_log_debug': False,
97- 'response_log_debug': False,
98 ## /settings
99 }
100
101
102=== modified file 'src/maasserver/tests/test_forms_settings.py'
103--- src/maasserver/tests/test_forms_settings.py 2013-09-19 13:34:46 +0000
104+++ src/maasserver/tests/test_forms_settings.py 2013-10-03 15:20:34 +0000
105@@ -50,20 +50,6 @@
106 self.assertEqual(
107 {'maas_name': maas_name}, form.initial)
108
109- def test_request_log_debug(self):
110- form = get_config_form('request_log_debug')
111- self.assertItemsEqual(['request_log_debug'], form.fields)
112- self.assertEqual(
113- forms.BooleanField,
114- form.fields['request_log_debug'].__class__)
115-
116- def test_response_log_debug(self):
117- form = get_config_form('response_log_debug')
118- self.assertItemsEqual(['response_log_debug'], form.fields)
119- self.assertEqual(
120- forms.BooleanField,
121- form.fields['response_log_debug'].__class__)
122-
123
124 class TestGetConfigDoc(MAASServerTestCase):
125
126
127=== modified file 'src/maasserver/tests/test_middleware.py'
128--- src/maasserver/tests/test_middleware.py 2013-09-11 08:13:20 +0000
129+++ src/maasserver/tests/test_middleware.py 2013-10-03 15:20:34 +0000
130@@ -22,6 +22,7 @@
131 ValidationError,
132 )
133 from django.http import HttpResponse
134+from django.http.request import build_request_repr
135 from django.test.client import RequestFactory
136 import maasserver
137 from maasserver.exceptions import (
138@@ -37,13 +38,13 @@
139 ExceptionLoggerMiddleware,
140 ExceptionMiddleware,
141 )
142-from maasserver.models import Config
143 from maasserver.testing import extract_redirect
144 from maasserver.testing.factory import factory
145 from maasserver.testing.testcase import (
146 LoggedInTestCase,
147 MAASServerTestCase,
148 )
149+from maastesting.utils import sample_binary_data
150 from testtools.matchers import (
151 Contains,
152 FileContains,
153@@ -188,6 +189,7 @@
154 handler = logging.handlers.RotatingFileHandler(filename)
155 logger.addHandler(handler)
156 self.addCleanup(logger.removeHandler, handler)
157+ return logger
158
159
160 class ExceptionLoggerMiddlewareTest(LoggingTest):
161@@ -207,21 +209,18 @@
162 def setUp(self):
163 super(LoggingTest, self).setUp()
164 self.logfile = self.make_file(contents="")
165- self.set_up_logger(self.logfile)
166-
167- def test_that_default_request_log_config_is_false(self):
168- self.assertFalse(Config.objects.get_config("request_log_debug"))
169-
170- def test_that_default_response_log_config_is_false(self):
171- self.assertFalse(Config.objects.get_config("response_log_debug"))
172-
173- def test_debugging_logger_does_not_log_request_if_config_is_false(self):
174+ self.logger = self.set_up_logger(self.logfile)
175+
176+ def test_debugging_logger_does_not_log_request_if_info_level(self):
177+ self.logger.setLevel(logging.INFO)
178 request = fake_request("/api/1.0/nodes/")
179 DebuggingLoggerMiddleware().process_request(request)
180 self.assertThat(
181- self.logfile, Not(FileContains(matcher=Contains(repr(request)))))
182+ self.logfile,
183+ Not(FileContains(matcher=Contains(build_request_repr(request)))))
184
185- def test_debugging_logger_does_not_log_response_if_config_is_false(self):
186+ def test_debugging_logger_does_not_log_response_if_info_level(self):
187+ self.logger.setLevel(logging.INFO)
188 request = fake_request("/api/1.0/nodes/")
189 response = HttpResponse(
190 content="test content",
191@@ -229,20 +228,20 @@
192 mimetype=b"text/plain; charset=utf-8")
193 DebuggingLoggerMiddleware().process_response(request, response)
194 self.assertThat(
195- self.logfile, Not(FileContains(matcher=Contains(repr(request)))))
196+ self.logfile,
197+ Not(FileContains(matcher=Contains(build_request_repr(request)))))
198
199 def test_debugging_logger_logs_request(self):
200- Config.objects.set_config("request_log_debug", True)
201+ self.logger.setLevel(logging.DEBUG)
202 request = fake_request("/api/1.0/nodes/")
203 request.content = "test content"
204 DebuggingLoggerMiddleware().process_request(request)
205 self.assertThat(
206- self.logfile, FileContains(matcher=Contains(repr(request))))
207- self.assertThat(
208- self.logfile, FileContains(matcher=Contains(request.content)))
209+ self.logfile,
210+ FileContains(matcher=Contains(build_request_repr(request))))
211
212 def test_debugging_logger_logs_response(self):
213- Config.objects.set_config("response_log_debug", True)
214+ self.logger.setLevel(logging.DEBUG)
215 request = fake_request("foo")
216 response = HttpResponse(
217 content="test content",
218@@ -250,10 +249,20 @@
219 mimetype=b"text/plain; charset=utf-8")
220 DebuggingLoggerMiddleware().process_response(request, response)
221 self.assertThat(
222- self.logfile, FileContains(matcher=Contains(repr(response))))
223- self.assertThat(
224 self.logfile, FileContains(matcher=Contains(response.content)))
225
226+ def test_debugging_logger_logs_binary_response(self):
227+ self.logger.setLevel(logging.DEBUG)
228+ request = fake_request("foo")
229+ response = HttpResponse(
230+ content=sample_binary_data,
231+ status=httplib.OK,
232+ mimetype=b"application/octet-stream")
233+ DebuggingLoggerMiddleware().process_response(request, response)
234+ self.assertThat(
235+ self.logfile,
236+ FileContains(matcher=Contains("non-utf-8 (binary?) content")))
237+
238
239 class ErrorsMiddlewareTest(LoggedInTestCase):
240