Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django-debug-toolbar-line-profiler shows only a single line of output, no content

I have a Raspberry Pi sitting in a remote location. It is hooked up to a small homemade circuit and a temperature probe. I've set up the Raspberry Pi to do a few things:

  • Run cron jobs every hour to take a temperature reading and store it locally to a sqlite database
  • Run an Nginx web server
  • Run a uwsgi application server
  • Serve a simple Django app

In that Django app, I have a simple view that does the following:

  1. Hit the DB to get the last 300 temperature recordings
  2. Put those into a Pandas DataFrame
  3. Use Matplotlib to produce a nice SVG graph of the recent temperature history
  4. Fill out a simple template which displays the SVG and also a small HTML table of the recent temperature readings.

Rendering this view takes ~30 seconds. A very long time. So I wanted to see what was taking so long. My guess is that it's all the work related to generating the graphics. But to find out, I wanted to do some profiling.

I installed django-debug-toolbar and also django-debug-toolbar-line-profiler using pip.

I have configured them according to the docs as best I understood. In particular, I've set:

DEBUG = True
TEMPLATE_DEBUG = DEBUG
DEBUG_TOOLBAR_PATCH_SETTINGS = False

MIDDLEWARE_CLASSES = (
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

DEBUG_TOOLBAR_PANELS = (
    'debug_toolbar.panels.versions.VersionsPanel',
    'debug_toolbar.panels.timer.TimerPanel',
    'debug_toolbar.panels.settings.SettingsPanel',
    'debug_toolbar.panels.headers.HeadersPanel',
    'debug_toolbar.panels.sql.SQLPanel',
    'debug_toolbar.panels.staticfiles.StaticFilesPanel',
    'debug_toolbar.panels.templates.TemplatesPanel',
    'debug_toolbar.panels.cache.CachePanel',
    'debug_toolbar.panels.signals.SignalsPanel',
    'debug_toolbar.panels.logging.LoggingPanel',
    'debug_toolbar.panels.redirects.RedirectsPanel',

    'debug_toolbar_line_profiler.panel.ProfilingPanel',
)

In addition, INTERNAL_IPS is also set properly.

I have built my view using class-based views. It looks like this:

from django.views.generic import TemplateView
from XXXX.models import TempReading, TempSeries
import numpy as np
import pandas as pd
import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
import seaborn as sbn
import StringIO

class TestView(TemplateView):
    template_name = 'XXXX/test.html'

    def get_context_data(self, **kwargs):
        upstairs = TempSeries.objects.get(name='Upstairs')
        upstairstemps = upstairs.tempreading_set.all().order_by('-timestamp')[:300]

        frame = pd.DataFrame(list(upstairstemps.values()))
        frame.set_index('timestamp', inplace=True)

        # matplotlib.rcParams['svg.fonttype'] = 'none'

        fig = Figure()
        ax = fig.add_subplot(1,1,1)
        frame['value'].plot(ax=ax)
        ax.get_xaxis().grid(color='w', linewidth=1)
        ax.get_yaxis().grid(color='w', linewidth=1)

        fig.set(facecolor='w')
        canvas = FigureCanvas(fig)

        imgdata = StringIO.StringIO()
        canvas.print_svg(imgdata)

        imgstr = imgdata.getvalue()

        context = super(TestView, self).get_context_data(**kwargs)
        context['svgtext'] = imgstr
        context['htmltable'] = frame[:5].to_html()

        return context

The code I am most interested in profiling is get_context_data.

When I load the page, the debug-toolbar does in fact show up. And the profiling panel is shown. But all I see is:

{method 'disable' of '_lsprof.Profiler' objects}

Here's a screenshot of the page as it first loads: enter image description here

And here's how it looks on the profiling page: enter image description here

It doesn't seem like it's doing any "line-profiling" at all! I was expecting to see timed results for every line within my class-based view. In particular, for each line within the get_context_data function. What's going on? Any help much appreciated.


Edit on 4/2

Just as a test, I wrote up a dummy view that does not use class-based views. And this seems to work just fine. Here's the new non-class-based-view:

def testview2(request):
    df = pd.DataFrame({'a': np.random.randn(10), 'b': np.random.randn(10)})
    htmltable = df.to_html()
    context = {}
    context['htmltable'] = htmltable

    return render(request, 'XXXX/test2.html', context)

And that produces the following result in the profiling pane: enter image description here

So that seems to be working fine. Is there some subtlety I'm missing about how debug-toolbar-line-profiler works with class-based views? In the docs, it suggests it will profile any method on the class that does not start with an underscore. Is that incorrect?

like image 939
8one6 Avatar asked Mar 30 '14 19:03

8one6


1 Answers

I noticed this happening when I decorated my views with @csrf_exempt; once removed the profiler worked fine.

Not sure why it causes the issue but that fixed it for me.

like image 196
JUhrig Avatar answered Oct 05 '22 18:10

JUhrig