123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- """
- 用于测量性能的中间件
- """
- # Original version taken from http://www.djangosnippets.org/snippets/186/
- # Original author: udfalkso
- # Modified by: Shwagroo Team and Gun.io
- import sys
- import os
- import re
- import hotshot, hotshot.stats
- import tempfile
- from six import StringIO
- from django.conf import settings
- words_re = re.compile(r'\s+')
- group_prefix_re = [
- re.compile("^.*/django/[^/]+"),
- re.compile("^(.*)/[^/]+$"), # extract module path
- re.compile(".*"), # catch strange entries
- ]
- class ProfileMiddleware(object):
- """
- Displays hotshot profiling for any view.
- http://yoursite.com/yourview/?prof
- Add the "prof" key to query string by appending ?prof (or &prof=)
- and you'll see the profiling results in your browser.
- It's set up to only be available in django's debug mode, is available for superuser otherwise,
- but you really shouldn't add this middleware to any production configuration.
- WARNING: It uses hotshot profiler which is not thread safe.
- """
- def process_request(self, request):
- if settings.DEBUG and 'prof' in request.GET:
- self.tmpfile = tempfile.mktemp()
- self.prof = hotshot.Profile(self.tmpfile)
- def process_view(self, request, callback, callback_args, callback_kwargs):
- if settings.DEBUG and 'prof' in request.GET:
- return self.prof.runcall(callback, request, *callback_args, **callback_kwargs)
- def get_group(self, file_):
- for g in group_prefix_re:
- name = g.findall(file_)
- if name:
- return name[0]
- def get_summary(self, results_dict, total):
- list_ = [(item[1], item[0]) for item in results_dict.items()]
- list_.sort(reverse = True)
- list_ = list_[:40]
- res = " tottime\n"
- for item in list_:
- res += "%4.1f%% %7.3f %s\n" % (100 * item[0] / total if total else 0, item[0], item[1])
- return res
- def summary_for_files(self, stats_str):
- stats_str = stats_str.split("\n")[5:]
- stats = {}
- groups = {}
- total = 0
- for s in stats_str:
- fields = words_re.split(s)
- if len(fields) == 7:
- time = float(fields[2])
- total += time
- file_ = fields[6].split(":")[0]
- if not file_ in stats:
- stats[file_] = 0
- stats[file_] += time
- group = self.get_group(file_)
- if not group in groups:
- groups[group] = 0
- groups[group] += time
- return "<pre>" + \
- " ---- By file ----\n\n" + self.get_summary(stats, total) + "\n" + \
- " ---- By group ---\n\n" + self.get_summary(groups, total) + \
- "</pre>"
- def process_response(self, request, response):
- if settings.DEBUG and 'prof' in request.GET:
- self.prof.close()
- out = StringIO()
- old_stdout = sys.stdout
- sys.stdout = out
- stats = hotshot.stats.load(self.tmpfile)
- stats.sort_stats('time', 'calls')
- stats.print_stats()
- sys.stdout = old_stdout
- stats_str = out.getvalue()
- if response and response.content and stats_str:
- response.content = "<pre>" + stats_str + "</pre>"
- response.content = "\n".join(response.content.split("\n")[:40])
- response.content += self.summary_for_files(stats_str)
- os.unlink(self.tmpfile)
- return response
|