Loading...

Blog: Profiling a Trac request: trac-req.py

File trac-req.py, 2.8 KB (added by simon@…, 9 years ago)

Trac request script.

Line 
1""""
2Usage:
31. Configure request data + switches to suit needs
42. Run `python req-hotshot.py` to perform the profiling
5"""
6
7import os, sys
8import hotshot, hotshot.stats
9from StringIO import StringIO
10import tempfile
11
12from trac.web.api import Request
13from trac.env import open_environment
14from trac.perm import PermissionCache
15from trac.core import TracError
16from trac.web.main import _dispatch_request
17
18#############################
19### Request configuration ###
20#############################
21# Path to the Trac environment on disk
22#project_path = '/path/to/my_trac_project'
23project_path = ''
24# The Trac project-relative URL to call
25# url_project = '/timeline'
26url_project = ''
27# Whatever request arguments to pass along with the call
28# req_args = {'daysback': 90, 'wiki': 'on', 'format': 'rss'}
29req_args = {}
30username = 'osimons'
31req_method = 'GET'
32
33################
34### Switches ###
35################
36do_output_html = True
37do_output_debug_summary = True
38do_profile = True
39# First request may skew test as all code loads/compiles
40# Prefer a first dry-run so that profiled request is done on 'warm' code
41do_profile_second_request = True
42
43##################
44### Run / Code ###
45##################
46if not os.path.exists(os.path.join(project_path, 'VERSION')):
47    sys.exit("'project_path' variable must point to a valid Trac project.")
48url_prefix = '/trac' # whatever really
49environ = {
50    'REQUEST_METHOD': req_method,
51    'SERVER_NAME': 'example.org',
52    'SERVER_PORT': 80,
53    'REQUEST_URI': url_prefix + url_project,
54    'PATH_INFO': url_project,
55    'SCRIPT_NAME': url_prefix,
56    'wsgi.url_scheme': 'http',
57    'wsgi.input': StringIO(''),
58    'trac.env_path': project_path
59    }
60
61buf = StringIO()
62def start_response(status, outheaders=None, exc_info=None):
63    if do_output_debug_summary:
64        print "DEBUG - status: ", status
65        print "DEBUG - outheaders: ", outheaders
66        print "DEBUG - exc_info: ", exc_info
67        print
68    return buf.write
69
70req = Request(environ, start_response)
71myenv = open_environment(project_path)
72req.perm = PermissionCache(myenv, username)
73req.args.update(req_args)
74
75def send_error(cls, exec_info):
76    print exec_info
77
78def run():
79    _dispatch_request(req, myenv, send_error)
80
81if do_profile:
82    (fd, fname) = tempfile.mkstemp()
83    try:
84        if do_profile_second_request:
85            # First request to load/compile all code, making second reqest 'warm'
86            run()
87            buf.truncate(0)
88            req._outheaders = []
89        profile = hotshot.Profile(fname)
90        profile.runcall(run)
91        profile.close()
92        stats = hotshot.stats.load(fname)
93        stats.sort_stats('time', 'calls')
94        stats.print_stats()
95    finally:
96        os.remove(fname)
97
98if do_output_html:
99    if not do_profile:
100        # No profiling, so no request has yet been made
101        run()
102    print buf.getvalue().decode('utf-8')