app/app_profiler/app_profiler.py
author Sverre Rabbelier <srabbelier@gmail.com>
Sat, 29 Aug 2009 14:31:26 -0700
changeset 2848 17a31a7e6abc
parent 2832 2a0a7e081caf
child 2857 bc793800116e
permissions -rw-r--r--
Convert profiler/start page to html
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2832
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     1
import cProfile
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     2
import ppstats
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     3
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     4
from google.appengine.ext import webapp
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     5
from google.appengine.api import memcache
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     6
import google.appengine.ext.webapp.util
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     7
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     8
import os.path
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     9
import logging
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    10
import re
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    11
import random
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    12
import string
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    13
import zlib
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    14
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    15
mc_client = memcache.Client()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    16
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    17
alphanumeric = string.letters + string.digits
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    18
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    19
global_profiler = None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    20
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    21
class GAEProfiler(object):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    22
    _save_every = 10
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    23
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    24
    def __init__(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    25
        self.is_profiling = False
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    26
        self._profiler = None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    27
        self.num_requests = 0
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    28
        self.requests_profiled = 0
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    29
        self.request_regex = None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    30
        self.profile_key = ''.join([random.choice(alphanumeric) for x in range(4)])
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    31
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    32
    def start_profiling(self, request_regex=None, num_requests=0):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    33
        "start profiling with this object, setting # of requests and filter"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    34
        if self.is_profiling:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    35
            return
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    36
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    37
        self.is_profiling = True
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    38
        if self._profiler is None:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    39
            self._profiler = cProfile.Profile()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    40
        self.num_requests = num_requests
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    41
        if request_regex:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    42
            self.request_regex = re.compile(request_regex)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    43
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    44
    def stop_profiling(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    45
        self.is_profiling = False
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    46
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    47
    def resume_profiling(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    48
        self.is_profiling = True
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    49
    
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    50
    def has_profiler(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    51
        return self._profiler is not None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    52
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    53
    def get_pstats(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    54
        "return a ppstats object from current profile data"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    55
        gae_base_dir = '/'.join(webapp.__file__.split('/')[:-5])
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    56
        sys_base_dir = '/'.join(logging.__file__.split('/')[:-2])
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    57
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    58
        stats = ppstats.Stats(self._profiler)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    59
        stats.hide_directory(gae_base_dir, 'GAEHome')
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    60
        stats.hide_directory(sys_base_dir, 'SysHome')
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    61
        stats.strip_dirs()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    62
        return stats
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    63
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    64
    def runcall(self, func, *args, **kwargs):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    65
        "profile one call, incrementing requests_profiled and maybe saving stats"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    66
        self.requests_profiled += 1
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    67
        if self._profiler:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    68
            ret = self._profiler.runcall(func, *args, **kwargs)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    69
        else:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    70
            ret = func(*args, **kwargs)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    71
        
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    72
#        if (self.requests_profiled % self._save_every) == 0 or \
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    73
#                self.requests_profiled == self.num_requests:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    74
#            self.save_pstats_to_memcache()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    75
        self.save_pstats_to_memcache()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    76
        return ret
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    77
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    78
    def should_profile_request(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    79
        "check for # of requests profiled and that SCRIPT_NAME matches regex"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    80
        env = dict(os.environ)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    81
        script_name = env.get('SCRIPT_NAME', '')
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    82
        logging.info(script_name)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    83
        
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    84
        if self.num_requests and self.requests_profiled >= self.num_requests:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    85
            return False
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    86
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    87
        if self.request_regex and not self.request_regex.search(script_name):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    88
            return False
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    89
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    90
        return True
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    91
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    92
    def save_pstats_to_memcache(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    93
        "save stats from profiler object to memcache"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    94
        ps = self.get_pstats()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    95
        output = ps.dump_stats_pickle()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    96
        compressed_data = zlib.compress(output, 3)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    97
        cache_key = cache_key_for_profile(self.profile_key)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    98
        mc_client.set(cache_key, compressed_data)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    99
        logging.info("Saved pstats to memcache with key %s" % cache_key)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   100
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   101
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   102
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   103
def get_global_profiler():
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   104
    global global_profiler
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   105
    if not global_profiler:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   106
        global_profiler = GAEProfiler()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   107
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   108
    return global_profiler
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   109
    
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   110
def cache_key_for_profile(profile_key):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   111
    "generate a memcache key"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   112
    return "ProfileData.%s" % profile_key
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   113
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   114
def load_pstats_from_memcache(profile_key):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   115
    "retrieve ppstats object"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   116
    mc_data = mc_client.get(cache_key_for_profile(profile_key))
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   117
    if not mc_data:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   118
        return None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   119
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   120
    return ppstats.from_gz(mc_data)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   121
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   122
def get_stats_from_global_or_request(request_obj):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   123
    "get pstats for a key, or the global pstats"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   124
    key = request_obj.get('key', '')
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   125
    if key:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   126
        return load_pstats_from_memcache(key)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   127
    else:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   128
        gp = get_global_profiler()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   129
        if not gp.has_profiler():
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   130
            return None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   131
        return gp.get_pstats()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   132
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   133
class show_profile(webapp.RequestHandler):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   134
    def get(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   135
        ps = get_stats_from_global_or_request(self.request)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   136
        if not ps:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   137
            self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   138
            return
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   139
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   140
        ps.set_output(self.response.out)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   141
        sort = self.request.get('sort', 'time')
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   142
        ps.sort_stats(sort)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   143
        self.response.out.write("<body><html><pre>\n")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   144
        ps.print_stats(30)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   145
        self.response.out.write("</pre></html></body>")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   146
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   147
class download_profile_data(webapp.RequestHandler):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   148
    def get(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   149
        ps = get_stats_from_global_or_request(self.request)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   150
        if not ps:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   151
            self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   152
            return            
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   153
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   154
        output = ps.dump_stats_pickle()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   155
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   156
        self.response.headers['Content-Type'] = 'application/octet-stream'
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   157
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   158
        self.response.out.write(output)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   159
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   160
class show_profiler_status(webapp.RequestHandler):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   161
    def get(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   162
        gp = get_global_profiler()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   163
        if not gp.has_profiler:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   164
            self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   165
            return
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   166
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   167
        self.response.out.write("<html><body>")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   168
        self.response.out.write("<b>Currently profiling:</b> %s<br>" % gp.is_profiling)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   169
        self.response.out.write("<b>Profile Key</b>: %s<br>" % gp.profile_key)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   170
        self.response.out.write("<b>Requests profiled so far:</b> %s<br>" % gp.requests_profiled)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   171
        self.response.out.write("<b>Requests to profile:</b> %s<br>" % gp.num_requests)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   172
        self.response.out.write("<b>Request regex:</b> %s<br>" % gp.request_regex)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   173
        self.response.out.write("</body></html>")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   174
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   175
class start_profiler(webapp.RequestHandler):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   176
    def get(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   177
        gp = get_global_profiler()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   178
        gp.start_profiling()
2848
17a31a7e6abc Convert profiler/start page to html
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
   179
        self.response.out.write("<html><body>")
17a31a7e6abc Convert profiler/start page to html
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
   180
        self.response.out.write("Started profiling (key: %s). <br />" % gp.profile_key)
17a31a7e6abc Convert profiler/start page to html
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
   181
        self.response.out.write("Retrieve saved results at "
17a31a7e6abc Convert profiler/start page to html
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
   182
            "<a href='/profiler/show?key=%(key)s'>/profiler/show?key=%(key)s</a>. <br />" % {'key':gp.profile_key})
17a31a7e6abc Convert profiler/start page to html
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
   183
        self.response.out.write("</body></html>")
2832
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   184
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   185
class stop_profiler(webapp.RequestHandler):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   186
    def get(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   187
        gp = get_global_profiler()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   188
        gp.stop_profiling()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   189
        self.request.out.write("Content-Type: text/plain\n\n")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   190
        self.request.out.write("done.")
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   191
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   192
class save_profile_data(webapp.RequestHandler):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   193
    def get(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   194
        gp = get_global_profiler()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   195
        
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   196
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   197
def _add_our_endpoints(application):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   198
    "insert our URLs into the application map"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   199
    url_mapping = [(regex.pattern, handler) for (regex, handler) in application._url_mapping]
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   200
    return webapp.WSGIApplication(url_mapping, debug=True)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   201
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   202
#
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   203
#  wrapper to for webapp applications
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   204
#
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   205
def run_wsgi_app(application):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   206
    "proxy webapp.util's call to profile when needed"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   207
    gp = get_global_profiler()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   208
    if gp.is_profiling and gp.should_profile_request():
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   209
        return gp.runcall(google.appengine.ext.webapp.util.run_wsgi_app, *(application,))
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   210
    else:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   211
        return google.appengine.ext.webapp.util.run_wsgi_app(application)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   212
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   213
#
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   214
# middleware for django applications
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   215
#
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   216
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   217
class ProfileMiddleware(object):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   218
    def __init__(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   219
        self.profiler = None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   220
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   221
    def process_request(self, request):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   222
        self.profiler = get_global_profiler()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   223
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   224
    def process_view(self, request, callback, callback_args, callback_kwargs):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   225
        if self.profiler.is_profiling:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   226
            return self.profiler.runcall(callback, request, *callback_args, **callback_kwargs)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   227
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   228
application = webapp.WSGIApplication(
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   229
    [('/profiler/start', start_profiler),
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   230
     ('/profiler/stop', stop_profiler),
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   231
     ('/profiler/show', show_profile),
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   232
     ('/profiler/download', download_profile_data),
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   233
     ('/profiler/status', show_profiler_status),
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   234
     ],
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   235
    debug=True)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   236
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   237
    
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   238
def main():
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   239
    google.appengine.ext.webapp.util.run_wsgi_app(application)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   240
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   241
if __name__ == '__main__':
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   242
    main()