Skip to content

Commit

Permalink
Add PYINSTRUMENT_PROFILE_DIR option to Django middleware
Browse files Browse the repository at this point in the history
This option allows users to profile every request, and save the HTML
output to a folder for later examination. This is especially good for
profiling API calls.
  • Loading branch information
joerick committed Jul 9, 2014
1 parent bc0db35 commit 4572216
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions pyinstrument/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from django.conf import settings
from pyinstrument import Profiler
from pyinstrument.profiler import NotMainThreadError
import time
import os

not_main_thread_message = (
'pyinstrument can only be used on the main thread in signal mode. Run your server process in '
Expand All @@ -15,9 +17,10 @@

class ProfilerMiddleware(object):
def process_request(self, request):
profile_dir = getattr(settings, 'PYINSTRUMENT_PROFILE_DIR', None)
use_signal = getattr(settings, 'PYINSTRUMENT_USE_SIGNAL', True)

if getattr(settings, 'PYINSTRUMENT_URL_ARGUMENT', 'profile') in request.GET:
if getattr(settings, 'PYINSTRUMENT_URL_ARGUMENT', 'profile') in request.GET or profile_dir:
profiler = Profiler(use_signal=use_signal)
try:
profiler.start()
Expand All @@ -31,7 +34,29 @@ def process_response(self, request, response):
try:
request.profiler.stop()

return HttpResponse(request.profiler.output_html())
output_html = request.profiler.output_html()

profile_dir = getattr(settings, 'PYINSTRUMENT_PROFILE_DIR', None)

if profile_dir:
filename = '{total_time:.3f}s {path} {timestamp:.0f}.html'.format(
total_time=request.profiler.root_frame().time(),
path=request.get_full_path().replace('/', '_'),
timestamp=time.time()
)

file_path = os.path.join(profile_dir, filename)

if not os.path.exists(profile_dir):
os.mkdir(profile_dir)

with open(file_path, 'w') as f:
f.write(output_html)

if getattr(settings, 'PYINSTRUMENT_URL_ARGUMENT', 'profile') in request.GET:
return HttpResponse(output_html)
else:
return response
except NotMainThreadError:
raise NotMainThreadError(not_main_thread_message)
else:
Expand Down

0 comments on commit 4572216

Please sign in to comment.