Merge lp:~mars/launchpad/add-profiling-feature-flag into lp:launchpad
- add-profiling-feature-flag
- Merge into devel
Proposed by
Māris Fogels
Status: | Work in progress | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~mars/launchpad/add-profiling-feature-flag | ||||
Merge into: | lp:launchpad | ||||
Prerequisite: | lp:~mars/launchpad/feature-flag-fixture | ||||
Diff against target: |
408 lines (+88/-51) 3 files modified
lib/canonical/launchpad/doc/profiling.txt (+21/-5) lib/lp/services/profile/profile.py (+13/-2) lib/lp/services/profile/tests.py (+54/-44) |
||||
To merge this branch: | bzr merge lp:~mars/launchpad/add-profiling-feature-flag | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Launchpad code reviewers | Pending | ||
Review via email: mp+39179@code.launchpad.net |
Commit message
Description of the change
Hi,
This branch changes our profiling code to use feature flags instead of config values. The code takes advantage of the new FeatureFixture, added in the prerequisite branch, to do the heavy lifting. Later we will be able to turn profiling on and off from the Launchpad UI.
To post a comment you must log in.
Unmerged revisions
- 11598. By Māris Fogels
-
Typo
- 11597. By Māris Fogels
-
Better comments
- 11596. By Māris Fogels
-
Merged feature-
flag-fixture into add-profiling- feature- flag. - 11595. By Māris Fogels
-
Merged feature-
flag-fixture into add-profiling- feature- flag. - 11594. By Māris Fogels
-
Merged feature-
flag-fixture into add-profiling- feature- flag. - 11593. By Māris Fogels
-
Merged in Graham's fixes for the feature flags helper setting None values. Added a test to verify the fix.
- 11592. By Māris Fogels
-
Merge from devel
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/launchpad/doc/profiling.txt' | |||
2 | --- lib/canonical/launchpad/doc/profiling.txt 2010-08-26 15:57:56 +0000 | |||
3 | +++ lib/canonical/launchpad/doc/profiling.txt 2010-10-22 20:36:24 +0000 | |||
4 | @@ -100,11 +100,10 @@ | |||
5 | 100 | 100 | ||
6 | 101 | The feature has two modes. | 101 | The feature has two modes. |
7 | 102 | 102 | ||
13 | 103 | - It can be configured to optionally profile requests. To turn this on, in | 103 | - It can be configured to optionally profile requests. To turn this on you |
14 | 104 | ``launchpad-lazr.conf`` (e.g., | 104 | must add a feature flag that sets the 'request_profiling' flag to 'on'. |
15 | 105 | ``configs/development/launchpad-lazr.conf``) , in the ``[profiling]`` | 105 | This flag can be set directly in the database or using bin/harness. See |
16 | 106 | section, set ``profiling_allowed: True``. As of this writing, this | 106 | https://dev.launchpad.net/LEP/FeatureFlags for the details. |
12 | 107 | is the default value for development. | ||
17 | 108 | 107 | ||
18 | 109 | Once it is turned on, you can insert /++profile++/ in the URL to get | 108 | Once it is turned on, you can insert /++profile++/ in the URL to get |
19 | 110 | basic instructions on how to use the feature. You use the | 109 | basic instructions on how to use the feature. You use the |
20 | @@ -123,6 +122,19 @@ | |||
21 | 123 | lp/services/profile is hooked up properly. This is intended to be a | 122 | lp/services/profile is hooked up properly. This is intended to be a |
22 | 124 | smoke test. The unit tests verify further functionality. | 123 | smoke test. The unit tests verify further functionality. |
23 | 125 | 124 | ||
24 | 125 | # XXX mars 2010-09-23 | ||
25 | 126 | # We will temporarily turn on the profiling feature so that this test | ||
26 | 127 | # still passes. Profiling used to be active for all developers, but the | ||
27 | 128 | # feature flags work has shut it off. This fixture can be removed once | ||
28 | 129 | # profiling for developers is active by default once again. | ||
29 | 130 | >>> from lp.services.features.testing import FeatureFixture | ||
30 | 131 | >>> fixture = FeatureFixture({'request_profiling': 'on'}) | ||
31 | 132 | >>> fixture.setUp() | ||
32 | 133 | |||
33 | 134 | >>> from lp.services.features import getFeatureFlag | ||
34 | 135 | >>> getFeatureFlag('request_profiling') | ||
35 | 136 | u'on' | ||
36 | 137 | |||
37 | 126 | >>> response = http('GET /++profile++ HTTP/1.0') | 138 | >>> response = http('GET /++profile++ HTTP/1.0') |
38 | 127 | >>> '<h1>Profiling Information</h1>' in response.getBody() | 139 | >>> '<h1>Profiling Information</h1>' in response.getBody() |
39 | 128 | True | 140 | True |
40 | @@ -214,3 +226,7 @@ | |||
41 | 214 | >>> shutil.rmtree(pagetests_profile_dir) | 226 | >>> shutil.rmtree(pagetests_profile_dir) |
42 | 215 | >>> shutil.rmtree(profile_dir) | 227 | >>> shutil.rmtree(profile_dir) |
43 | 216 | >>> old_config = config.pop('memory_profile') | 228 | >>> old_config = config.pop('memory_profile') |
44 | 229 | |||
45 | 230 | |||
46 | 231 | # Turn profiling off | ||
47 | 232 | >>> fixture.cleanUp() | ||
48 | 217 | 233 | ||
49 | === modified file 'lib/lp/services/profile/profile.py' | |||
50 | --- lib/lp/services/profile/profile.py 2010-08-27 14:20:28 +0000 | |||
51 | +++ lib/lp/services/profile/profile.py 2010-10-22 20:36:24 +0000 | |||
52 | @@ -30,12 +30,15 @@ | |||
53 | 30 | memory, | 30 | memory, |
54 | 31 | resident, | 31 | resident, |
55 | 32 | ) | 32 | ) |
56 | 33 | from lp.services import features | ||
57 | 33 | 34 | ||
58 | 34 | 35 | ||
59 | 35 | class ProfilingOops(Exception): | 36 | class ProfilingOops(Exception): |
60 | 36 | """Fake exception used to log OOPS information when profiling pages.""" | 37 | """Fake exception used to log OOPS information when profiling pages.""" |
61 | 37 | 38 | ||
62 | 38 | 39 | ||
63 | 40 | # This variable holds all of the data about an active profile run for the | ||
64 | 41 | # duration of the request. | ||
65 | 39 | _profilers = threading.local() | 42 | _profilers = threading.local() |
66 | 40 | 43 | ||
67 | 41 | 44 | ||
68 | @@ -46,8 +49,16 @@ | |||
69 | 46 | If profiling is enabled, start a profiler for this thread. If memory | 49 | If profiling is enabled, start a profiler for this thread. If memory |
70 | 47 | profiling is requested, save the VSS and RSS. | 50 | profiling is requested, save the VSS and RSS. |
71 | 48 | """ | 51 | """ |
73 | 49 | if not config.profiling.profiling_allowed: | 52 | if features.getFeatureFlag('request_profiling'): |
74 | 53 | # Set a flag so that the end_request hook knows it has some work to | ||
75 | 54 | # do. We can not use the feature flag itself to control our | ||
76 | 55 | # end_request event handlers because the handler that tears down the | ||
77 | 56 | # feature flags and the handler that ends the profiling run do not | ||
78 | 57 | # fire in a predictable order. | ||
79 | 58 | _profilers.active = True | ||
80 | 59 | else: | ||
81 | 50 | return | 60 | return |
82 | 61 | |||
83 | 51 | actions = get_desired_profile_actions(event.request) | 62 | actions = get_desired_profile_actions(event.request) |
84 | 52 | if config.profiling.profile_all_requests: | 63 | if config.profiling.profile_all_requests: |
85 | 53 | actions.add('log') | 64 | actions.add('log') |
86 | @@ -71,7 +82,7 @@ | |||
87 | 71 | @adapter(IEndRequestEvent) | 82 | @adapter(IEndRequestEvent) |
88 | 72 | def end_request(event): | 83 | def end_request(event): |
89 | 73 | """If profiling is turned on, save profile data for the request.""" | 84 | """If profiling is turned on, save profile data for the request.""" |
91 | 74 | if not config.profiling.profiling_allowed: | 85 | if not getattr(_profilers, 'active', False): |
92 | 75 | return | 86 | return |
93 | 76 | try: | 87 | try: |
94 | 77 | actions = _profilers.actions | 88 | actions = _profilers.actions |
95 | 78 | 89 | ||
96 | === modified file 'lib/lp/services/profile/tests.py' | |||
97 | --- lib/lp/services/profile/tests.py 2010-08-26 22:10:56 +0000 | |||
98 | +++ lib/lp/services/profile/tests.py 2010-10-22 20:36:24 +0000 | |||
99 | @@ -14,7 +14,6 @@ | |||
100 | 14 | import time | 14 | import time |
101 | 15 | import unittest | 15 | import unittest |
102 | 16 | 16 | ||
103 | 17 | from lp.testing import TestCase | ||
104 | 18 | from bzrlib.lsprof import BzrProfiler | 17 | from bzrlib.lsprof import BzrProfiler |
105 | 19 | from zope.app.publication.interfaces import EndRequestEvent | 18 | from zope.app.publication.interfaces import EndRequestEvent |
106 | 20 | from zope.component import getSiteManager | 19 | from zope.component import getSiteManager |
107 | @@ -26,7 +25,11 @@ | |||
108 | 26 | ) | 25 | ) |
109 | 27 | from canonical.launchpad.webapp.servers import LaunchpadTestRequest | 26 | from canonical.launchpad.webapp.servers import LaunchpadTestRequest |
110 | 28 | from canonical.launchpad.webapp.interfaces import StartRequestEvent | 27 | from canonical.launchpad.webapp.interfaces import StartRequestEvent |
111 | 28 | from canonical.testing import layers | ||
112 | 29 | from lp.services.profile import profile | 29 | from lp.services.profile import profile |
113 | 30 | from lp.services.features.testing import FeatureFixture | ||
114 | 31 | from lp.testing import TestCase | ||
115 | 32 | |||
116 | 30 | 33 | ||
117 | 31 | EXAMPLE_HTML_START = '''\ | 34 | EXAMPLE_HTML_START = '''\ |
118 | 32 | <html><head><title>Random!</title></head> | 35 | <html><head><title>Random!</title></head> |
119 | @@ -43,6 +46,8 @@ | |||
120 | 43 | 46 | ||
121 | 44 | class BaseTest(TestCase): | 47 | class BaseTest(TestCase): |
122 | 45 | 48 | ||
123 | 49 | layer = layers.DatabaseFunctionalLayer | ||
124 | 50 | |||
125 | 46 | def _get_request(self, path='/'): | 51 | def _get_request(self, path='/'): |
126 | 47 | """Return a test request for the given path.""" | 52 | """Return a test request for the given path.""" |
127 | 48 | return LaunchpadTestRequest(PATH_INFO=path) | 53 | return LaunchpadTestRequest(PATH_INFO=path) |
128 | @@ -58,13 +63,19 @@ | |||
129 | 58 | getattr(profile._profilers, name, None), None, | 63 | getattr(profile._profilers, name, None), None, |
130 | 59 | 'Profiler state (%s) is dirty; %s.' % (name, message)) | 64 | 'Profiler state (%s) is dirty; %s.' % (name, message)) |
131 | 60 | 65 | ||
132 | 66 | def turnOnProfiling(self): | ||
133 | 67 | """Turn on the request_profiling feature flag.""" | ||
134 | 68 | self.useFixture(FeatureFixture({'request_profiling': 'on'})) | ||
135 | 69 | |||
136 | 70 | def turnOffProfiling(self): | ||
137 | 71 | """Turn off the request_profiling feature flag.""" | ||
138 | 72 | self.useFixture(FeatureFixture({'request_profiling': None})) | ||
139 | 73 | |||
140 | 61 | def pushProfilingConfig( | 74 | def pushProfilingConfig( |
143 | 62 | self, profiling_allowed='False', profile_all_requests='False', | 75 | self, profile_all_requests='False', memory_profile_log=''): |
142 | 63 | memory_profile_log=''): | ||
144 | 64 | """This is a convenience for setting profile configs.""" | 76 | """This is a convenience for setting profile configs.""" |
145 | 65 | self.pushConfig( | 77 | self.pushConfig( |
146 | 66 | 'profiling', | 78 | 'profiling', |
147 | 67 | profiling_allowed=profiling_allowed, | ||
148 | 68 | profile_all_requests=profile_all_requests, | 79 | profile_all_requests=profile_all_requests, |
149 | 69 | memory_profile_log=memory_profile_log) | 80 | memory_profile_log=memory_profile_log) |
150 | 70 | 81 | ||
151 | @@ -86,11 +97,12 @@ | |||
152 | 86 | delattr(profile._profilers, name) | 97 | delattr(profile._profilers, name) |
153 | 87 | TestCase.tearDown(self) | 98 | TestCase.tearDown(self) |
154 | 88 | 99 | ||
157 | 89 | def test_config_stops_profiling(self): | 100 | def test_feature_flag_stops_profiling(self): |
158 | 90 | """The ``profiling_allowed`` configuration should disable all | 101 | """The ``request_profiling`` feature flag should disable all |
159 | 91 | profiling, even if it is requested""" | 102 | profiling, even if it is requested""" |
160 | 103 | self.turnOffProfiling() | ||
161 | 92 | self.pushProfilingConfig( | 104 | self.pushProfilingConfig( |
163 | 93 | profiling_allowed='False', profile_all_requests='True', | 105 | profile_all_requests='True', |
164 | 94 | memory_profile_log='.') | 106 | memory_profile_log='.') |
165 | 95 | profile.start_request(self._get_start_event('/++profile++show,log')) | 107 | profile.start_request(self._get_start_event('/++profile++show,log')) |
166 | 96 | self.assertCleanProfilerState('config was ignored') | 108 | self.assertCleanProfilerState('config was ignored') |
167 | @@ -98,7 +110,7 @@ | |||
168 | 98 | def test_optional_profiling_without_marked_request_has_no_profile(self): | 110 | def test_optional_profiling_without_marked_request_has_no_profile(self): |
169 | 99 | """Even if profiling is allowed, it does not happen with a normal | 111 | """Even if profiling is allowed, it does not happen with a normal |
170 | 100 | request.""" | 112 | request.""" |
172 | 101 | self.pushProfilingConfig(profiling_allowed='True') | 113 | self.turnOnProfiling() |
173 | 102 | profile.start_request(self._get_start_event('/')) | 114 | profile.start_request(self._get_start_event('/')) |
174 | 103 | self.assertEqual(profile._profilers.actions, set()) | 115 | self.assertEqual(profile._profilers.actions, set()) |
175 | 104 | self.assertIs(getattr(profile._profilers, 'profiler', None), None) | 116 | self.assertIs(getattr(profile._profilers, 'profiler', None), None) |
176 | @@ -108,7 +120,7 @@ | |||
177 | 108 | def test_optional_profiling_with_show_request_starts_profiling(self): | 120 | def test_optional_profiling_with_show_request_starts_profiling(self): |
178 | 109 | """If profiling is allowed and a request with the "show" marker | 121 | """If profiling is allowed and a request with the "show" marker |
179 | 110 | URL segment is made, profiling starts.""" | 122 | URL segment is made, profiling starts.""" |
181 | 111 | self.pushProfilingConfig(profiling_allowed='True') | 123 | self.turnOnProfiling() |
182 | 112 | profile.start_request(self._get_start_event('/++profile++show/')) | 124 | profile.start_request(self._get_start_event('/++profile++show/')) |
183 | 113 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) | 125 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) |
184 | 114 | self.assertIs( | 126 | self.assertIs( |
185 | @@ -119,7 +131,7 @@ | |||
186 | 119 | def test_optional_profiling_with_log_request_starts_profiling(self): | 131 | def test_optional_profiling_with_log_request_starts_profiling(self): |
187 | 120 | """If profiling is allowed and a request with the "log" marker | 132 | """If profiling is allowed and a request with the "log" marker |
188 | 121 | URL segment is made, profiling starts.""" | 133 | URL segment is made, profiling starts.""" |
190 | 122 | self.pushProfilingConfig(profiling_allowed='True') | 134 | self.turnOnProfiling() |
191 | 123 | profile.start_request(self._get_start_event('/++profile++log/')) | 135 | profile.start_request(self._get_start_event('/++profile++log/')) |
192 | 124 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) | 136 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) |
193 | 125 | self.assertIs( | 137 | self.assertIs( |
194 | @@ -130,7 +142,7 @@ | |||
195 | 130 | def test_optional_profiling_with_combined_request_starts_profiling(self): | 142 | def test_optional_profiling_with_combined_request_starts_profiling(self): |
196 | 131 | """If profiling is allowed and a request with the "log" and | 143 | """If profiling is allowed and a request with the "log" and |
197 | 132 | "show" marker URL segment is made, profiling starts.""" | 144 | "show" marker URL segment is made, profiling starts.""" |
199 | 133 | self.pushProfilingConfig(profiling_allowed='True') | 145 | self.turnOnProfiling() |
200 | 134 | profile.start_request(self._get_start_event('/++profile++log,show/')) | 146 | profile.start_request(self._get_start_event('/++profile++log,show/')) |
201 | 135 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) | 147 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) |
202 | 136 | self.assertIs( | 148 | self.assertIs( |
203 | @@ -141,7 +153,7 @@ | |||
204 | 141 | def test_optional_profiling_with_reversed_request_starts_profiling(self): | 153 | def test_optional_profiling_with_reversed_request_starts_profiling(self): |
205 | 142 | """If profiling is allowed and a request with the "show" and | 154 | """If profiling is allowed and a request with the "show" and |
206 | 143 | "log" marker URL segment is made, profiling starts.""" | 155 | "log" marker URL segment is made, profiling starts.""" |
208 | 144 | self.pushProfilingConfig(profiling_allowed='True') | 156 | self.turnOnProfiling() |
209 | 145 | # The fact that this is reversed from the previous request is the only | 157 | # The fact that this is reversed from the previous request is the only |
210 | 146 | # difference from the previous test. Also, it doesn't have a | 158 | # difference from the previous test. Also, it doesn't have a |
211 | 147 | # trailing slash. :-P | 159 | # trailing slash. :-P |
212 | @@ -154,8 +166,8 @@ | |||
213 | 154 | 166 | ||
214 | 155 | def test_forced_profiling_registers_action(self): | 167 | def test_forced_profiling_registers_action(self): |
215 | 156 | """profile_all_requests should register as a log action""" | 168 | """profile_all_requests should register as a log action""" |
218 | 157 | self.pushProfilingConfig( | 169 | self.turnOnProfiling() |
219 | 158 | profiling_allowed='True', profile_all_requests='True') | 170 | self.pushProfilingConfig(profile_all_requests='True') |
220 | 159 | profile.start_request(self._get_start_event('/')) | 171 | profile.start_request(self._get_start_event('/')) |
221 | 160 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) | 172 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) |
222 | 161 | self.assertIs( | 173 | self.assertIs( |
223 | @@ -167,7 +179,7 @@ | |||
224 | 167 | """If profiling is allowed and a request with the marker URL segment | 179 | """If profiling is allowed and a request with the marker URL segment |
225 | 168 | is made incorrectly, profiling does not start and help is an action. | 180 | is made incorrectly, profiling does not start and help is an action. |
226 | 169 | """ | 181 | """ |
228 | 170 | self.pushProfilingConfig(profiling_allowed='True') | 182 | self.turnOnProfiling() |
229 | 171 | profile.start_request(self._get_start_event('/++profile++/')) | 183 | profile.start_request(self._get_start_event('/++profile++/')) |
230 | 172 | self.assertIs(getattr(profile._profilers, 'profiler', None), None) | 184 | self.assertIs(getattr(profile._profilers, 'profiler', None), None) |
231 | 173 | self.assertIs( | 185 | self.assertIs( |
232 | @@ -179,8 +191,8 @@ | |||
233 | 179 | """If profiling is forced and a request with the marker URL segment | 191 | """If profiling is forced and a request with the marker URL segment |
234 | 180 | is made incorrectly, profiling starts and help is an action. | 192 | is made incorrectly, profiling starts and help is an action. |
235 | 181 | """ | 193 | """ |
238 | 182 | self.pushProfilingConfig( | 194 | self.turnOnProfiling() |
239 | 183 | profiling_allowed='True', profile_all_requests='True') | 195 | self.pushProfilingConfig(profile_all_requests='True') |
240 | 184 | profile.start_request(self._get_start_event('/++profile++/')) | 196 | profile.start_request(self._get_start_event('/++profile++/')) |
241 | 185 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) | 197 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) |
242 | 186 | self.assertIs( | 198 | self.assertIs( |
243 | @@ -189,8 +201,8 @@ | |||
244 | 189 | self.assertEquals(profile._profilers.actions, set(('help', 'log'))) | 201 | self.assertEquals(profile._profilers.actions, set(('help', 'log'))) |
245 | 190 | 202 | ||
246 | 191 | def test_memory_profile_start(self): | 203 | def test_memory_profile_start(self): |
249 | 192 | self.pushProfilingConfig( | 204 | self.turnOnProfiling() |
250 | 193 | profiling_allowed='True', memory_profile_log='.') | 205 | self.pushProfilingConfig(memory_profile_log='.') |
251 | 194 | profile.start_request(self._get_start_event('/')) | 206 | profile.start_request(self._get_start_event('/')) |
252 | 195 | self.assertIs(getattr(profile._profilers, 'profiler', None), None) | 207 | self.assertIs(getattr(profile._profilers, 'profiler', None), None) |
253 | 196 | self.assertIsInstance(profile._profilers.memory_profile_start, tuple) | 208 | self.assertIsInstance(profile._profilers.memory_profile_start, tuple) |
254 | @@ -198,8 +210,8 @@ | |||
255 | 198 | self.assertEqual(profile._profilers.actions, set()) | 210 | self.assertEqual(profile._profilers.actions, set()) |
256 | 199 | 211 | ||
257 | 200 | def test_combo_memory_and_profile_start(self): | 212 | def test_combo_memory_and_profile_start(self): |
260 | 201 | self.pushProfilingConfig( | 213 | self.turnOnProfiling() |
261 | 202 | profiling_allowed='True', memory_profile_log='.') | 214 | self.pushProfilingConfig(memory_profile_log='.') |
262 | 203 | profile.start_request(self._get_start_event('/++profile++show/')) | 215 | profile.start_request(self._get_start_event('/++profile++show/')) |
263 | 204 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) | 216 | self.assertIsInstance(profile._profilers.profiler, BzrProfiler) |
264 | 205 | self.assertIsInstance(profile._profilers.memory_profile_start, tuple) | 217 | self.assertIsInstance(profile._profilers.memory_profile_start, tuple) |
265 | @@ -267,10 +279,11 @@ | |||
266 | 267 | ######################################################################### | 279 | ######################################################################### |
267 | 268 | # Tests | 280 | # Tests |
268 | 269 | def test_config_stops_profiling(self): | 281 | def test_config_stops_profiling(self): |
270 | 270 | """The ``profiling_allowed`` configuration should disable all | 282 | """The ``request_profiling`` feature should disable all |
271 | 271 | profiling, even if it is requested""" | 283 | profiling, even if it is requested""" |
272 | 284 | self.turnOffProfiling() | ||
273 | 272 | self.pushProfilingConfig( | 285 | self.pushProfilingConfig( |
275 | 273 | profiling_allowed='False', profile_all_requests='True', | 286 | profile_all_requests='True', |
276 | 274 | memory_profile_log=self.memory_profile_log) | 287 | memory_profile_log=self.memory_profile_log) |
277 | 275 | request = self.endRequest('/++profile++show,log') | 288 | request = self.endRequest('/++profile++show,log') |
278 | 276 | self.assertIs(getattr(request, 'oops', None), None) | 289 | self.assertIs(getattr(request, 'oops', None), None) |
279 | @@ -282,7 +295,7 @@ | |||
280 | 282 | def test_optional_profiling_without_marked_request_has_no_profile(self): | 295 | def test_optional_profiling_without_marked_request_has_no_profile(self): |
281 | 283 | """Even if profiling is allowed, it does not happen with a normal | 296 | """Even if profiling is allowed, it does not happen with a normal |
282 | 284 | request.""" | 297 | request.""" |
284 | 285 | self.pushProfilingConfig(profiling_allowed='True') | 298 | self.turnOnProfiling() |
285 | 286 | request = self.endRequest('/') | 299 | request = self.endRequest('/') |
286 | 287 | self.assertIs(getattr(request, 'oops', None), None) | 300 | self.assertIs(getattr(request, 'oops', None), None) |
287 | 288 | self.assertEqual(self.getAddedResponse(request), '') | 301 | self.assertEqual(self.getAddedResponse(request), '') |
288 | @@ -293,7 +306,7 @@ | |||
289 | 293 | def test_optional_profiling_with_show_request_profiles(self): | 306 | def test_optional_profiling_with_show_request_profiles(self): |
290 | 294 | """If profiling is allowed and a request with the "show" marker | 307 | """If profiling is allowed and a request with the "show" marker |
291 | 295 | URL segment is made, profiling starts.""" | 308 | URL segment is made, profiling starts.""" |
293 | 296 | self.pushProfilingConfig(profiling_allowed='True') | 309 | self.turnOnProfiling() |
294 | 297 | request = self.endRequest('/++profile++show/') | 310 | request = self.endRequest('/++profile++show/') |
295 | 298 | self.assertIsInstance(request.oops, ErrorReport) | 311 | self.assertIsInstance(request.oops, ErrorReport) |
296 | 299 | self.assertIn('Top Inline Time', self.getAddedResponse(request)) | 312 | self.assertIn('Top Inline Time', self.getAddedResponse(request)) |
297 | @@ -304,7 +317,7 @@ | |||
298 | 304 | def test_optional_profiling_with_log_request_profiles(self): | 317 | def test_optional_profiling_with_log_request_profiles(self): |
299 | 305 | """If profiling is allowed and a request with the "log" marker | 318 | """If profiling is allowed and a request with the "log" marker |
300 | 306 | URL segment is made, profiling starts.""" | 319 | URL segment is made, profiling starts.""" |
302 | 307 | self.pushProfilingConfig(profiling_allowed='True') | 320 | self.turnOnProfiling() |
303 | 308 | request = self.endRequest('/++profile++log/') | 321 | request = self.endRequest('/++profile++log/') |
304 | 309 | self.assertIsInstance(request.oops, ErrorReport) | 322 | self.assertIsInstance(request.oops, ErrorReport) |
305 | 310 | response = self.getAddedResponse(request) | 323 | response = self.getAddedResponse(request) |
306 | @@ -319,7 +332,7 @@ | |||
307 | 319 | def test_optional_profiling_with_combined_request_profiles(self): | 332 | def test_optional_profiling_with_combined_request_profiles(self): |
308 | 320 | """If profiling is allowed and a request with the "log" and | 333 | """If profiling is allowed and a request with the "log" and |
309 | 321 | "show" marker URL segment is made, profiling starts.""" | 334 | "show" marker URL segment is made, profiling starts.""" |
311 | 322 | self.pushProfilingConfig(profiling_allowed='True') | 335 | self.turnOnProfiling() |
312 | 323 | request = self.endRequest('/++profile++log,show') | 336 | request = self.endRequest('/++profile++log,show') |
313 | 324 | self.assertIsInstance(request.oops, ErrorReport) | 337 | self.assertIsInstance(request.oops, ErrorReport) |
314 | 325 | response = self.getAddedResponse(request) | 338 | response = self.getAddedResponse(request) |
315 | @@ -333,8 +346,8 @@ | |||
316 | 333 | 346 | ||
317 | 334 | def test_forced_profiling_logs(self): | 347 | def test_forced_profiling_logs(self): |
318 | 335 | """profile_all_requests should register as a log action""" | 348 | """profile_all_requests should register as a log action""" |
321 | 336 | self.pushProfilingConfig( | 349 | self.turnOnProfiling() |
322 | 337 | profiling_allowed='True', profile_all_requests='True') | 350 | self.pushProfilingConfig(profile_all_requests='True') |
323 | 338 | request = self.endRequest('/') | 351 | request = self.endRequest('/') |
324 | 339 | self.assertIsInstance(request.oops, ErrorReport) | 352 | self.assertIsInstance(request.oops, ErrorReport) |
325 | 340 | response = self.getAddedResponse(request) | 353 | response = self.getAddedResponse(request) |
326 | @@ -351,7 +364,7 @@ | |||
327 | 351 | """If profiling is allowed and a request with the marker URL segment | 364 | """If profiling is allowed and a request with the marker URL segment |
328 | 352 | is made incorrectly, profiling does not start and help is an action. | 365 | is made incorrectly, profiling does not start and help is an action. |
329 | 353 | """ | 366 | """ |
331 | 354 | self.pushProfilingConfig(profiling_allowed='True') | 367 | self.turnOnProfiling() |
332 | 355 | request = self.endRequest('/++profile++') | 368 | request = self.endRequest('/++profile++') |
333 | 356 | self.assertIs(getattr(request, 'oops', None), None) | 369 | self.assertIs(getattr(request, 'oops', None), None) |
334 | 357 | response = self.getAddedResponse(request) | 370 | response = self.getAddedResponse(request) |
335 | @@ -365,8 +378,8 @@ | |||
336 | 365 | """If profiling is forced and a request with the marker URL segment | 378 | """If profiling is forced and a request with the marker URL segment |
337 | 366 | is made incorrectly, profiling starts and help is an action. | 379 | is made incorrectly, profiling starts and help is an action. |
338 | 367 | """ | 380 | """ |
341 | 368 | self.pushProfilingConfig( | 381 | self.turnOnProfiling() |
342 | 369 | profiling_allowed='True', profile_all_requests='True') | 382 | self.pushProfilingConfig(profile_all_requests='True') |
343 | 370 | request = self.endRequest('/++profile++') | 383 | request = self.endRequest('/++profile++') |
344 | 371 | self.assertIsInstance(request.oops, ErrorReport) | 384 | self.assertIsInstance(request.oops, ErrorReport) |
345 | 372 | response = self.getAddedResponse(request) | 385 | response = self.getAddedResponse(request) |
346 | @@ -382,9 +395,8 @@ | |||
347 | 382 | 395 | ||
348 | 383 | def test_memory_profile(self): | 396 | def test_memory_profile(self): |
349 | 384 | "Does the memory profile work?" | 397 | "Does the memory profile work?" |
353 | 385 | self.pushProfilingConfig( | 398 | self.turnOnProfiling() |
354 | 386 | profiling_allowed='True', | 399 | self.pushProfilingConfig(memory_profile_log=self.memory_profile_log) |
352 | 387 | memory_profile_log=self.memory_profile_log) | ||
355 | 388 | request = self.endRequest('/') | 400 | request = self.endRequest('/') |
356 | 389 | self.assertIs(getattr(request, 'oops', None), None) | 401 | self.assertIs(getattr(request, 'oops', None), None) |
357 | 390 | self.assertEqual(self.getAddedResponse(request), '') | 402 | self.assertEqual(self.getAddedResponse(request), '') |
358 | @@ -400,9 +412,8 @@ | |||
359 | 400 | 412 | ||
360 | 401 | def test_memory_profile_with_non_defaults(self): | 413 | def test_memory_profile_with_non_defaults(self): |
361 | 402 | "Does the memory profile work with an oops and pageid?" | 414 | "Does the memory profile work with an oops and pageid?" |
365 | 403 | self.pushProfilingConfig( | 415 | self.turnOnProfiling() |
366 | 404 | profiling_allowed='True', | 416 | self.pushProfilingConfig(memory_profile_log=self.memory_profile_log) |
364 | 405 | memory_profile_log=self.memory_profile_log) | ||
367 | 406 | request = self.endRequest('/++profile++show/no-such-file', | 417 | request = self.endRequest('/++profile++show/no-such-file', |
368 | 407 | KeyError(), pageid='Foo') | 418 | KeyError(), pageid='Foo') |
369 | 408 | log = self.getMemoryLog() | 419 | log = self.getMemoryLog() |
370 | @@ -413,9 +424,8 @@ | |||
371 | 413 | self.assertCleanProfilerState() | 424 | self.assertCleanProfilerState() |
372 | 414 | 425 | ||
373 | 415 | def test_combo_memory_and_profile(self): | 426 | def test_combo_memory_and_profile(self): |
377 | 416 | self.pushProfilingConfig( | 427 | self.turnOnProfiling() |
378 | 417 | profiling_allowed='True', | 428 | self.pushProfilingConfig(memory_profile_log=self.memory_profile_log) |
376 | 418 | memory_profile_log=self.memory_profile_log) | ||
379 | 419 | request = self.endRequest('/++profile++show/') | 429 | request = self.endRequest('/++profile++show/') |
380 | 420 | self.assertIsInstance(request.oops, ErrorReport) | 430 | self.assertIsInstance(request.oops, ErrorReport) |
381 | 421 | self.assertIn('Top Inline Time', self.getAddedResponse(request)) | 431 | self.assertIn('Top Inline Time', self.getAddedResponse(request)) |
382 | @@ -424,7 +434,7 @@ | |||
383 | 424 | self.assertCleanProfilerState() | 434 | self.assertCleanProfilerState() |
384 | 425 | 435 | ||
385 | 426 | def test_profiling_oops_is_informational(self): | 436 | def test_profiling_oops_is_informational(self): |
387 | 427 | self.pushProfilingConfig(profiling_allowed='True') | 437 | self.turnOnProfiling() |
388 | 428 | request = self.endRequest('/++profile++show/') | 438 | request = self.endRequest('/++profile++show/') |
389 | 429 | response = self.getAddedResponse(request) | 439 | response = self.getAddedResponse(request) |
390 | 430 | self.assertIsInstance(request.oops, ErrorReport) | 440 | self.assertIsInstance(request.oops, ErrorReport) |
391 | @@ -433,7 +443,7 @@ | |||
392 | 433 | self.assertCleanProfilerState() | 443 | self.assertCleanProfilerState() |
393 | 434 | 444 | ||
394 | 435 | def test_real_oops_trumps_profiling_oops(self): | 445 | def test_real_oops_trumps_profiling_oops(self): |
396 | 436 | self.pushProfilingConfig(profiling_allowed='True') | 446 | self.turnOnProfiling() |
397 | 437 | request = self.endRequest('/++profile++show/no-such-file', | 447 | request = self.endRequest('/++profile++show/no-such-file', |
398 | 438 | KeyError('foo')) | 448 | KeyError('foo')) |
399 | 439 | self.assertIsInstance(request.oops, ErrorReport) | 449 | self.assertIsInstance(request.oops, ErrorReport) |
400 | @@ -444,7 +454,7 @@ | |||
401 | 444 | self.assertCleanProfilerState() | 454 | self.assertCleanProfilerState() |
402 | 445 | 455 | ||
403 | 446 | def test_oopsid_is_in_profile_filename(self): | 456 | def test_oopsid_is_in_profile_filename(self): |
405 | 447 | self.pushProfilingConfig(profiling_allowed='True') | 457 | self.turnOnProfiling() |
406 | 448 | request = self.endRequest('/++profile++log/') | 458 | request = self.endRequest('/++profile++log/') |
407 | 449 | self.assertIn("-" + request.oopsid + "-", self.getProfilePaths()[0]) | 459 | self.assertIn("-" + request.oopsid + "-", self.getProfilePaths()[0]) |
408 | 450 | self.assertCleanProfilerState() | 460 | self.assertCleanProfilerState() |
Hi, we still need a config setting to control profiling because we do
not ever want it on in prod.
Here's what I think we need, for clarity:
C - config
F - flags
- on prod
C - allow_profiling False: no profiling, no how, no way
- no devel
C - allow_profiling true: profiling anytime
- on staging
C - allow_profiling True:
F - profiling on request by developers [use a team scope to id the developer]
F - profiling of all requests [use the default scope to turn it on
for all requests]
That is, the check for 'should we profile' is: allow_profiling and getFeatureFlag( 'profile' ) == 'on'
config.
-Rob