~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/services/profile/profile.py

  • Committer: Gary Poster
  • Date: 2011-08-08 15:24:22 UTC
  • mto: This revision was merged to the branch mainline in revision 13632.
  • Revision ID: gary.poster@canonical.com-20110808152422-q265ar4k56nsnc8f
respond to review

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
    """Fake exception used to log OOPS information when profiling pages."""
44
44
 
45
45
 
46
 
class StdLibProfiler(BzrProfiler):
 
46
class PStatsProfiler(BzrProfiler):
47
47
    """This provides a wrapper around the standard library's profiler.
48
48
 
49
 
    It makes the BzrProfiler and the StdLibProfiler follow a similar API.
 
49
    It makes the BzrProfiler and the PStatsProfiler follow a similar API.
50
50
    It also makes them both honor the BzrProfiler's thread lock.
51
51
    """
52
52
 
80
80
            self.p.disable()
81
81
            p = self.p
82
82
            self.p = None
83
 
            return StdLibStats(p)
 
83
            return PStats(p)
84
84
        finally:
85
85
            self.__class__.profiler_lock.release()
86
86
 
87
87
 
88
 
class StdLibStats:
89
 
    """This emulates enough of the Bzr stats class to make it interoperable
90
 
    for our purposes."""
 
88
class PStats:
 
89
    """Emulate enough of the Bzr stats class for our needs."""
91
90
 
92
91
    _stats = None
93
92
 
107
106
        mapping = {
108
107
            'inlinetime': 'time',
109
108
            'totaltime': 'cumulative',
110
 
            'callcount': 'calls'
 
109
            'callcount': 'calls',
111
110
            }
112
111
        self.stats.sort_stats(mapping[name])
113
112
 
167
166
        pass
168
167
    actions = get_desired_profile_actions(event.request)
169
168
    if config.profiling.profile_all_requests:
170
 
        actions.add('log')
 
169
        actions.add('callgrind')
171
170
    _profilers.actions = actions
172
171
    _profilers.profiler = None
173
172
    _profilers.profiling = True
174
173
    if actions:
175
 
        if actions.difference(('help', 'stdlib')):
 
174
        if actions.difference(('help',)):
176
175
            # If this assertion has reason to fail, we'll need to add code
177
176
            # to try and stop the profiler before we delete it, in case it is
178
177
            # still running.
179
178
            assert getattr(_profilers, 'profiler', None) is None
180
 
            if 'stdlib' in actions:
181
 
                _profilers.profiler = StdLibProfiler()
182
 
            else:
 
179
            if 'pstats' in actions and 'callgrind' not in actions:
 
180
                _profilers.profiler = PStatsProfiler()
 
181
            else:  # 'callgrind' is the default, and wins in a conflict.
183
182
                _profilers.profiler = BzrProfiler()
184
183
            _profilers.profiler.start()
185
184
    if config.profiling.memory_profile_log:
235
234
            oopsid = oops.id
236
235
        else:
237
236
            oops = request.oops
238
 
        if 'log' in actions:
 
237
        if actions.intersection(('callgrind', 'pstats')):
239
238
            filename = '%s-%s-%s-%s' % (
240
239
                timestamp, pageid, oopsid,
241
240
                threading.currentThread().getName())
242
 
            if 'stdlib' in actions:
243
 
                filename += '.prof'
244
 
            else:
 
241
            if 'callgrind' in actions:
 
242
                # callgrind wins in a conflict between it and pstats, as
 
243
                # documented in the help.
245
244
                # The Bzr stats class looks at the filename to know to use
246
245
                # callgrind syntax.
247
246
                filename = 'callgrind.out.' + filename
 
247
            else:
 
248
                filename += '.prof'
248
249
            dump_path = os.path.join(dump_path, filename)
249
250
            prof_stats.save(dump_path)
250
251
            template_context['dump_path'] = os.path.abspath(dump_path)
313
314
                action for action in (
314
315
                    item.strip().lower() for item in actions.split(','))
315
316
                if action)
316
 
            result.intersection_update(('log', 'show', 'stdlib'))
317
 
            if not result.difference(('stdlib',)):
 
317
            # 'log' is backwards compatible for 'callgrind'
 
318
            result.intersection_update(('log', 'callgrind', 'show', 'pstats'))
 
319
            if 'log' in result:
 
320
                result.remove('log')
 
321
                if 'pstats' not in result:
 
322
                    result.add('callgrind')
 
323
            if not result:
318
324
                result.add('help')
319
325
    return result
320
326