app/app_profiler/app_profiler.py
changeset 2857 bc793800116e
parent 2848 17a31a7e6abc
equal deleted inserted replaced
2856:f446e019825c 2857:bc793800116e
     3 
     3 
     4 from google.appengine.ext import webapp
     4 from google.appengine.ext import webapp
     5 from google.appengine.api import memcache
     5 from google.appengine.api import memcache
     6 import google.appengine.ext.webapp.util
     6 import google.appengine.ext.webapp.util
     7 
     7 
       
     8 from email.MIMEMultipart import MIMEMultipart
       
     9 from email.Message import Message
       
    10 
       
    11 import httplib
       
    12 import logging
     8 import os.path
    13 import os.path
     9 import logging
    14 import random
    10 import re
    15 import re
    11 import random
       
    12 import string
    16 import string
    13 import zlib
    17 import zlib
    14 
    18 
    15 mc_client = memcache.Client()
    19 mc_client = memcache.Client()
    16 
    20 
   105     if not global_profiler:
   109     if not global_profiler:
   106         global_profiler = GAEProfiler()
   110         global_profiler = GAEProfiler()
   107 
   111 
   108     return global_profiler
   112     return global_profiler
   109     
   113     
       
   114 def new_global_profiler():
       
   115     global global_profiler
       
   116     global_profiler = GAEProfiler()
       
   117     return global_profiler
       
   118 
   110 def cache_key_for_profile(profile_key):
   119 def cache_key_for_profile(profile_key):
   111     "generate a memcache key"
   120     "generate a memcache key"
   112     return "ProfileData.%s" % profile_key
   121     return "ProfileData.%s" % profile_key
   113 
   122 
   114 def load_pstats_from_memcache(profile_key):
   123 def load_pstats_from_memcache(profile_key):
   121 
   130 
   122 def get_stats_from_global_or_request(request_obj):
   131 def get_stats_from_global_or_request(request_obj):
   123     "get pstats for a key, or the global pstats"
   132     "get pstats for a key, or the global pstats"
   124     key = request_obj.get('key', '')
   133     key = request_obj.get('key', '')
   125     if key:
   134     if key:
   126         return load_pstats_from_memcache(key)
   135         gp = GAEProfiler()
       
   136         gp.profile_obj = load_pstats_from_memcache(key)
       
   137         gp.profile_key = key
       
   138         return gp
   127     else:
   139     else:
   128         gp = get_global_profiler()
   140         gp = get_global_profiler()
   129         if not gp.has_profiler():
   141         if not gp.has_profiler():
   130             return None
   142             return None
   131         return gp.get_pstats()
   143         return gp
       
   144 
       
   145 def mime_upload_data_as_file(field_name, filename, body):
       
   146     part = Message()
       
   147     part['Content-Disposition'] = 'form-data; name="%s"; filename="%s"' % (field_name, filename)
       
   148     part['Content-Transfer-Encoding'] = 'binary'
       
   149     part['Content-Type'] = 'application/octet-stream'
       
   150     part['Content-Length'] = str(len(body))
       
   151     part.set_payload(body)
       
   152     return part
       
   153 
       
   154 def mime_form_value(name, value):
       
   155     part = Message()
       
   156     part['Content-Disposition'] = 'form-data; name="%s"' % name
       
   157     part.set_payload(value)
       
   158     return part
   132 
   159 
   133 class show_profile(webapp.RequestHandler):
   160 class show_profile(webapp.RequestHandler):
   134     def get(self):
   161     def get(self):
   135         ps = get_stats_from_global_or_request(self.request)
   162         ps = get_stats_from_global_or_request(self.request)
   136         if not ps:
   163         if not ps:
   137             self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
   164             self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
   138             return
   165             return
   139 
   166 
   140         ps.set_output(self.response.out)
   167         ps.profile_obj.set_output(self.response.out)
   141         sort = self.request.get('sort', 'time')
   168         sort = self.request.get('sort', 'time')
   142         ps.sort_stats(sort)
   169         ps.profile_obj.sort_stats(sort)
   143         self.response.out.write("<body><html><pre>\n")
   170         self.response.out.write("<body><html><pre>\n")
   144         ps.print_stats(30)
   171         ps.profile_obj.print_stats(30)
   145         self.response.out.write("</pre></html></body>")
   172         self.response.out.write("</pre></html></body>")
   146 
   173 
   147 class download_profile_data(webapp.RequestHandler):
   174 class download_profile_data(webapp.RequestHandler):
   148     def get(self):
   175     def get(self):
   149         ps = get_stats_from_global_or_request(self.request)
   176         ps = get_stats_from_global_or_request(self.request)
   150         if not ps:
   177         if not ps:
   151             self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
   178             self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
   152             return            
   179             return            
   153 
   180 
   154         output = ps.dump_stats_pickle()
   181         output = ps.profile_obj.dump_stats_pickle()
   155 
   182 
   156         self.response.headers['Content-Type'] = 'application/octet-stream'
   183         self.response.headers['Content-Type'] = 'application/octet-stream'
   157 
   184 
   158         self.response.out.write(output)
   185         self.response.out.write(output)
   159 
   186 
       
   187 class send_profile_data(webapp.RequestHandler):
       
   188     def get(self):
       
   189         ps = get_stats_from_global_or_request(self.request)
       
   190         if not ps:
       
   191             self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
       
   192             return            
       
   193 
       
   194         dest = self.request.get('dest', '')
       
   195         if not dest:
       
   196             self.response.out.write("<body><html>No destination</html></body>")
       
   197 
       
   198         upload_form = MIMEMultipart('form-data')
       
   199 
       
   200         upload_filename =  'profile.%s.pstats' % ps.profile_key
       
   201         upload_field_name = 'profile_file'
       
   202 
       
   203         upload_form.attach(mime_upload_data_as_file('profile_file', upload_field_name, zlib.compress(ps.profile_obj.dump_stats_pickle())))
       
   204         upload_form.attach(mime_form_value('key_only', '1'))
       
   205 
       
   206         http_conn = httplib.HTTPConnection(dest)
       
   207         http_conn.connect()
       
   208         http_conn.request('POST', '/upload_profile', upload_form.as_string(), 
       
   209                           {'Content-Type': 'multipart/form-data; boundary=%s' % upload_form.get_boundary()})
       
   210 
       
   211         http_resp = http_conn.getresponse()
       
   212         remote_data = http_resp.read()
       
   213         if http_resp.status == 200:
       
   214             remote_url = "http://%s/view_profile?key=%s" % (dest, remote_data)
       
   215             self.response.out.write("<html><body>Success! <a href='%s'>%s</a></body></html>" % (remote_url, remote_url))
       
   216         else:
       
   217             self.response.out.write("Failure!\n%s: %s\n%s" % (http_resp.status, http_resp.reason, remote_data))
       
   218             
   160 class show_profiler_status(webapp.RequestHandler):
   219 class show_profiler_status(webapp.RequestHandler):
   161     def get(self):
   220     def get(self):
   162         gp = get_global_profiler()
   221         gp = get_global_profiler()
   163         if not gp.has_profiler:
   222         if not gp.has_profiler:
   164             self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
   223             self.response.out.write("<body><html><h3>No profiler.</h3><html></body>")
   172         self.response.out.write("<b>Request regex:</b> %s<br>" % gp.request_regex)
   231         self.response.out.write("<b>Request regex:</b> %s<br>" % gp.request_regex)
   173         self.response.out.write("</body></html>")
   232         self.response.out.write("</body></html>")
   174 
   233 
   175 class start_profiler(webapp.RequestHandler):
   234 class start_profiler(webapp.RequestHandler):
   176     def get(self):
   235     def get(self):
   177         gp = get_global_profiler()
   236         gp = new_global_profiler()
   178         gp.start_profiling()
   237         gp.start_profiling()
   179         self.response.out.write("<html><body>")
   238         self.response.headers['Content-Type'] = "text/plain"
   180         self.response.out.write("Started profiling (key: %s). <br />" % gp.profile_key)
   239         self.response.out.write("Started profiling (key: %s).\n" % gp.profile_key)
   181         self.response.out.write("Retrieve saved results at "
   240         self.response.out.write("Retrieve saved results at <a href='/profiler/show?key=%(key)s'>/profiler/show?key=%(key)s).\n" % {'key':gp.profile_key})
   182             "<a href='/profiler/show?key=%(key)s'>/profiler/show?key=%(key)s</a>. <br />" % {'key':gp.profile_key})
       
   183         self.response.out.write("</body></html>")
       
   184 
   241 
   185 class stop_profiler(webapp.RequestHandler):
   242 class stop_profiler(webapp.RequestHandler):
   186     def get(self):
   243     def get(self):
   187         gp = get_global_profiler()
   244         gp = get_global_profiler()
   188         gp.stop_profiling()
   245         gp.stop_profiling()
   229     [('/profiler/start', start_profiler),
   286     [('/profiler/start', start_profiler),
   230      ('/profiler/stop', stop_profiler),
   287      ('/profiler/stop', stop_profiler),
   231      ('/profiler/show', show_profile),
   288      ('/profiler/show', show_profile),
   232      ('/profiler/download', download_profile_data),
   289      ('/profiler/download', download_profile_data),
   233      ('/profiler/status', show_profiler_status),
   290      ('/profiler/status', show_profiler_status),
       
   291      ('/profiler/send', send_profile_data),
   234      ],
   292      ],
   235     debug=True)
   293     debug=True)
   236 
   294 
   237     
   295     
   238 def main():
   296 def main():