~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/support/werkzeug/contrib/profiler.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20080622211713-inlv5k4eifxckelr
ImportĀ upstreamĀ versionĀ 1.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
"""
3
 
    werkzeug.contrib.profiler
4
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~
5
 
 
6
 
    This module provides a simple WSGI profiler middleware for finding
7
 
    bottlenecks in web application.  It uses the :mod:`profile` or
8
 
    :mod:`cProfile` module to do the profiling and writes the stats to the
9
 
    stream provided (defaults to stderr).
10
 
 
11
 
    Example usage::
12
 
 
13
 
        from werkzeug.contrib.profiler import ProfilerMiddleware
14
 
        app = ProfilerMiddleware(app)
15
 
 
16
 
    :copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details.
17
 
    :license: BSD, see LICENSE for more details.
18
 
"""
19
 
import sys
20
 
try:
21
 
    try:
22
 
        from cProfile import Profile
23
 
    except ImportError:
24
 
        from profile import Profile
25
 
    from pstats import Stats
26
 
    available = True
27
 
except ImportError:
28
 
    available = False
29
 
 
30
 
 
31
 
class MergeStream(object):
32
 
    """An object that redirects `write` calls to multiple streams.
33
 
    Use this to log to both `sys.stdout` and a file::
34
 
 
35
 
        f = open('profiler.log', 'w')
36
 
        stream = MergeStream(sys.stdout, f)
37
 
        profiler = ProfilerMiddleware(app, stream)
38
 
    """
39
 
 
40
 
    def __init__(self, *streams):
41
 
        if not streams:
42
 
            raise TypeError('at least one stream must be given')
43
 
        self.streams = streams
44
 
 
45
 
    def write(self, data):
46
 
        for stream in self.streams:
47
 
            stream.write(data)
48
 
 
49
 
 
50
 
class ProfilerMiddleware(object):
51
 
    """Simple profiler middleware.  Wraps a WSGI application and profiles
52
 
    a request.  This intentionally buffers the response so that timings are
53
 
    more exact.
54
 
 
55
 
    For the exact meaning of `sort_by` and `restrictions` consult the
56
 
    :mod:`profile` documentation.
57
 
 
58
 
    :param app: the WSGI application to profile.
59
 
    :param stream: the stream for the profiled stats.  defaults to stderr.
60
 
    :param sort_by: a tuple of columns to sort the result by.
61
 
    :param restrictions: a tuple of profiling strictions.
62
 
    """
63
 
 
64
 
    def __init__(self, app, stream=None,
65
 
                 sort_by=('time', 'calls'), restrictions=()):
66
 
        if not available:
67
 
            raise RuntimeError('the profiler is not available because '
68
 
                               'profile or pstat is not installed.')
69
 
        self._app = app
70
 
        self._stream = stream or sys.stdout
71
 
        self._sort_by = sort_by
72
 
        self._restrictions = restrictions
73
 
 
74
 
    def __call__(self, environ, start_response):
75
 
        response_body = []
76
 
 
77
 
        def catching_start_response(status, headers, exc_info=None):
78
 
            start_response(status, headers, exc_info)
79
 
            return response_body.append
80
 
 
81
 
        def runapp():
82
 
            appiter = self._app(environ, catching_start_response)
83
 
            response_body.extend(appiter)
84
 
            if hasattr(appiter, 'close'):
85
 
                appiter.close()
86
 
 
87
 
        p = Profile()
88
 
        p.runcall(runapp)
89
 
        body = ''.join(response_body)
90
 
        stats = Stats(p)
91
 
        stats.sort_stats(*self._sort_by)
92
 
 
93
 
        self._stream.write('-' * 80)
94
 
        self._stream.write('\nPATH: %r\n' % environ.get('PATH_INFO'))
95
 
        stats.print_stats(*self._restrictions)
96
 
        self._stream.write('-' * 80 + '\n\n')
97
 
 
98
 
        return [body]
99
 
 
100
 
 
101
 
def make_action(app_factory, hostname='localhost', port=5000,
102
 
                threaded=False, processes=1, stream=None,
103
 
                sort_by=('time', 'calls'), restrictions=()):
104
 
    """Return a new callback for :mod:`werkzeug.script` that starts a local
105
 
    server with the profiler enabled::
106
 
 
107
 
        from werkzeug.contrib import profiler
108
 
        action_profile = profiler.make_action(make_app)
109
 
    """
110
 
    def action(hostname=('h', hostname), port=('p', port),
111
 
               threaded=threaded, processes=processes):
112
 
        """Start a new development server."""
113
 
        from werkzeug.serving import run_simple
114
 
        app = ProfilerMiddleware(app_factory(), stream, sort_by, restrictions)
115
 
        run_simple(hostname, port, app, False, None, threaded, processes)
116
 
    return action