Last active
December 28, 2015 02:19
-
-
Save ikatson/7426817 to your computer and use it in GitHub Desktop.
Simple django profiling
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
# Profiling middleware and decorator, that allows to profile any django | |
# view easily for superusers. | |
__author__ = '[email protected]' | |
import cProfile | |
import pstats | |
import tempfile | |
import cStringIO as StringIO | |
def profile_view(func): | |
"""A view decorator that allows profiling. | |
Usage: | |
/path/to/view/?profile=1 | |
/path/to/view/?profile=1&print_callees=1 | |
/path/to/view/?profile=1&print_callers=1 | |
/path/to/view/?profile=1&profile_limit=100 | |
/path/to/view/?profile=1&profile_order=time | |
This will print the pstats.Stats profiling report right to | |
your screen, as a content of Django response. | |
""" | |
def inner(request, *args, **kwargs): | |
if 'profile' not in request.GET: | |
return func(request, *args, **kwargs) | |
profile_order = request.GET.get('profile_order', 'cumulative') | |
print_callees = request.GET.get('print_callees') | |
print_callers = request.GET.get('print_callers') | |
profile_limit = int(request.GET.get('profile_limit', 80)) | |
pfile = tempfile.NamedTemporaryFile() | |
result = {} | |
def wrapper(): | |
result_ = func(request, *args, **kwargs) | |
result['result'] = result_ | |
return result_ | |
cProfile.runctx('wrapper()', globals(), locals(), pfile.name) | |
stream = StringIO.StringIO() | |
stats = pstats.Stats(pfile.name, stream=stream) | |
stats = stats.sort_stats(profile_order) | |
if print_callees: | |
stats.print_callees(profile_limit) | |
elif print_callers: | |
stats.print_callers(profile_limit) | |
else: | |
stats.print_stats(profile_limit) | |
response = result['result'] | |
text = stream.getvalue() | |
# text/plain results use {line-break: break-word} by default in Chrome, | |
# which makes long output of e.g. "print_callees=1" hard to read. | |
# See http://stackoverflow.com/questions/5837556/how-to-disable-word- | |
# wrapping-in-plain-text-files-in-chrome and | |
# http://habrahabr.ru/company/mailru/blog/201778/#comment_6971294 | |
html = '<pre>%s</pre>' % text | |
response.content = html | |
response['Content-Type'] = 'text/html' | |
return response | |
return inner | |
class ProfilingMiddleware(object): | |
"""Profiling middleware, that allows to profile any django view easily. | |
For usage examples, see profile_view decorator. | |
""" | |
def process_view(self, request, view_func, view_args, view_kwargs): | |
if 'profile' in request.GET and request.user.is_superuser: | |
return profile_view(view_func)(request, *view_args, **view_kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment