Merge lp:~gary/launchpad/bug838869 into lp:launchpad

Proposed by Gary Poster
Status: Merged
Approved by: Gary Poster
Approved revision: no longer in the source branch.
Merged at revision: 13857
Proposed branch: lp:~gary/launchpad/bug838869
Merge into: lp:launchpad
Diff against target: 613 lines (+439/-41)
4 files modified
lib/canonical/launchpad/webapp/adapter.py (+120/-37)
lib/canonical/launchpad/webapp/tests/test_statementtracer.py (+316/-0)
lib/lp/services/profile/profile.py (+2/-2)
lib/lp/services/profile/tests.py (+1/-2)
To merge this branch: bzr merge lp:~gary/launchpad/bug838869
Reviewer Review Type Date Requested Status
j.c.sackett (community) Approve
Review via email: mp+73695@code.launchpad.net

Commit message

[r=jcsackett][bug=838869] Add tests for Launchpad SQL logger; add a more surgical SQL logger for outside of a request than what we had before; and add the ability to conditionally request tracebacks in the SQL logger.

Description of the change

This branch does three things.

- It adds a helper for tracking queries piecemeal in tests and make harness, SQLLogger. This is different than the QueryCollector in lib/lp/testing/_webservice.py because it does not require a browser request to work. I use this in a branch stacked on this one, https://code.launchpad.net/~gary/launchpad/bug811447 , to check queries generated from a piece of model code.

- It adds the ability to conditionally collect stacktraces, and renames the associated function from `start_sql_traceback_logging` to `start_sql_logging`. I use this in a branch stacked on this one, https://code.launchpad.net/~gary/launchpad/bug838878 , to support ++profile++sqltrace conditionally generating stacktraces.

- It adds tests for the logger, which had not existed at all as far as I could find. I include tests for the functionality I added as well as existing functionality. This is bug 838869.

Lint is happy.

Reasonable QA will be to go to https://qastaging.launchpad.net/++profile++sqltrace and make sure it still generates a sql trace analysis; and run `make run LP_DEBUG_SQL=1` on a dev machine to make sure it still produces SQL.

Thank you.

To post a comment you must log in.
Revision history for this message
j.c.sackett (jcsackett) wrote :

Gary, this looks good.

review: Approve
Revision history for this message
Robert Collins (lifeless) wrote :

There was/is a non browser query collector in testing/. This may be
duplicative.

On 3/09/2011 4:34 AM, <email address hidden> wrote:

The proposal to merge lp:~gary/launchpad/bug838869 into lp:launchpad has
been updated.

   Status: Approved => Merged

For more details, see:
https://code.launchpad.net/~gary/launchpad/bug838869/+merge/73695

--
https://code.launchpad.net/~gary/launchpad/bug838869/+merge/73695
Your team Launchpad code revie...

