This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Make profiling transparent and aggregatable.

If the config variable profile_directory is set, ProfilingMiddleware
will be added to the WSGI stack. The middleware will generate a file in
the specified directory on each request containing the contents of that
request's profile.
  • Loading branch information...
spladug authored and bsimpson63 committed Jul 23, 2012
1 parent 283c26e commit 416922673577a435da97ebacfba192e5d375516c
Showing with 18 additions and 27 deletions.
  1. +2 −0 r2/example.ini
  2. +16 −27 r2/r2/config/middleware.py
View
@@ -39,6 +39,8 @@ read_only_mode = false
allow_wiki_editing = true
# a modified read only mode used for cache shown during heavy load 503s
heavy_load_mode = false
+# directory to write cProfile stats dumps to (disabled if not set)
+profile_directory =
# a message placed in the infobar
announcement_message =
View
@@ -96,37 +96,25 @@ def error_mapper(code, message, environ, global_conf=None, **kw):
class ProfilingMiddleware(object):
- def __init__(self, app):
+ def __init__(self, app, directory):
self.app = app
+ self.directory = directory
def __call__(self, environ, start_response):
- query_params = urlparse.parse_qs(environ['QUERY_STRING'])
-
- if "profile" in query_params:
- import cProfile
+ import cProfile
- def fake_start_response(*args, **kwargs):
- pass
-
- try:
- tmpfile = tempfile.NamedTemporaryFile()
-
- cProfile.runctx("self.app(environ, fake_start_response)",
- globals(),
- locals(),
- tmpfile.name)
-
- tmpfile.seek(0)
+ try:
+ tmpfile = tempfile.NamedTemporaryFile(prefix='profile',
+ dir=self.directory,
+ delete=False)
- start_response('200 OK',
- [('Content-Type', 'application/octet-stream'),
- ('Content-Disposition',
- 'attachment; filename=profile.bin')])
- return tmpfile.read()
- finally:
- tmpfile.close()
+ profile = cProfile.Profile()
+ result = profile.runcall(self.app, environ, start_response)
+ profile.dump_stats(tmpfile.name)
- return self.app(environ, start_response)
+ return result
+ finally:
+ tmpfile.close()
class DomainMiddleware(object):
@@ -423,8 +411,9 @@ def make_app(global_conf, full_stack=True, **app_conf):
app = LimitUploadSize(app)
- if g.config['debug']:
- app = ProfilingMiddleware(app)
+ profile_directory = g.config.get('profile_directory')
+ if profile_directory:
+ app = ProfilingMiddleware(app, profile_directory)
app = DomainListingMiddleware(app)
app = SubredditMiddleware(app)

0 comments on commit 4169226

Please sign in to comment.