~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-05 16:24:32 UTC
  • mto: This revision was merged to the branch mainline in revision 13623.
  • Revision ID: gary.poster@canonical.com-20110805162432-qws460rvbghqmfsn
Make ++profile++ use standard page templates, not chameleon, to remove template compilation step in Makefile

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
import StringIO
14
14
 
15
15
from bzrlib.lsprof import BzrProfiler
16
 
from chameleon.zpt.template import PageTemplateFile
17
 
from zope.app.publication.interfaces import IBeforeTraverseEvent
 
16
from zope.pagetemplate.pagetemplatefile import PageTemplateFile
18
17
from zope.app.publication.interfaces import IEndRequestEvent
19
18
from zope.component import (
20
19
    adapter,
43
42
 
44
43
_profilers = threading.local()
45
44
 
 
45
 
46
46
def before_traverse(event):
47
 
    """Handle profiling when enabled via the profiling.enabled feature flag."""
48
 
    # This event is raised on each step of traversal so needs to be lightweight
49
 
    # and not assume that profiling has not started - but this is equally well
50
 
    # done in _maybe_profile so that function takes care of it. We have to use
51
 
    # this event (or add a new one) because we depend on the feature flags
52
 
    # system being configured and usable, and on the principal being known.
 
47
    "Handle profiling when enabled via the profiling.enabled feature flag."
 
48
    # This event is raised on each step of traversal so needs to be
 
49
    # lightweight and not assume that profiling has not started - but this is
 
50
    # equally well done in _maybe_profile so that function takes care of it.
 
51
    # We have to use this event (or add a new one) because we depend on the
 
52
    # feature flags system being configured and usable, and on the principal
 
53
    # being known.
53
54
    try:
54
55
        if getFeatureFlag('profiling.enabled'):
55
56
            _maybe_profile(event)
67
68
 
68
69
def _maybe_profile(event):
69
70
    """Setup profiling as requested.
70
 
    
 
71
 
71
72
    If profiling is enabled, start a profiler for this thread. If memory
72
73
    profiling is requested, save the VSS and RSS.
73
74
 
76
77
    try:
77
78
        if _profilers.profiling:
78
79
            # Already profiling - e.g. called in from both start_request and
79
 
            # before_traverse, or by successive before_traverse on one request.
 
80
            # before_traverse, or by successive before_traverse on one
 
81
            # request.
80
82
            return
81
83
    except AttributeError:
82
84
        # The first call in on a new thread cannot be profiling at the start.
119
121
    # Create a timestamp including milliseconds.
120
122
    now = datetime.fromtimestamp(da.get_request_start_time())
121
123
    timestamp = "%s.%d" % (
122
 
        now.strftime('%Y-%m-%d_%H:%M:%S'), int(now.microsecond/1000.0))
 
124
        now.strftime('%Y-%m-%d_%H:%M:%S'), int(now.microsecond / 1000.0))
123
125
    pageid = request._orig_env.get('launchpad.pageid', 'Unknown')
124
126
    oopsid = getattr(request, 'oopsid', None)
125
127
    content_type = request.response.getHeader('content-type')
130
132
        _major, _minor, content_type_params = parse(content_type)
131
133
        is_html = _major == 'text' and _minor == 'html'
132
134
    template_context = {
133
 
        'actions': actions,
 
135
        # Dicts are easier for tal expressions.
 
136
        'actions': dict((action, True) for action in actions),
134
137
        'always_log': config.profiling.profile_all_requests}
 
138
    dump_path = config.profiling.profile_dir
135
139
    if _profilers.profiler is not None:
136
140
        prof_stats = _profilers.profiler.stop()
137
141
        # Free some memory.
150
154
            filename = '%s-%s-%s-%s.prof' % (
151
155
                timestamp, pageid, oopsid,
152
156
                threading.currentThread().getName())
153
 
            dump_path = os.path.join(config.profiling.profile_dir, filename)
 
157
            dump_path = os.path.join(dump_path, filename)
154
158
            prof_stats.save(dump_path, format="callgrind")
155
 
            template_context['dump_path'] = os.path.abspath(dump_path)
156
159
        if is_html and 'show' in actions:
157
160
            # Generate raw OOPS results.
158
161
            f = StringIO.StringIO()
164
167
                f = StringIO.StringIO()
165
168
                prof_stats.pprint(file=f)
166
169
                template_context[name] = f.getvalue()
 
170
    template_context['dump_path'] = os.path.abspath(dump_path)
167
171
    if actions and is_html:
168
172
        # Hack the new HTML in at the end of the page.
169
173
        encoding = content_type_params.get('charset', 'utf-8')
170
 
        added_html = template.render(**template_context).encode(encoding)
 
174
        added_html = template(**template_context).encode(encoding)
171
175
        existing_html = request.response.consumeBody()
172
176
        e_start, e_close_body, e_end = existing_html.rpartition(
173
177
            '</body>')