--
launchpad-reviews mailing list
<email address hidden>
https://lists.ubuntu.com/ma...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/webapp/adapter.py'
2--- lib/canonical/launchpad/webapp/adapter.py 2011-08-26 13:13:20 +0000
3+++ lib/canonical/launchpad/webapp/adapter.py 2011-09-02 16:31:40 +0000
4@@ -6,13 +6,16 @@
5
6 __metaclass__ = type
7
8+from functools import partial
9 import logging
10 import os
11 import re
12+import StringIO
13 import sys
14 import thread
15 import threading
16 from time import time
17+import traceback
18 import warnings
19
20 import psycopg2
21@@ -79,6 +82,7 @@
22 )
23 from lp.services.stacktrace import (
24 extract_stack,
25+ extract_tb,
26 print_list,
27 )
28
29@@ -91,9 +95,11 @@
30 'get_request_start_time',
31 'get_request_duration',
32 'get_store_name',
33+ 'print_queries',
34 'soft_timeout_expired',
35- 'start_sql_traceback_logging',
36- 'stop_sql_traceback_logging',
37+ 'SQLLogger',
38+ 'start_sql_logging',
39+ 'stop_sql_logging',
40 'StoreSelector',
41 ]
42
43@@ -202,7 +208,9 @@
44 warnings.warn('clear_request_started() called outside of a request',
45 stacklevel=2)
46 _local.request_start_time = None
47- _local.sql_trace = None
48+ _local.sql_logging = None
49+ _local.sql_logging_start = None
50+ _local.sql_logging_tracebacks_if = None
51 request = get_current_browser_request()
52 set_request_timeline(request, Timeline())
53 if getattr(_local, 'commit_logger', None) is not None:
54@@ -351,18 +359,75 @@
55 return True
56
57
58-def start_sql_traceback_logging():
59- """Set the sql traceback data logging for the current request."""
60- _local.sql_trace = []
61-
62-
63-def stop_sql_traceback_logging():
64- """Stop the sql traceback data logging and return the result."""
65- result = getattr(_local, 'sql_trace', None)
66- _local.sql_trace = None
67+def start_sql_logging(tracebacks_if=False):
68+ """Turn the sql data logging on."""
69+ if getattr(_local, 'sql_logging', None) is not None:
70+ warnings.warn('SQL logging already started')
71+ return
72+ _local.sql_logging_tracebacks_if = tracebacks_if
73+ _local.sql_logging = []
74+ _local.sql_logging_start = int(time() * 1000)
75+
76+
77+def stop_sql_logging():
78+ """Turn off the sql data logging and return the result."""
79+ result = getattr(_local, 'sql_logging', None)
80+ _local.sql_logging_tracebacks_if = None
81+ _local.sql_logging = None
82+ _local.sql_logging_start = None
83+ if result is None:
84+ warnings.warn('SQL logging not started')
85 return result
86
87
88+class SQLLogger:
89+
90+ def __init__(self, tracebacks_if=False):
91+ self.tracebacks_if = tracebacks_if
92+
93+ queries = None
94+
95+ def __enter__(self):
96+ self.queries = None
97+ start_sql_logging(self.tracebacks_if)
98+
99+ def __exit__(self, exc_type, exc_value, tb):
100+ self.queries = stop_sql_logging()
101+
102+ def __str__(self):
103+ if self.queries is None:
104+ return '(no queries)'
105+ else:
106+ out = StringIO.StringIO()
107+ print_queries(self.queries, file=out)
108+ return out.getvalue()
109+
110+
111+def print_queries(queries, file=None):
112+ if file is None:
113+ file = sys.stdout
114+ for query in queries:
115+ stack = query['stack']
116+ if stack is not None:
117+ exception = query['exception']
118+ if exception is not None:
119+ file.write(
120+ 'Error when determining whether to generate a '
121+ 'stacktrace.\n')
122+ file.write('Traceback (most recent call last):\n')
123+ print_list(stack, file)
124+ if exception is not None:
125+ lines = traceback.format_exception_only(*exception)
126+ file.write(' '.join(lines))
127+ file.write("." * 70 + "\n")
128+ sql = query['sql']
129+ if sql is not None:
130+ file.write('%d-%d@%s %s\n' % sql)
131+ else:
132+ file.write('(no SQL recorded)\n')
133+ file.write("-" * 70 + "\n")
134+
135+
136 # ---- Prevent database access in the main thread of the app server
137
138 class StormAccessFromMainThread(Exception):
139@@ -625,23 +690,14 @@
140 class LaunchpadStatementTracer:
141 """Storm tracer class to log executed statements."""
142
143+ _normalize_whitespace = partial(re.compile('\s+').sub, ' ')
144+
145 def __init__(self):
146 self._debug_sql = bool(os.environ.get('LP_DEBUG_SQL'))
147 self._debug_sql_extra = bool(os.environ.get('LP_DEBUG_SQL_EXTRA'))
148
149 def connection_raw_execute(self, connection, raw_cursor,
150 statement, params):
151- sql_trace = getattr(_local, 'sql_trace', None)
152- if sql_trace is not None or self._debug_sql_extra:
153- # Gather data for the [start|stop]_sql_traceback_logging
154- # feature, as exposed by ++profile++sqltrace, and/or for stderr,
155- # as exposed by LP_DEBUG_SQL_EXTRA.
156- stack = extract_stack()
157- if sql_trace is not None:
158- sql_trace.append(dict(stack=stack, sql=None))
159- if self._debug_sql_extra:
160- print_list(stack)
161- sys.stderr.write("." * 70 + "\n")
162 statement_to_log = statement
163 if params:
164 # There are some bind parameters so we want to insert them into
165@@ -656,18 +712,43 @@
166 param_strings = [repr(p) if isinstance(p, basestring) else p
167 for p in query_params]
168 statement_to_log = quoted_statement % tuple(param_strings)
169+ # Record traceback to log, if requested.
170+ print_traceback = self._debug_sql_extra
171+ log_sql = getattr(_local, 'sql_logging', None)
172+ log_traceback = False
173+ if log_sql is not None:
174+ log_sql.append(dict(stack=None, sql=None, exception=None))
175+ conditional = getattr(_local, 'sql_logging_tracebacks_if', None)
176+ if callable(conditional):
177+ try:
178+ log_traceback = conditional(
179+ self._normalize_whitespace(
180+ statement_to_log.strip()).upper())
181+ except (MemoryError, SystemExit, KeyboardInterrupt):
182+ raise
183+ except:
184+ exc_type, exc_value, tb = sys.exc_info()
185+ log_sql[-1]['exception'] = (exc_type, exc_value)
186+ log_sql[-1]['stack'] = extract_tb(tb)
187+ else:
188+ log_traceback = bool(conditional)
189+ if print_traceback or log_traceback:
190+ stack = extract_stack()
191+ if log_traceback:
192+ log_sql[-1]['stack'] = stack
193+ if print_traceback:
194+ print_list(stack)
195+ sys.stderr.write("." * 70 + "\n")
196 # store the last executed statement as an attribute on the current
197 # thread
198 threading.currentThread().lp_last_sql_statement = statement
199 request_starttime = getattr(_local, 'request_start_time', None)
200 if request_starttime is None:
201- if (sql_trace is not None or
202- self._debug_sql or
203- self._debug_sql_extra):
204+ if print_traceback or self._debug_sql or log_sql is not None:
205 # Stash some information for logging at the end of the
206- # request.
207+ # SQL execution.
208 connection._lp_statement_info = (
209- time(),
210+ int(time() * 1000),
211 'SQL-%s' % connection._database.name,
212 statement_to_log)
213 return
214@@ -682,24 +763,26 @@
215 # action may be None if the tracer was installed after the
216 # statement was submitted.
217 action.finish()
218- # Do data reporting for the [start|stop]_sql_traceback_logging
219- # feature, as exposed by ++profile++sqltrace, and/or for stderr,
220- # as exposed by LP_DEBUG_SQL_EXTRA and LP_DEBUG_SQL.
221- sql_trace = getattr(_local, 'sql_trace', None)
222- if sql_trace is not None or self._debug_sql or self._debug_sql_extra:
223+ log_sql = getattr(_local, 'sql_logging', None)
224+ if log_sql is not None or self._debug_sql or self._debug_sql_extra:
225 data = None
226 if action is not None:
227 data = action.logTuple()
228 else:
229 info = getattr(connection, '_lp_statement_info', None)
230 if info is not None:
231+ stop = int(time() * 1000)
232 start, dbname, statement = info
233+ logging_start = (
234+ getattr(_local, 'sql_logging_start', None) or start)
235 # Times are in milliseconds, to mirror actions.
236- duration = int((time() - start) * 1000)
237- data = (0, duration, dbname, statement)
238+ start = start - logging_start
239+ stop = stop - logging_start
240+ data = (start, stop, dbname, statement)
241+ connection._lp_statement_info = None
242 if data is not None:
243- if sql_trace and sql_trace[-1]['sql'] is None:
244- sql_trace[-1]['sql'] = data
245+ if log_sql and log_sql[-1]['sql'] is None:
246+ log_sql[-1]['sql'] = data
247 if self._debug_sql or self._debug_sql_extra:
248 sys.stderr.write('%d-%d@%s %s\n' % data)
249 sys.stderr.write("-" * 70 + "\n")
250
251=== added file 'lib/canonical/launchpad/webapp/tests/test_statementtracer.py'
252--- lib/canonical/launchpad/webapp/tests/test_statementtracer.py 1970-01-01 00:00:00 +0000
253+++ lib/canonical/launchpad/webapp/tests/test_statementtracer.py 2011-09-02 16:31:40 +0000
254@@ -0,0 +1,316 @@
255+# Copyright 2011 Canonical Ltd. This software is licensed under the
256+# GNU Affero General Public License version 3 (see the file LICENSE).
257+
258+"""Tests for the LaunchpadStatementTracer."""
259+
260+__metaclass__ = type
261+
262+from contextlib import contextmanager
263+import StringIO
264+import sys
265+
266+from lp.testing import (
267+ person_logged_in,
268+ TestCase,
269+ TestCaseWithFactory,
270+ )
271+from lp.services.osutils import override_environ
272+from lp.services.timeline.requesttimeline import get_request_timeline
273+from canonical.launchpad.webapp import adapter as da
274+from canonical.lazr.utils import get_current_browser_request
275+from canonical.testing import DatabaseFunctionalLayer
276+
277+
278+@contextmanager
279+def stdout():
280+ file = StringIO.StringIO()
281+ original = sys.stdout
282+ sys.stdout = file
283+ try:
284+ yield file
285+ finally:
286+ sys.stdout = original
287+
288+
289+@contextmanager
290+def stderr():
291+ file = StringIO.StringIO()
292+ original = sys.stderr
293+ sys.stderr = file
294+ try:
295+ yield file
296+ finally:
297+ sys.stderr = original
298+
299+
300+class StubTime:
301+
302+ time = 1000.0
303+
304+ def __call__(self):
305+ result = self.time
306+ self.time += 0.001
307+ return result
308+
309+
310+class StubConnection:
311+
312+ def __init__(self):
313+ self._database = type('StubDatabase', (), dict(name='stub-database'))
314+
315+
316+class TestLoggingOutsideOfRequest(TestCase):
317+
318+ def setUp(self):
319+ super(TestLoggingOutsideOfRequest, self).setUp()
320+ self.connection = StubConnection()
321+ original_time = da.time
322+ self.addCleanup(setattr, da, 'time', original_time)
323+ da.time = StubTime()
324+
325+ def execute(self, statement=None, params=None, **environ):
326+ with override_environ(**environ):
327+ tracer = da.LaunchpadStatementTracer()
328+ if statement is None:
329+ statement = 'SELECT * FROM bar WHERE bing = 42'
330+ tracer.connection_raw_execute(
331+ self.connection, None, statement, params)
332+ tracer.connection_raw_execute_success(
333+ self.connection, None, statement, params)
334+
335+ def test_no_logging(self):
336+ with stderr() as file:
337+ self.execute()
338+ self.assertEqual('', file.getvalue())
339+
340+ def test_stderr(self):
341+ with stderr() as file:
342+ self.execute(LP_DEBUG_SQL='1')
343+ self.assertEqual(
344+ '0-1@SQL-stub-database SELECT * FROM bar WHERE bing = 42\n' +
345+ "-" * 70 + "\n",
346+ file.getvalue())
347+
348+ def test_stderr_with_stacktrace(self):
349+ with stderr() as file:
350+ self.execute(LP_DEBUG_SQL_EXTRA='1')
351+ self.assertStartsWith(
352+ file.getvalue(),
353+ ' File "')
354+ self.assertEndsWith(
355+ file.getvalue(),
356+ "." * 70 + "\n" +
357+ '0-1@SQL-stub-database SELECT * FROM bar WHERE bing = 42\n' +
358+ "-" * 70 + "\n")
359+
360+ def test_data_logging(self):
361+ da.start_sql_logging()
362+ with stderr() as file:
363+ self.execute()
364+ self.assertEqual('', file.getvalue())
365+ result = da.stop_sql_logging()
366+ self.assertEqual(1, len(result))
367+ self.assertIs(None, result[0]['stack'])
368+ self.assertIs(None, result[0]['exception'])
369+ self.assertEqual(
370+ (1, 2, 'SQL-stub-database', 'SELECT * FROM bar WHERE bing = 42'),
371+ result[0]['sql'])
372+
373+ def test_data_logging_with_stacktrace(self):
374+ da.start_sql_logging(tracebacks_if=True)
375+ with stderr() as file:
376+ self.execute()
377+ self.assertEqual('', file.getvalue())
378+ result = da.stop_sql_logging()
379+ self.assertEqual(1, len(result))
380+ self.assertIsNot(None, result[0]['stack'])
381+ self.assertIs(None, result[0]['exception'])
382+ self.assertEqual(
383+ (1, 2, 'SQL-stub-database', 'SELECT * FROM bar WHERE bing = 42'),
384+ result[0]['sql'])
385+
386+ def test_data_logging_with_conditional_stacktrace(self):
387+ # Conditions must be normalized to uppercase.
388+ da.start_sql_logging(tracebacks_if=lambda sql: 'KUMQUAT' in sql)
389+ with stderr() as file:
390+ self.execute()
391+ self.execute(statement='SELECT * FROM kumquat WHERE bing = 42')
392+ self.assertEqual('', file.getvalue())
393+ result = da.stop_sql_logging()
394+ self.assertEqual(2, len(result))
395+ self.assertIs(None, result[0]['stack'])
396+ self.assertIsNot(None, result[1]['stack'])
397+
398+ def test_data_logging_with_conditional_stacktrace_normalized_whitespace(
399+ self):
400+ # The whitespace in the SQL is normalized
401+ da.start_sql_logging(
402+ tracebacks_if=lambda sql: 'FROM KUMQUAT WHERE' in sql)
403+ self.execute(
404+ statement='SELECT * FROM kumquat \nWHERE bing = 42')
405+ result = da.stop_sql_logging()
406+ self.assertEqual(1, len(result))
407+ self.assertIsNot(None, result[0]['stack'])
408+
409+ def test_data_logging_with_broken_conditional_stacktrace(self):
410+ error = ValueError('rutebega')
411+
412+ def ow(sql):
413+ raise error
414+ da.start_sql_logging(tracebacks_if=ow)
415+ with stderr() as file:
416+ self.execute()
417+ self.assertEqual('', file.getvalue())
418+ result = da.stop_sql_logging()
419+ self.assertEqual(1, len(result))
420+ self.assertIsNot(None, result[0]['stack'])
421+ self.assertEqual((ValueError, error), result[0]['exception'])
422+ self.assertEqual(
423+ (1, 2, 'SQL-stub-database', 'SELECT * FROM bar WHERE bing = 42'),
424+ result[0]['sql'])
425+
426+ def test_print_queries_with_tracebacks(self):
427+ da.start_sql_logging(tracebacks_if=True)
428+ self.execute()
429+ result = da.stop_sql_logging()
430+ with stdout() as file:
431+ da.print_queries(result)
432+ self.assertStartsWith(
433+ file.getvalue(),
434+ ' File "')
435+ self.assertEndsWith(
436+ file.getvalue(),
437+ "." * 70 + "\n" +
438+ '1-2@SQL-stub-database SELECT * FROM bar WHERE bing = 42\n' +
439+ "-" * 70 + "\n")
440+
441+ def test_print_queries_without_tracebacks(self):
442+ da.start_sql_logging()
443+ self.execute()
444+ result = da.stop_sql_logging()
445+ with stdout() as file:
446+ da.print_queries(result)
447+ self.assertEqual(
448+ '1-2@SQL-stub-database SELECT * FROM bar WHERE bing = 42\n' +
449+ "-" * 70 + "\n",
450+ file.getvalue())
451+
452+ def test_print_queries_with_exceptions(self):
453+ def ow(sql):
454+ raise ValueError('rutebega')
455+ da.start_sql_logging(tracebacks_if=ow)
456+ self.execute()
457+ result = da.stop_sql_logging()
458+ with stdout() as file:
459+ da.print_queries(result)
460+ self.assertStartsWith(
461+ file.getvalue(),
462+ 'Error when determining whether to generate a stacktrace.\n' +
463+ 'Traceback (most recent call last):\n' +
464+ ' File "')
465+ self.assertEndsWith(
466+ file.getvalue(),
467+ "ValueError: rutebega\n" +
468+ "." * 70 + "\n" +
469+ '1-2@SQL-stub-database SELECT * FROM bar WHERE bing = 42\n' +
470+ "-" * 70 + "\n")
471+
472+ def test_context_manager(self):
473+ logger = da.SQLLogger()
474+ with logger:
475+ self.execute()
476+ self.assertEqual(1, len(logger.queries))
477+ self.assertIs(None, logger.queries[0]['stack'])
478+ self.assertIs(None, logger.queries[0]['exception'])
479+ self.assertEqual(
480+ (1, 2, 'SQL-stub-database', 'SELECT * FROM bar WHERE bing = 42'),
481+ logger.queries[0]['sql'])
482+ with stdout() as file:
483+ result = str(logger)
484+ self.assertEqual('', file.getvalue())
485+ self.assertEqual(
486+ '1-2@SQL-stub-database SELECT * FROM bar WHERE bing = 42\n' +
487+ "-" * 70 + "\n",
488+ result)
489+
490+ def test_context_manager_with_stacktrace(self):
491+ logger = da.SQLLogger(tracebacks_if=True)
492+ with logger:
493+ self.execute()
494+ self.assertEqual(1, len(logger.queries))
495+ self.assertIsNot(None, logger.queries[0]['stack'])
496+
497+ def test_sql_parameters(self):
498+ logger = da.SQLLogger()
499+ with logger:
500+ self.execute(statement='SELECT * FROM bar WHERE bing = %s',
501+ params=(142,))
502+ self.assertEqual(
503+ (1, 2, 'SQL-stub-database', 'SELECT * FROM bar WHERE bing = 142'),
504+ logger.queries[0]['sql'])
505+
506+
507+class TestLoggingWithinRequest(TestCaseWithFactory):
508+ # When called with a request, the code uses the request timeline and
509+ # its action objects.
510+
511+ layer = DatabaseFunctionalLayer
512+
513+ def setUp(self):
514+ super(TestLoggingWithinRequest, self).setUp()
515+ self.connection = StubConnection()
516+ self.person = self.factory.makePerson()
517+ da.set_request_started(1000.0)
518+ self.addCleanup(da.clear_request_started)
519+
520+ def test_logger(self):
521+ tracer = da.LaunchpadStatementTracer()
522+ logger = da.SQLLogger()
523+ with person_logged_in(self.person):
524+ with logger:
525+ tracer.connection_raw_execute(
526+ self.connection, None,
527+ 'SELECT * FROM bar WHERE bing = 42', ())
528+ timeline = get_request_timeline(get_current_browser_request())
529+ action = timeline.actions[-1]
530+ self.assertEqual(
531+ 'SELECT * FROM bar WHERE bing = 42',
532+ action.detail)
533+ self.assertEqual('SQL-stub-database', action.category)
534+ self.assertIs(None, action.duration)
535+ # Now we change the detail to verify that the action is the
536+ # source of the final log.
537+ action.detail = 'SELECT * FROM surprise'
538+ tracer.connection_raw_execute_success(
539+ self.connection, None,
540+ 'SELECT * FROM bar WHERE bing = 42', ())
541+ self.assertIsNot(None, action.duration)
542+ self.assertEqual(
543+ 'SELECT * FROM surprise', logger.queries[0]['sql'][3])
544+
545+ def test_stderr(self):
546+ with override_environ(LP_DEBUG_SQL='1'):
547+ tracer = da.LaunchpadStatementTracer()
548+ with person_logged_in(self.person):
549+ with stderr() as file:
550+ tracer.connection_raw_execute(
551+ self.connection, None,
552+ 'SELECT * FROM bar WHERE bing = 42', ())
553+ timeline = get_request_timeline(get_current_browser_request())
554+ action = timeline.actions[-1]
555+ self.assertEqual(
556+ 'SELECT * FROM bar WHERE bing = 42',
557+ action.detail)
558+ self.assertEqual('SQL-stub-database', action.category)
559+ self.assertIs(None, action.duration)
560+ # Now we change the detail to verify that the action is the
561+ # source of the final log.
562+ action.detail = 'SELECT * FROM surprise'
563+ tracer.connection_raw_execute_success(
564+ self.connection, None,
565+ 'SELECT * FROM bar WHERE bing = 42', ())
566+ self.assertIsNot(None, action.duration)
567+ self.assertEndsWith(
568+ file.getvalue(),
569+ '@SQL-stub-database SELECT * FROM surprise\n' +
570+ "-" * 70 + "\n")
571
572=== modified file 'lib/lp/services/profile/profile.py'
573--- lib/lp/services/profile/profile.py 2011-08-24 17:24:38 +0000
574+++ lib/lp/services/profile/profile.py 2011-09-02 16:31:40 +0000
575@@ -213,7 +213,7 @@
576 actions.add('callgrind')
577 if actions:
578 if 'sqltrace' in actions:
579- da.start_sql_traceback_logging()
580+ da.start_sql_logging(tracebacks_if=True)
581 if 'show' in actions or actions.intersection(available_profilers):
582 _profilers.profiler = Profiler()
583 _profilers.profiler.start()
584@@ -346,7 +346,7 @@
585 del prof_stats
586 trace = None
587 if 'sqltrace' in actions:
588- trace = da.stop_sql_traceback_logging() or ()
589+ trace = da.stop_sql_logging() or ()
590 # The trace is a list of dicts, each with the keys "sql" and
591 # "stack". "sql" is a tuple of start time, stop time, database
592 # name (with a "SQL-" prefix), and sql statement. "stack" is a
593
594=== modified file 'lib/lp/services/profile/tests.py'
595--- lib/lp/services/profile/tests.py 2011-08-22 19:06:39 +0000
596+++ lib/lp/services/profile/tests.py 2011-09-02 16:31:40 +0000
597@@ -82,7 +82,6 @@
598 profile._profilers.actions = None
599 profile._profilers.memory_profile_start = None
600 profile._profilers.profiling = False
601- da.stop_sql_traceback_logging()
602 super(TestCleanupProfiler, self).tearDown()
603
604
605@@ -275,7 +274,7 @@
606 profile.start_request(self._get_start_event('/++profile++sqltrace/'))
607 self.assertIs(getattr(profile._profilers, 'profiler', None), None)
608 self.assertEquals(profile._profilers.actions, set(('sqltrace', )))
609- self.assertEqual([], da.stop_sql_traceback_logging())
610+ self.assertEqual([], da.stop_sql_logging())
611
612
613 class BaseRequestEndHandlerTest(BaseTest):