From 7a24088d0d4316e113387d229ed0491e31226348 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Fri, 9 Sep 2011 10:22:19 -0700 Subject: If a stacktrace frame is not in the expected format, skip over it --- debug_toolbar/panels/sql.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 841aaac..9687a5c 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -190,11 +190,15 @@ class SQLDebugPanel(DebugPanel): query['start_offset'] = width_ratio_tally query['end_offset'] = query['width_ratio'] + query['start_offset'] width_ratio_tally += query['width_ratio'] - + stacktrace = [] for frame in query['stacktrace']: params = map(escape, frame[0].rsplit('/', 1) + list(frame[1:])) - stacktrace.append(u'{0}/{1} in {3}({2})\n {4}'.format(*params)) + try: + stacktrace.append(u'{0}/{1} in {3}({2})\n {4}'.format(*params)) + except IndexError: + # This frame doesn't have the expected format, so skip it and move on to the next one + continue query['stacktrace'] = mark_safe('\n'.join(stacktrace)) i += 1 -- cgit v1.2.3 From 358d2364f95d859bf75f0194b3ea2b66642f0529 Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Fri, 9 Sep 2011 23:48:35 +0200 Subject: Revert some of the previous changes and modify slightly the panels to separate the gneration of the stats and the generation of the content. --- debug_toolbar/middleware.py | 13 +++++++------ debug_toolbar/panels/cache.py | 12 ++++++++---- debug_toolbar/panels/sql.py | 35 +++++++++++++++++++---------------- 3 files changed, 34 insertions(+), 26 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index f49a29f..1d332c0 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -5,7 +5,6 @@ import imp import thread from django.conf import settings -from django.conf.urls.defaults import include, patterns from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.utils.encoding import smart_unicode @@ -97,6 +96,7 @@ class DebugToolbarMiddleware(object): for panel in toolbar.panels: panel.process_request(request) self.__class__.debug_toolbars[thread.get_ident()] = toolbar + request.debug_toolbar = toolbar def process_view(self, request, view_func, view_args, view_kwargs): __traceback_hide__ = True @@ -124,13 +124,14 @@ class DebugToolbarMiddleware(object): ) response.cookies = cookies if 'gzip' not in response.get('Content-Encoding', '') and \ - response.get('Content-Type', '').split(';')[0] in _HTML_TYPES: + response.get('Content-Type', '').split(';')[0] in _HTML_TYPES: + toolbar.stats = {} for panel in toolbar.panels: - panel.process_response(request, response) + panel.process_response(request, response) response.content = replace_insensitive( - smart_unicode(response.content), - self.tag, - smart_unicode(toolbar.render_toolbar() + self.tag)) + smart_unicode(response.content), + self.tag, + smart_unicode(toolbar.render_toolbar() + self.tag)) if response.get('Content-Length', None): response['Content-Length'] = len(response.content) del self.__class__.debug_toolbars[ident] diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index 5617ec2..c03971d 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -95,11 +95,15 @@ class CacheDebugPanel(DebugPanel): def url(self): return '' - def content(self): - context = self.context.copy() - context.update({ + def process_response(self, request, response): + self.stats = { 'cache_calls': len(self.cache.calls), 'cache_time': self.cache.total_time, 'cache': self.cache, - }) + } + request.debug_toolbar.stats['cache'] = self.stats + + def content(self): + context = self.context.copy() + context.update(self.stats) return render_to_string('debug_toolbar/panels/cache.html', context) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 9687a5c..2eced7c 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -23,7 +23,7 @@ def cursor(func, self): if not djdt: return result logger = djdt.get_panel(SQLDebugPanel) - + return CursorWrapper(result, self, logger=logger) def get_isolation_level_display(engine, level): @@ -38,7 +38,7 @@ def get_isolation_level_display(engine, level): } else: raise ValueError(engine) - + return choices.get(level) def get_transaction_status_display(engine, level): @@ -53,7 +53,7 @@ def get_transaction_status_display(engine, level): } else: raise ValueError(engine) - + return choices.get(level) class SQLDebugPanel(DebugPanel): @@ -73,7 +73,7 @@ class SQLDebugPanel(DebugPanel): self._databases = {} self._transaction_status = {} self._transaction_ids = {} - + def get_transaction_id(self, alias): conn = connections[alias].connection if not conn: @@ -97,9 +97,9 @@ class SQLDebugPanel(DebugPanel): self._transaction_ids[alias] = uuid.uuid4().hex else: self._transaction_ids[alias] = None - + return self._transaction_ids[alias] - + def record(self, alias, **kwargs): self._queries.append((alias, kwargs)) if alias not in self._databases: @@ -126,7 +126,7 @@ class SQLDebugPanel(DebugPanel): def title(self): count = len(self._databases) - + return __('SQL Queries from %(count)d connection', 'SQL Queries from %(count)d connections', count) % dict( count=count, ) @@ -134,7 +134,7 @@ class SQLDebugPanel(DebugPanel): def url(self): return '' - def content(self): + def process_response(self, request, response): if self._queries: width_ratio_tally = 0 colors = [ @@ -157,14 +157,14 @@ class SQLDebugPanel(DebugPanel): nn = 0 rgb[nn] = nc db['rgb_color'] = rgb - + trans_ids = {} trans_id = None i = 0 for alias, query in self._queries: trans_id = query.get('trans_id') last_trans_id = trans_ids.get(alias) - + if trans_id != last_trans_id: if last_trans_id: self._queries[i-1][1]['ends_trans'] = True @@ -173,7 +173,7 @@ class SQLDebugPanel(DebugPanel): query['starts_trans'] = True if trans_id: query['in_trans'] = True - + query['alias'] = alias if 'iso_level' in query: query['iso_level'] = get_isolation_level_display(query['engine'], query['iso_level']) @@ -190,7 +190,7 @@ class SQLDebugPanel(DebugPanel): query['start_offset'] = width_ratio_tally query['end_offset'] = query['width_ratio'] + query['start_offset'] width_ratio_tally += query['width_ratio'] - + stacktrace = [] for frame in query['stacktrace']: params = map(escape, frame[0].rsplit('/', 1) + list(frame[1:])) @@ -204,14 +204,17 @@ class SQLDebugPanel(DebugPanel): if trans_id: self._queries[i-1][1]['ends_trans'] = True - - context = self.context.copy() - context.update({ + + self.stats = { 'databases': sorted(self._databases.items(), key=lambda x: -x[1]['time_spent']), 'queries': [q for a, q in self._queries], 'sql_time': self._sql_time, - }) + } + request.debug_toolbar.stats['sql'] = getattr(self, 'stats', None) + def content(self): + context = self.context.copy() + context.update(self.stats) return render_to_string('debug_toolbar/panels/sql.html', context) class BoldKeywordFilter(sqlparse.filters.Filter): -- cgit v1.2.3 From 970e084055c1210ff6251965bc87ad1b0d72ea0e Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Sat, 10 Sep 2011 00:01:15 +0200 Subject: Populate the stats['headers'] on the request.debug_toolbar --- debug_toolbar/panels/headers.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py index 1e929f6..cedd3ee 100644 --- a/debug_toolbar/panels/headers.py +++ b/debug_toolbar/panels/headers.py @@ -46,6 +46,9 @@ class HeaderDebugPanel(DebugPanel): [(k, request.META[k]) for k in self.header_filter if k in request.META] ) + def process_response(self, request, response): + request.debug_toolbar.stats['headers'] = self.headers + def content(self): context = self.context.copy() context.update({ -- cgit v1.2.3 From a08238af1ec07e077a0ee0f816d82c62c3f0ac63 Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Sat, 10 Sep 2011 01:24:32 +0200 Subject: Revert some of the previous changes and modify slightly the panels to separate the gneration of the stats and the generation of the content. --- debug_toolbar/panels/cache.py | 1 + debug_toolbar/panels/profiling.py | 47 ++++++++++++++++++++------------------- debug_toolbar/panels/sql.py | 1 + 3 files changed, 26 insertions(+), 23 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index c03971d..4cc783e 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -102,6 +102,7 @@ class CacheDebugPanel(DebugPanel): 'cache': self.cache, } request.debug_toolbar.stats['cache'] = self.stats + return response def content(self): context = self.context.copy() diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index 289e1f7..623b27a 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -8,9 +8,9 @@ from debug_toolbar.panels import DebugPanel try: from line_profiler import LineProfiler, show_func DJ_PROFILE_USE_LINE_PROFILER = True -except ImportError: +except ImportError: DJ_PROFILE_USE_LINE_PROFILER = False - + from cStringIO import StringIO import cProfile @@ -20,7 +20,7 @@ import os class DjangoDebugToolbarStats(Stats): __root = None - + def get_root_func(self): if self.__root is None: for func, (cc, nc, tt, ct, callers) in self.stats.iteritems(): @@ -28,7 +28,7 @@ class DjangoDebugToolbarStats(Stats): self.__root = func break return self.__root - + class FunctionCall(object): def __init__(self, statobj, func, depth=0, stats=None, id=0, parent_ids=[], hsv=(0,0.5,1)): self.statobj = statobj @@ -42,14 +42,14 @@ class FunctionCall(object): self.parent_ids = parent_ids self.hsv = hsv self._line_stats_text = None - + def parent_classes(self): return self.parent_classes - + def background(self): r,g,b = hsv_to_rgb(*self.hsv) return 'rgb(%f%%,%f%%,%f%%)' %(r*100, g*100, b*100) - + def func_std_string(self): # match what old profile produced func_name = self.func if func_name[:2] == ('~', 0): @@ -64,16 +64,16 @@ class FunctionCall(object): idx = file_name.find('/site-packages/') if idx > -1: file_name=file_name[idx+14:] - + file_path, file_name = file_name.rsplit(os.sep, 1) - + return mark_safe('{0}/{1} in {3}({2})'.format( file_path, file_name, line_num, method, )) - + def subfuncs(self): i=0 h,s,v = self.hsv @@ -86,23 +86,23 @@ class FunctionCall(object): else: s1 = s*(stats[3]/self.stats[3]) yield FunctionCall(self.statobj, - func, - self.depth+1, + func, + self.depth+1, stats=stats, id=str(self.id) + '_' + str(i), parent_ids=self.parent_ids + [self.id], hsv=(h1,s1,1)) - + def count(self): return self.stats[1] - + def tottime(self): return self.stats[2] - + def cumtime(self): cc, nc, tt, ct = self.stats return self.stats[3] - + def tottime_per_call(self): cc, nc, tt, ct = self.stats @@ -110,7 +110,7 @@ class FunctionCall(object): return 0 return tt/nc - + def cumtime_per_call(self): cc, nc, tt, ct = self.stats @@ -121,7 +121,7 @@ class FunctionCall(object): def indent(self): return 16 * self.depth - + def line_stats_text(self): if self._line_stats_text is None: lstats = self.statobj.line_stats @@ -146,7 +146,7 @@ class ProfilingDebugPanel(DebugPanel): def url(self): return '' - + def title(self): return _('Profiling') @@ -179,6 +179,8 @@ class ProfilingDebugPanel(DebugPanel): self.stats = DjangoDebugToolbarStats(self.profiler) if DJ_PROFILE_USE_LINE_PROFILER: self.stats.line_stats = self.line_profiler.get_stats() + self.stats.calc_callees() + request.debug_toolbar.stats['profiling'] = self.stats return response def add_node(self, func_list, func, max_depth, cum_time=0.1): @@ -189,12 +191,11 @@ class ProfilingDebugPanel(DebugPanel): if subfunc.stats[3] >= cum_time or (subfunc.func in self.stats.line_stats.timings): func.has_subfuncs = True self.add_node(func_list, subfunc, max_depth, cum_time=cum_time) - + def content(self): - - self.stats.calc_callees() + import ipdb; ipdb.set_trace() root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0) - + func_list = [] self.add_node(func_list, root, 10, root.stats[3]/8) context = self.context.copy() diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 2eced7c..bfe52d9 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -211,6 +211,7 @@ class SQLDebugPanel(DebugPanel): 'sql_time': self._sql_time, } request.debug_toolbar.stats['sql'] = getattr(self, 'stats', None) + return response def content(self): context = self.context.copy() -- cgit v1.2.3 From dddfb118720733a0956440663d659653875b2dd9 Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Sat, 10 Sep 2011 02:25:53 +0200 Subject: Apply the same changes to the timer panel --- debug_toolbar/panels/timer.py | 64 ++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 28 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index d866166..ef32988 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -27,10 +27,38 @@ class TimerDebugPanel(DebugPanel): self._start_rusage = resource.getrusage(resource.RUSAGE_SELF) def process_response(self, request, response): - self.total_time = (time.time() - self._start_time) * 1000 + total_time = (time.time() - self._start_time) * 1000 if self.has_resource: self._end_rusage = resource.getrusage(resource.RUSAGE_SELF) + utime = 1000 * self._elapsed_ru('ru_utime') + stime = 1000 * self._elapsed_ru('ru_stime') + vcsw = self._elapsed_ru('ru_nvcsw') + ivcsw = self._elapsed_ru('ru_nivcsw') + minflt = self._elapsed_ru('ru_minflt') + majflt = self._elapsed_ru('ru_majflt') +# these are documented as not meaningful under Linux. If you're running BSD +# feel free to enable them, and add any others that I hadn't gotten to before +# I noticed that I was getting nothing but zeroes and that the docs agreed. :-( +# +# blkin = self._elapsed_ru('ru_inblock') +# blkout = self._elapsed_ru('ru_oublock') +# swap = self._elapsed_ru('ru_nswap') +# rss = self._end_rusage.ru_maxrss +# srss = self._end_rusage.ru_ixrss +# urss = self._end_rusage.ru_idrss +# usrss = self._end_rusage.ru_isrss + + self.stats = { + 'total_time': total_time, + 'utime': utime, + 'stime': stime, + 'vcsw': vcsw, + 'ivcsw': ivcsw, + 'minflt': minflt, + 'majflt': majflt, + } + def nav_title(self): return _('Time') @@ -39,9 +67,9 @@ class TimerDebugPanel(DebugPanel): if self.has_resource: utime = self._end_rusage.ru_utime - self._start_rusage.ru_utime stime = self._end_rusage.ru_stime - self._start_rusage.ru_stime - return 'CPU: %0.2fms (%0.2fms)' % ((utime + stime) * 1000.0, self.total_time) + return 'CPU: %0.2fms (%0.2fms)' % ((utime + stime) * 1000.0, self.stats['total_time']) else: - return 'TOTAL: %0.2fms' % (self.total_time) + return 'TOTAL: %0.2fms' % (self.stats[total_time]) def title(self): return _('Resource Usage') @@ -53,33 +81,13 @@ class TimerDebugPanel(DebugPanel): return getattr(self._end_rusage, name) - getattr(self._start_rusage, name) def content(self): - - utime = 1000 * self._elapsed_ru('ru_utime') - stime = 1000 * self._elapsed_ru('ru_stime') - vcsw = self._elapsed_ru('ru_nvcsw') - ivcsw = self._elapsed_ru('ru_nivcsw') - minflt = self._elapsed_ru('ru_minflt') - majflt = self._elapsed_ru('ru_majflt') - -# these are documented as not meaningful under Linux. If you're running BSD -# feel free to enable them, and add any others that I hadn't gotten to before -# I noticed that I was getting nothing but zeroes and that the docs agreed. :-( -# -# blkin = self._elapsed_ru('ru_inblock') -# blkout = self._elapsed_ru('ru_oublock') -# swap = self._elapsed_ru('ru_nswap') -# rss = self._end_rusage.ru_maxrss -# srss = self._end_rusage.ru_ixrss -# urss = self._end_rusage.ru_idrss -# usrss = self._end_rusage.ru_isrss - # TODO l10n on values rows = ( - (_('User CPU time'), '%0.3f msec' % utime), - (_('System CPU time'), '%0.3f msec' % stime), - (_('Total CPU time'), '%0.3f msec' % (utime + stime)), - (_('Elapsed time'), '%0.3f msec' % self.total_time), - (_('Context switches'), '%d voluntary, %d involuntary' % (vcsw, ivcsw)), + (_('User CPU time'), '%0.3f msec' % self.stats['utime']), + (_('System CPU time'), '%0.3f msec' % self.stats['stime']), + (_('Total CPU time'), '%0.3f msec' % (self.stats['utime'] + self.stats['stime'])), + (_('Elapsed time'), '%0.3f msec' % self.stats['total_time']), + (_('Context switches'), '%d voluntary, %d involuntary' % (self.stats['vcsw'], self.stats['ivcsw'])), # ('Memory use', '%d max RSS, %d shared, %d unshared' % (rss, srss, urss + usrss)), # ('Page faults', '%d no i/o, %d requiring i/o' % (minflt, majflt)), # ('Disk operations', '%d in, %d out, %d swapout' % (blkin, blkout, swap)), -- cgit v1.2.3 From 83357d374f6741a5cf50da5c4f3f29934ed3281b Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Sat, 10 Sep 2011 02:36:38 +0200 Subject: Also add the BSD specific value and comment them out --- debug_toolbar/panels/timer.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index ef32988..43cc202 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -57,6 +57,13 @@ class TimerDebugPanel(DebugPanel): 'ivcsw': ivcsw, 'minflt': minflt, 'majflt': majflt, +# 'blkin': blkin, +# 'blkout': blkout, +# 'swap': swap, +# 'rss': rss, +# 'urss': urss, +# 'srss': srss, +# 'usrss': usrss, } def nav_title(self): @@ -88,9 +95,10 @@ class TimerDebugPanel(DebugPanel): (_('Total CPU time'), '%0.3f msec' % (self.stats['utime'] + self.stats['stime'])), (_('Elapsed time'), '%0.3f msec' % self.stats['total_time']), (_('Context switches'), '%d voluntary, %d involuntary' % (self.stats['vcsw'], self.stats['ivcsw'])), -# ('Memory use', '%d max RSS, %d shared, %d unshared' % (rss, srss, urss + usrss)), -# ('Page faults', '%d no i/o, %d requiring i/o' % (minflt, majflt)), -# ('Disk operations', '%d in, %d out, %d swapout' % (blkin, blkout, swap)), +# ('Memory use', '%d max RSS, %d shared, %d unshared' % (self.stats['rss'], self.stats.['srss'], +# self.stats['urss'] + self.stats['usrss'])), +# ('Page faults', '%d no i/o, %d requiring i/o' % (self.stats['minflt'], self.stats['majflt'])), +# ('Disk operations', '%d in, %d out, %d swapout' % (self.stats['blkin'], self.stats['blkout'], self.stats['swap'])), ) context = self.context.copy() -- cgit v1.2.3 From d3649d340a9a7e20235fa63615830b9b0b7edbdd Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Sun, 11 Sep 2011 05:16:47 +0200 Subject: Fix the profiling panel when the line_profiler module is not available. --- debug_toolbar/panels/profiling.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index 623b27a..e57aa97 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -123,7 +123,8 @@ class FunctionCall(object): return 16 * self.depth def line_stats_text(self): - if self._line_stats_text is None: + if (self._line_stats_text is None and + DJ_PROFILE_USE_LINE_PROFILER): lstats = self.statobj.line_stats if self.func in lstats.timings: out = StringIO() @@ -188,12 +189,13 @@ class ProfilingDebugPanel(DebugPanel): func.has_subfuncs = False if func.depth < max_depth: for subfunc in func.subfuncs(): - if subfunc.stats[3] >= cum_time or (subfunc.func in self.stats.line_stats.timings): + if (subfunc.stats[3] >= cum_time or + (hasattr(self.stats, 'line_stats') and + (subfunc.func in self.stats.line_stats.timings))): func.has_subfuncs = True self.add_node(func_list, subfunc, max_depth, cum_time=cum_time) def content(self): - import ipdb; ipdb.set_trace() root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0) func_list = [] -- cgit v1.2.3 From 2682e29116522cb64fd6e7c9d776a1e3b4c25a3a Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Sun, 11 Sep 2011 05:30:17 +0200 Subject: pep 8 compliance --- debug_toolbar/panels/profiling.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index e57aa97..01ae1e0 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -18,6 +18,7 @@ from pstats import Stats from colorsys import hsv_to_rgb import os + class DjangoDebugToolbarStats(Stats): __root = None @@ -29,8 +30,10 @@ class DjangoDebugToolbarStats(Stats): break return self.__root + class FunctionCall(object): - def __init__(self, statobj, func, depth=0, stats=None, id=0, parent_ids=[], hsv=(0,0.5,1)): + def __init__(self, statobj, func, depth=0, stats=None, + id=0, parent_ids=[], hsv=(0,0.5,1)): self.statobj = statobj self.func = func if stats: @@ -50,7 +53,7 @@ class FunctionCall(object): r,g,b = hsv_to_rgb(*self.hsv) return 'rgb(%f%%,%f%%,%f%%)' %(r*100, g*100, b*100) - def func_std_string(self): # match what old profile produced + def func_std_string(self): # match what old profile produced func_name = self.func if func_name[:2] == ('~', 0): # special case for built-in functions @@ -63,7 +66,7 @@ class FunctionCall(object): file_name, line_num, method = self.func idx = file_name.find('/site-packages/') if idx > -1: - file_name=file_name[idx+14:] + file_name = file_name[idx+14:] file_path, file_name = file_name.rsplit(os.sep, 1) @@ -76,7 +79,7 @@ class FunctionCall(object): def subfuncs(self): i=0 - h,s,v = self.hsv + h, s, v = self.hsv count = len(self.statobj.all_callees[self.func]) for func, stats in self.statobj.all_callees[self.func].iteritems(): i += 1 -- cgit v1.2.3 From e0aa1e9dd987cc43996647b6096fb6a21b77ab29 Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Sun, 11 Sep 2011 06:01:08 +0200 Subject: linting- Remove unused import --- debug_toolbar/panels/version.py | 1 - 1 file changed, 1 deletion(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/version.py b/debug_toolbar/panels/version.py index f0d8fbc..e042732 100644 --- a/debug_toolbar/panels/version.py +++ b/debug_toolbar/panels/version.py @@ -5,7 +5,6 @@ from django.conf import settings from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ -import debug_toolbar from debug_toolbar.panels import DebugPanel -- cgit v1.2.3 From 7dfb666ae92ba2831926a003d26480a00a5dff30 Mon Sep 17 00:00:00 2001 From: Yann Malet Date: Sun, 11 Sep 2011 06:18:59 +0200 Subject: Modify the Version panel --- debug_toolbar/panels/version.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/version.py b/debug_toolbar/panels/version.py index e042732..76e44ed 100644 --- a/debug_toolbar/panels/version.py +++ b/debug_toolbar/panels/version.py @@ -23,11 +23,11 @@ class VersionDebugPanel(DebugPanel): def url(self): return '' - + def title(self): return _('Versions') - def content(self): + def process_response(self, request, response): versions = {} versions['Python'] = '%d.%d.%d' % sys.version_info[:3] for app in settings.INSTALLED_APPS + ['django']: @@ -49,11 +49,15 @@ class VersionDebugPanel(DebugPanel): if isinstance(version, (list, tuple)): version = '.'.join(str(o) for o in version) versions[name] = version + self.stats = { + 'versions': versions, + 'paths': sys.path + } + request.debug_toolbar.stats['versions'] = self.stats['versions'] + request.debug_toolbar.stats['paths'] = self.stats['paths'] + return response + def content(self): context = self.context.copy() - context.update({ - 'versions': versions, - 'paths': sys.path, - }) - + context.update(self.stats) return render_to_string('debug_toolbar/panels/versions.html', context) -- cgit v1.2.3 From b77aec6160d66ee1ecff2687d74724ce74ea8ff5 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 11:21:29 -0500 Subject: Don't add the toolbar to the request object until the end of the process_response method --- debug_toolbar/middleware.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index 1d332c0..b014f33 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -96,7 +96,6 @@ class DebugToolbarMiddleware(object): for panel in toolbar.panels: panel.process_request(request) self.__class__.debug_toolbars[thread.get_ident()] = toolbar - request.debug_toolbar = toolbar def process_view(self, request, view_func, view_args, view_kwargs): __traceback_hide__ = True @@ -127,12 +126,15 @@ class DebugToolbarMiddleware(object): response.get('Content-Type', '').split(';')[0] in _HTML_TYPES: toolbar.stats = {} for panel in toolbar.panels: - panel.process_response(request, response) + panel.process_response(request, response) response.content = replace_insensitive( - smart_unicode(response.content), - self.tag, - smart_unicode(toolbar.render_toolbar() + self.tag)) + smart_unicode(response.content), + self.tag, + smart_unicode(toolbar.render_toolbar() + self.tag)) if response.get('Content-Length', None): response['Content-Length'] = len(response.content) + # Add the toolbar to the request object, so that the stats are + # available to subsequent middleware classes. + request.debug_toolbar = toolbar del self.__class__.debug_toolbars[ident] return response -- cgit v1.2.3 From 74a7c2f3209b8561e71a140842877ee89fc6c725 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 11:25:35 -0500 Subject: Update the cache panel to use the toolbar object --- debug_toolbar/panels/cache.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index 4cc783e..bbfed66 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -5,6 +5,7 @@ from django.core import cache from django.core.cache.backends.base import BaseCache from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ +from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel class CacheStatTracker(BaseCache): @@ -101,8 +102,8 @@ class CacheDebugPanel(DebugPanel): 'cache_time': self.cache.total_time, 'cache': self.cache, } - request.debug_toolbar.stats['cache'] = self.stats - return response + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['cache'] = self.stats def content(self): context = self.context.copy() -- cgit v1.2.3 From d9e9d8bbddb9986db79047a40194232f1baadf50 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 11:33:18 -0500 Subject: Tweaked the sql panel --- debug_toolbar/panels/sql.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index bfe52d9..2c36336 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -210,8 +210,8 @@ class SQLDebugPanel(DebugPanel): 'queries': [q for a, q in self._queries], 'sql_time': self._sql_time, } - request.debug_toolbar.stats['sql'] = getattr(self, 'stats', None) - return response + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['sql'] = self.stats def content(self): context = self.context.copy() -- cgit v1.2.3 From 48dca6e339b6e22de0ae2a570c0c71ff98831886 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 11:38:46 -0500 Subject: Cleaned up whitespace in the SQL and cache panels --- debug_toolbar/panels/cache.py | 24 ++++++++++----------- debug_toolbar/panels/sql.py | 50 +++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 37 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index bbfed66..ad3f844 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -13,7 +13,7 @@ class CacheStatTracker(BaseCache): def __init__(self, cache): self.cache = cache self.reset() - + def reset(self): self.calls = [] self.hits = 0 @@ -23,11 +23,11 @@ class CacheStatTracker(BaseCache): self.get_many = 0 self.deletes = 0 self.total_time = 0 - + def _get_func_info(self): stack = inspect.stack()[2] return (stack[1], stack[2], stack[3], stack[4]) - + def get(self, key, default=None): t = time.time() value = self.cache.get(key, default) @@ -40,7 +40,7 @@ class CacheStatTracker(BaseCache): self.gets += 1 self.calls.append((this_time, 'get', (key,), self._get_func_info())) return value - + def set(self, key, value, timeout=None): t = time.time() self.cache.set(key, value, timeout) @@ -48,7 +48,7 @@ class CacheStatTracker(BaseCache): self.total_time += this_time * 1000 self.sets += 1 self.calls.append((this_time, 'set', (key, value, timeout), self._get_func_info())) - + def delete(self, key): t = time.time() self.cache.delete(key) @@ -56,7 +56,7 @@ class CacheStatTracker(BaseCache): self.total_time += this_time * 1000 self.deletes += 1 self.calls.append((this_time, 'delete', (key,), self._get_func_info())) - + def get_many(self, keys): t = time.time() results = self.cache.get_many(keys) @@ -76,7 +76,7 @@ class CacheDebugPanel(DebugPanel): """ name = 'Cache' has_content = True - + def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) # This is hackish but to prevent threading issues is somewhat needed @@ -86,16 +86,16 @@ class CacheDebugPanel(DebugPanel): else: self.cache = CacheStatTracker(cache.cache) cache.cache = self.cache - + def nav_title(self): return _('Cache: %.2fms') % self.cache.total_time - + def title(self): return _('Cache Usage') - + def url(self): return '' - + def process_response(self, request, response): self.stats = { 'cache_calls': len(self.cache.calls), @@ -104,7 +104,7 @@ class CacheDebugPanel(DebugPanel): } toolbar = DebugToolbarMiddleware.get_current() toolbar.stats['cache'] = self.stats - + def content(self): context = self.context.copy() context.update(self.stats) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 2c36336..9527410 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -18,12 +18,12 @@ from debug_toolbar.utils.tracking import replace_call @replace_call(BaseDatabaseWrapper.cursor) def cursor(func, self): result = func(self) - + djdt = DebugToolbarMiddleware.get_current() if not djdt: return result logger = djdt.get_panel(SQLDebugPanel) - + return CursorWrapper(result, self, logger=logger) def get_isolation_level_display(engine, level): @@ -38,7 +38,7 @@ def get_isolation_level_display(engine, level): } else: raise ValueError(engine) - + return choices.get(level) def get_transaction_status_display(engine, level): @@ -53,7 +53,7 @@ def get_transaction_status_display(engine, level): } else: raise ValueError(engine) - + return choices.get(level) class SQLDebugPanel(DebugPanel): @@ -63,7 +63,7 @@ class SQLDebugPanel(DebugPanel): """ name = 'SQL' has_content = True - + def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) self._offset = dict((k, len(connections[k].queries)) for k in connections) @@ -73,33 +73,33 @@ class SQLDebugPanel(DebugPanel): self._databases = {} self._transaction_status = {} self._transaction_ids = {} - + def get_transaction_id(self, alias): conn = connections[alias].connection if not conn: return None - + engine = conn.__class__.__module__.split('.', 1)[0] if engine == 'psycopg2': cur_status = conn.get_transaction_status() else: raise ValueError(engine) - + last_status = self._transaction_status.get(alias) self._transaction_status[alias] = cur_status - + if not cur_status: # No available state return None - + if cur_status != last_status: if cur_status: self._transaction_ids[alias] = uuid.uuid4().hex else: self._transaction_ids[alias] = None - + return self._transaction_ids[alias] - + def record(self, alias, **kwargs): self._queries.append((alias, kwargs)) if alias not in self._databases: @@ -112,10 +112,10 @@ class SQLDebugPanel(DebugPanel): self._databases[alias]['num_queries'] += 1 self._sql_time += kwargs['duration'] self._num_queries += 1 - + def nav_title(self): return _('SQL') - + def nav_subtitle(self): # TODO l10n: use ngettext return "%d %s in %.2fms" % ( @@ -123,17 +123,17 @@ class SQLDebugPanel(DebugPanel): (self._num_queries == 1) and 'query' or 'queries', self._sql_time ) - + def title(self): count = len(self._databases) - + return __('SQL Queries from %(count)d connection', 'SQL Queries from %(count)d connections', count) % dict( count=count, ) - + def url(self): return '' - + def process_response(self, request, response): if self._queries: width_ratio_tally = 0 @@ -157,14 +157,14 @@ class SQLDebugPanel(DebugPanel): nn = 0 rgb[nn] = nc db['rgb_color'] = rgb - + trans_ids = {} trans_id = None i = 0 for alias, query in self._queries: trans_id = query.get('trans_id') last_trans_id = trans_ids.get(alias) - + if trans_id != last_trans_id: if last_trans_id: self._queries[i-1][1]['ends_trans'] = True @@ -173,7 +173,7 @@ class SQLDebugPanel(DebugPanel): query['starts_trans'] = True if trans_id: query['in_trans'] = True - + query['alias'] = alias if 'iso_level' in query: query['iso_level'] = get_isolation_level_display(query['engine'], query['iso_level']) @@ -190,7 +190,7 @@ class SQLDebugPanel(DebugPanel): query['start_offset'] = width_ratio_tally query['end_offset'] = query['width_ratio'] + query['start_offset'] width_ratio_tally += query['width_ratio'] - + stacktrace = [] for frame in query['stacktrace']: params = map(escape, frame[0].rsplit('/', 1) + list(frame[1:])) @@ -201,10 +201,10 @@ class SQLDebugPanel(DebugPanel): continue query['stacktrace'] = mark_safe('\n'.join(stacktrace)) i += 1 - + if trans_id: self._queries[i-1][1]['ends_trans'] = True - + self.stats = { 'databases': sorted(self._databases.items(), key=lambda x: -x[1]['time_spent']), 'queries': [q for a, q in self._queries], @@ -212,7 +212,7 @@ class SQLDebugPanel(DebugPanel): } toolbar = DebugToolbarMiddleware.get_current() toolbar.stats['sql'] = self.stats - + def content(self): context = self.context.copy() context.update(self.stats) -- cgit v1.2.3 From f8759c9f0d64a90ac0e1942e735c27c662ab05b1 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 11:54:19 -0500 Subject: Tweaked the profiling panel --- debug_toolbar/panels/profiling.py | 64 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index 01ae1e0..26f7888 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -21,7 +21,7 @@ import os class DjangoDebugToolbarStats(Stats): __root = None - + def get_root_func(self): if self.__root is None: for func, (cc, nc, tt, ct, callers) in self.stats.iteritems(): @@ -45,15 +45,15 @@ class FunctionCall(object): self.parent_ids = parent_ids self.hsv = hsv self._line_stats_text = None - + def parent_classes(self): return self.parent_classes - + def background(self): r,g,b = hsv_to_rgb(*self.hsv) return 'rgb(%f%%,%f%%,%f%%)' %(r*100, g*100, b*100) - - def func_std_string(self): # match what old profile produced + + def func_std_string(self): # match what old profile produced func_name = self.func if func_name[:2] == ('~', 0): # special case for built-in functions @@ -67,16 +67,16 @@ class FunctionCall(object): idx = file_name.find('/site-packages/') if idx > -1: file_name = file_name[idx+14:] - + file_path, file_name = file_name.rsplit(os.sep, 1) - + return mark_safe('{0}/{1} in {3}({2})'.format( file_path, file_name, line_num, method, )) - + def subfuncs(self): i=0 h, s, v = self.hsv @@ -95,39 +95,38 @@ class FunctionCall(object): id=str(self.id) + '_' + str(i), parent_ids=self.parent_ids + [self.id], hsv=(h1,s1,1)) - + def count(self): return self.stats[1] - + def tottime(self): return self.stats[2] - + def cumtime(self): cc, nc, tt, ct = self.stats return self.stats[3] - + def tottime_per_call(self): cc, nc, tt, ct = self.stats - + if nc == 0: return 0 - + return tt/nc - + def cumtime_per_call(self): cc, nc, tt, ct = self.stats - + if cc == 0: return 0 - + return ct/cc - + def indent(self): return 16 * self.depth - + def line_stats_text(self): - if (self._line_stats_text is None and - DJ_PROFILE_USE_LINE_PROFILER): + if self._line_stats_text is None and DJ_PROFILE_USE_LINE_PROFILER: lstats = self.statobj.line_stats if self.func in lstats.timings: out = StringIO() @@ -144,16 +143,16 @@ class ProfilingDebugPanel(DebugPanel): """ name = 'Profiling' has_content = True - + def nav_title(self): return _('Profiling') - + def url(self): return '' - + def title(self): return _('Profiling') - + def _unwrap_closure_and_profile(self, func): if not hasattr(func, 'func_code'): return @@ -162,7 +161,7 @@ class ProfilingDebugPanel(DebugPanel): for cell in func.func_closure: if hasattr(cell.cell_contents, 'func_code'): self._unwrap_closure_and_profile(cell.cell_contents) - + def process_view(self, request, view_func, view_args, view_kwargs): __traceback_hide__ = True self.profiler = cProfile.Profile() @@ -177,16 +176,17 @@ class ProfilingDebugPanel(DebugPanel): self.line_profiler = None out = self.profiler.runcall(view_func, *args, **view_kwargs) return out - + def process_response(self, request, response): self.profiler.create_stats() self.stats = DjangoDebugToolbarStats(self.profiler) if DJ_PROFILE_USE_LINE_PROFILER: self.stats.line_stats = self.line_profiler.get_stats() self.stats.calc_callees() - request.debug_toolbar.stats['profiling'] = self.stats + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['profiling'] = self.stats return response - + def add_node(self, func_list, func, max_depth, cum_time=0.1): func_list.append(func) func.has_subfuncs = False @@ -197,15 +197,15 @@ class ProfilingDebugPanel(DebugPanel): (subfunc.func in self.stats.line_stats.timings))): func.has_subfuncs = True self.add_node(func_list, subfunc, max_depth, cum_time=cum_time) - + def content(self): root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0) - + func_list = [] self.add_node(func_list, root, 10, root.stats[3]/8) context = self.context.copy() context.update({ 'func_list': func_list, }) - + return render_to_string('debug_toolbar/panels/profiling.html', context) -- cgit v1.2.3 From 6c005d703941fc60dd8ecc07ad8bdaf3e27b2950 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 11:59:44 -0500 Subject: Tweaks to the timer panel, and a correction to the profiling panel --- debug_toolbar/panels/profiling.py | 1 + debug_toolbar/panels/timer.py | 34 +++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index 26f7888..e08591a 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -3,6 +3,7 @@ from __future__ import division from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from django.utils.safestring import mark_safe +from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel try: diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index 43cc202..1e44212 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -5,6 +5,7 @@ except ImportError: import time from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ +from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel class TimerDebugPanel(DebugPanel): @@ -50,21 +51,24 @@ class TimerDebugPanel(DebugPanel): # usrss = self._end_rusage.ru_isrss self.stats = { - 'total_time': total_time, - 'utime': utime, - 'stime': stime, - 'vcsw': vcsw, - 'ivcsw': ivcsw, - 'minflt': minflt, - 'majflt': majflt, -# 'blkin': blkin, -# 'blkout': blkout, -# 'swap': swap, -# 'rss': rss, -# 'urss': urss, -# 'srss': srss, -# 'usrss': usrss, - } + 'total_time': total_time, + 'utime': utime, + 'stime': stime, + 'vcsw': vcsw, + 'ivcsw': ivcsw, + 'minflt': minflt, + 'majflt': majflt, +# 'blkin': blkin, +# 'blkout': blkout, +# 'swap': swap, +# 'rss': rss, +# 'urss': urss, +# 'srss': srss, +# 'usrss': usrss, + } + + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['timer'] = self.stats def nav_title(self): return _('Time') -- cgit v1.2.3 From e99c3acd249cc05e1e85ec9a60b5a87685a79f78 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 12:02:25 -0500 Subject: Tweaks to the version panel, and whitespace corrections for the timer panel --- debug_toolbar/panels/timer.py | 24 ++++++++++++------------ debug_toolbar/panels/version.py | 14 ++++++++------ 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index 1e44212..466e5c0 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -21,17 +21,17 @@ class TimerDebugPanel(DebugPanel): else: has_content = True has_resource = True - + def process_request(self, request): self._start_time = time.time() if self.has_resource: self._start_rusage = resource.getrusage(resource.RUSAGE_SELF) - + def process_response(self, request, response): total_time = (time.time() - self._start_time) * 1000 if self.has_resource: self._end_rusage = resource.getrusage(resource.RUSAGE_SELF) - + utime = 1000 * self._elapsed_ru('ru_utime') stime = 1000 * self._elapsed_ru('ru_stime') vcsw = self._elapsed_ru('ru_nvcsw') @@ -49,7 +49,7 @@ class TimerDebugPanel(DebugPanel): # srss = self._end_rusage.ru_ixrss # urss = self._end_rusage.ru_idrss # usrss = self._end_rusage.ru_isrss - + self.stats = { 'total_time': total_time, 'utime': utime, @@ -69,10 +69,10 @@ class TimerDebugPanel(DebugPanel): toolbar = DebugToolbarMiddleware.get_current() toolbar.stats['timer'] = self.stats - + def nav_title(self): return _('Time') - + def nav_subtitle(self): # TODO l10n if self.has_resource: @@ -81,16 +81,16 @@ class TimerDebugPanel(DebugPanel): return 'CPU: %0.2fms (%0.2fms)' % ((utime + stime) * 1000.0, self.stats['total_time']) else: return 'TOTAL: %0.2fms' % (self.stats[total_time]) - + def title(self): return _('Resource Usage') - + def url(self): return '' - + def _elapsed_ru(self, name): return getattr(self._end_rusage, name) - getattr(self._start_rusage, name) - + def content(self): # TODO l10n on values rows = ( @@ -104,10 +104,10 @@ class TimerDebugPanel(DebugPanel): # ('Page faults', '%d no i/o, %d requiring i/o' % (self.stats['minflt'], self.stats['majflt'])), # ('Disk operations', '%d in, %d out, %d swapout' % (self.stats['blkin'], self.stats['blkout'], self.stats['swap'])), ) - + context = self.context.copy() context.update({ 'rows': rows, }) - + return render_to_string('debug_toolbar/panels/timer.html', context) diff --git a/debug_toolbar/panels/version.py b/debug_toolbar/panels/version.py index 76e44ed..c18da63 100644 --- a/debug_toolbar/panels/version.py +++ b/debug_toolbar/panels/version.py @@ -5,6 +5,7 @@ from django.conf import settings from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ +from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel @@ -49,13 +50,14 @@ class VersionDebugPanel(DebugPanel): if isinstance(version, (list, tuple)): version = '.'.join(str(o) for o in version) versions[name] = version + self.stats = { - 'versions': versions, - 'paths': sys.path - } - request.debug_toolbar.stats['versions'] = self.stats['versions'] - request.debug_toolbar.stats['paths'] = self.stats['paths'] - return response + 'versions': versions, + 'paths': sys.path, + } + + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['version'] = self.stats def content(self): context = self.context.copy() -- cgit v1.2.3 From 2b3dc54bccff7463c100b689f84d2af259f1db77 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 12:02:39 -0500 Subject: Minor whitespace correction for the version panel --- debug_toolbar/panels/version.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/version.py b/debug_toolbar/panels/version.py index c18da63..6a7c54e 100644 --- a/debug_toolbar/panels/version.py +++ b/debug_toolbar/panels/version.py @@ -15,19 +15,19 @@ class VersionDebugPanel(DebugPanel): """ name = 'Version' has_content = True - + def nav_title(self): return _('Versions') - + def nav_subtitle(self): return 'Django %s' % django.get_version() - + def url(self): return '' - + def title(self): return _('Versions') - + def process_response(self, request, response): versions = {} versions['Python'] = '%d.%d.%d' % sys.version_info[:3] @@ -58,7 +58,7 @@ class VersionDebugPanel(DebugPanel): toolbar = DebugToolbarMiddleware.get_current() toolbar.stats['version'] = self.stats - + def content(self): context = self.context.copy() context.update(self.stats) -- cgit v1.2.3 From 5f7a6aa2658c019eddf5696fec051199fe0e64ec Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 12:04:53 -0500 Subject: Updated the headers panel --- debug_toolbar/panels/headers.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py index cedd3ee..4c94dd9 100644 --- a/debug_toolbar/panels/headers.py +++ b/debug_toolbar/panels/headers.py @@ -1,6 +1,8 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel +from debug_toolbar.middleware import DebugToolbarMiddleware + class HeaderDebugPanel(DebugPanel): """ @@ -31,27 +33,31 @@ class HeaderDebugPanel(DebugPanel): 'SERVER_PROTOCOL', 'SERVER_SOFTWARE', ) - + def nav_title(self): return _('HTTP Headers') - + def title(self): return _('HTTP Headers') - + def url(self): return '' - + def process_request(self, request): self.headers = dict( [(k, request.META[k]) for k in self.header_filter if k in request.META] ) - + self.stats = { + 'headers': self.headers + } + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['headers'] = self.stats + + def process_response(self, request, response): request.debug_toolbar.stats['headers'] = self.headers - + def content(self): context = self.context.copy() - context.update({ - 'headers': self.headers - }) + context.update(self.stats) return render_to_string('debug_toolbar/panels/headers.html', context) -- cgit v1.2.3 From 12decd75ddaf805b8a2f333102f2752161338eb9 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 12:07:01 -0500 Subject: Updated the logger panel --- debug_toolbar/panels/logger.py | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/logger.py b/debug_toolbar/panels/logger.py index 5e82a13..ba34700 100644 --- a/debug_toolbar/panels/logger.py +++ b/debug_toolbar/panels/logger.py @@ -7,6 +7,7 @@ except ImportError: from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel +from debug_toolbar.middleware import DebugToolbarMiddleware class LogCollector(object): @@ -15,15 +16,15 @@ class LogCollector(object): raise NotImplementedError("threading module is not available, \ the logging panel cannot be used without it") self.records = {} # a dictionary that maps threads to log records - + def add_record(self, record, thread=None): # Avoid logging SQL queries since they are already in the SQL panel # TODO: Make this check whether SQL panel is enabled if record.get('channel', '') == 'django.db.backends': return - + self.get_records(thread).append(record) - + def get_records(self, thread=None): """ Returns a list of records for the provided thread, of if none is provided, @@ -34,7 +35,7 @@ class LogCollector(object): if thread not in self.records: self.records[thread] = [] return self.records[thread] - + def clear_records(self, thread=None): if thread is None: thread = threading.currentThread() @@ -46,7 +47,7 @@ class ThreadTrackingHandler(logging.Handler): def __init__(self, collector): logging.Handler.__init__(self) self.collector = collector - + def emit(self, record): record = { 'message': record.getMessage(), @@ -76,7 +77,7 @@ if logbook_supported: def __init__(self, collector): logbook.handlers.Handler.__init__(self, bubble=True) self.collector = collector - + def emit(self, record): record = { 'message': record.message, @@ -88,39 +89,43 @@ if logbook_supported: } self.collector.add_record(record) - + logbook_handler = LogbookThreadTrackingHandler(collector) logbook_handler.push_application() # register with logbook class LoggingPanel(DebugPanel): name = 'Logging' has_content = True - + def process_request(self, request): collector.clear_records() - + + def process_response(self, request, response): + records = self.get_and_delete() + self.stats = {'records': records} + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['logger'] = self.stats + def get_and_delete(self): records = collector.get_records() collector.clear_records() return records - + def nav_title(self): return _("Logging") - + def nav_subtitle(self): # FIXME l10n: use ngettext return "%s message%s" % (len(collector.get_records()), (len(collector.get_records()) == 1) and '' or 's') - + def title(self): return _('Log Messages') - + def url(self): return '' - + def content(self): - records = self.get_and_delete() context = self.context.copy() - context.update({'records': records}) - + context.update(self.stats) return render_to_string('debug_toolbar/panels/logger.html', context) -- cgit v1.2.3 From 3e06ce8a73d03a9f1c7ab1a424c8dfd350d99ec4 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 12:10:38 -0500 Subject: Updated the request_vars panel --- debug_toolbar/panels/request_vars.py | 40 +++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/request_vars.py b/debug_toolbar/panels/request_vars.py index 9033d48..80cd018 100644 --- a/debug_toolbar/panels/request_vars.py +++ b/debug_toolbar/panels/request_vars.py @@ -1,6 +1,7 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ +from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel from debug_toolbar.utils import get_name_from_obj @@ -10,53 +11,58 @@ class RequestVarsDebugPanel(DebugPanel): """ name = 'RequestVars' has_content = True - + def __init__(self, *args, **kwargs): DebugPanel.__init__(self, *args, **kwargs) self.view_func = None self.view_args = None self.view_kwargs = None - + def nav_title(self): return _('Request Vars') - + def title(self): return _('Request Vars') - + def url(self): return '' - + def process_request(self, request): self.request = request - + def process_view(self, request, view_func, view_args, view_kwargs): self.view_func = view_func self.view_args = view_args self.view_kwargs = view_kwargs - - def content(self): - context = self.context.copy() - - context.update({ + + def process_response(self, request, response): + self.stats = { 'get': [(k, self.request.GET.getlist(k)) for k in self.request.GET], 'post': [(k, self.request.POST.getlist(k)) for k in self.request.POST], 'cookies': [(k, self.request.COOKIES.get(k)) for k in self.request.COOKIES], - }) + } + if hasattr(self, 'view_func'): if self.view_func is not None: name = get_name_from_obj(self.view_func) else: name = '' - - context.update({ + + self.stats.update({ 'view_func': name, 'view_args': self.view_args, 'view_kwargs': self.view_kwargs }) - + if hasattr(self.request, 'session'): - context.update({ + self.stats.update({ 'session': [(k, self.request.session.get(k)) for k in self.request.session.iterkeys()] }) - + + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['request_vars'] = self.stats + + def content(self): + context = self.context.copy() + context.update(self.stats) return render_to_string('debug_toolbar/panels/request_vars.html', context) -- cgit v1.2.3 From fa8e9aab09cd47370749e1a03f2e90e6a7a93faf Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 12:11:38 -0500 Subject: Updated the settings_vars panel --- debug_toolbar/panels/settings_vars.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/settings_vars.py b/debug_toolbar/panels/settings_vars.py index ebb4464..029496e 100644 --- a/debug_toolbar/panels/settings_vars.py +++ b/debug_toolbar/panels/settings_vars.py @@ -2,6 +2,7 @@ from django.conf import settings from django.template.loader import render_to_string from django.views.debug import get_safe_settings from django.utils.translation import ugettext_lazy as _ +from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel @@ -11,19 +12,24 @@ class SettingsVarsDebugPanel(DebugPanel): """ name = 'SettingsVars' has_content = True - + def nav_title(self): return _('Settings') - + def title(self): return _('Settings from %s') % settings.SETTINGS_MODULE - + def url(self): return '' - + + def process_response(self, request, response): + self.stats = { + 'settings': get_safe_settings(), + } + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['settings_vars'] = self.stats + def content(self): context = self.context.copy() - context.update({ - 'settings': get_safe_settings(), - }) + context.update(self.stats) return render_to_string('debug_toolbar/panels/settings_vars.html', context) -- cgit v1.2.3 From 2519b2cc5cda4b462de108cac1d9dd2fae2e9dd4 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 12:12:58 -0500 Subject: Updated the signals panel --- debug_toolbar/panels/signals.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/signals.py b/debug_toolbar/panels/signals.py index dbd3725..9855299 100644 --- a/debug_toolbar/panels/signals.py +++ b/debug_toolbar/panels/signals.py @@ -14,12 +14,13 @@ try: except ImportError: connection_created = None +from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel class SignalDebugPanel(DebugPanel): name = "Signals" has_content = True - + SIGNALS = { 'request_started': request_started, 'request_finished': request_finished, @@ -34,16 +35,16 @@ class SignalDebugPanel(DebugPanel): 'post_delete': post_delete, 'post_syncdb': post_syncdb, } - + def nav_title(self): return _("Signals") - + def title(self): return _("Signals") - + def url(self): return '' - + def signals(self): signals = self.SIGNALS.copy() if hasattr(settings, 'DEBUG_TOOLBAR_CONFIG'): @@ -57,8 +58,8 @@ class SignalDebugPanel(DebugPanel): signals[parts[-1]] = getattr(sys.modules[path], parts[-1]) return signals signals = property(signals) - - def content(self): + + def process_response(self, request, response): signals = [] keys = self.signals.keys() keys.sort() @@ -80,8 +81,12 @@ class SignalDebugPanel(DebugPanel): text = "function %s" % receiver.__name__ receivers.append(text) signals.append((name, signal, receivers)) - + + self.stats = {'signals': signals} + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['signals'] = self.stats + + def content(self): context = self.context.copy() - context.update({'signals': signals}) - + context.update(self.stats) return render_to_string('debug_toolbar/panels/signals.html', context) -- cgit v1.2.3 From 5b4553713775a35634594a65502e5ca8ba58dae9 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 12:31:25 -0500 Subject: Updated the template panel, and corrected an issue in the headers panel --- debug_toolbar/middleware.py | 2 +- debug_toolbar/panels/headers.py | 6 ++---- debug_toolbar/panels/template.py | 34 ++++++++++++++++++++-------------- 3 files changed, 23 insertions(+), 19 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index b014f33..03b2804 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -123,7 +123,7 @@ class DebugToolbarMiddleware(object): ) response.cookies = cookies if 'gzip' not in response.get('Content-Encoding', '') and \ - response.get('Content-Type', '').split(';')[0] in _HTML_TYPES: + response.get('Content-Type', '').split(';')[0] in _HTML_TYPES: toolbar.stats = {} for panel in toolbar.panels: panel.process_response(request, response) diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py index 4c94dd9..a88fbd9 100644 --- a/debug_toolbar/panels/headers.py +++ b/debug_toolbar/panels/headers.py @@ -47,16 +47,14 @@ class HeaderDebugPanel(DebugPanel): self.headers = dict( [(k, request.META[k]) for k in self.header_filter if k in request.META] ) + + def process_response(self, request, response): self.stats = { 'headers': self.headers } toolbar = DebugToolbarMiddleware.get_current() toolbar.stats['headers'] = self.stats - - def process_response(self, request, response): - request.debug_toolbar.stats['headers'] = self.headers - def content(self): context = self.context.copy() context.update(self.stats) diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index d620a38..d0ab6cc 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -7,6 +7,7 @@ from django.template.context import get_standard_processors from django.template.loader import render_to_string from django.test.signals import template_rendered from django.utils.translation import ugettext_lazy as _ +from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel # Code taken and adapted from Simon Willison and Django Snippets: @@ -40,15 +41,15 @@ class TemplateDebugPanel(DebugPanel): """ name = 'Template' has_content = True - + def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) self.templates = [] template_rendered.connect(self._store_template_info) - + def _store_template_info(self, sender, **kwargs): context_data = kwargs['context'] - + context_list = [] for context_layer in context_data.dicts: temp_layer = {} @@ -74,22 +75,22 @@ class TemplateDebugPanel(DebugPanel): pass kwargs['context'] = context_list self.templates.append(kwargs) - + def nav_title(self): return _('Templates') - + def title(self): num_templates = len([t for t in self.templates if not (t['template'].name and t['template'].name.startswith('debug_toolbar/'))]) return _('Templates (%(num_templates)s rendered)') % {'num_templates': num_templates} - + def url(self): return '' - + def process_request(self, request): self.request = request - - def content(self): + + def process_response(self, request, response): context_processors = dict( [ ("%s.%s" % (k.__module__, k.__name__), @@ -116,12 +117,17 @@ class TemplateDebugPanel(DebugPanel): context_list = template_data.get('context', []) info['context'] = '\n'.join(context_list) template_context.append(info) - - context = self.context.copy() - context.update({ + + self.stats = { 'templates': template_context, 'template_dirs': [normpath(x) for x in settings.TEMPLATE_DIRS], 'context_processors': context_processors, - }) - + } + + toolbar = DebugToolbarMiddleware.get_current() + toolbar.stats['template'] = self.stats + + def content(self): + context = self.context.copy() + context.update(self.stats) return render_to_string('debug_toolbar/panels/templates.html', context) -- cgit v1.2.3 From 0ef39192ecf7ebc359f3ad3a87fbf962b568397b Mon Sep 17 00:00:00 2001 From: bkonkle Date: Mon, 12 Sep 2011 13:11:08 -0500 Subject: Don't add the entire toolbar to the request object, just the stats --- debug_toolbar/middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index 03b2804..ccd4778 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -135,6 +135,6 @@ class DebugToolbarMiddleware(object): response['Content-Length'] = len(response.content) # Add the toolbar to the request object, so that the stats are # available to subsequent middleware classes. - request.debug_toolbar = toolbar + request.debug_toolbar_stats = toolbar.stats del self.__class__.debug_toolbars[ident] return response -- cgit v1.2.3 From 36a2f1d85d615db3c8eda65ccbd3ee14702b1397 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Thu, 15 Sep 2011 09:33:51 -0500 Subject: Don't add to the request object, because get_current can be used to obtain the current toolbar --- debug_toolbar/middleware.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index ccd4778..59194dc 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -133,8 +133,5 @@ class DebugToolbarMiddleware(object): smart_unicode(toolbar.render_toolbar() + self.tag)) if response.get('Content-Length', None): response['Content-Length'] = len(response.content) - # Add the toolbar to the request object, so that the stats are - # available to subsequent middleware classes. - request.debug_toolbar_stats = toolbar.stats del self.__class__.debug_toolbars[ident] return response -- cgit v1.2.3 From 03cd2ded38bb6ccd3c97e11fcd1f99bd967dc996 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Thu, 15 Sep 2011 09:37:18 -0500 Subject: Revert the middleware back to its original state, because no changes are actually needed --- debug_toolbar/middleware.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index 59194dc..f49a29f 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -5,6 +5,7 @@ import imp import thread from django.conf import settings +from django.conf.urls.defaults import include, patterns from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.utils.encoding import smart_unicode @@ -123,8 +124,7 @@ class DebugToolbarMiddleware(object): ) response.cookies = cookies if 'gzip' not in response.get('Content-Encoding', '') and \ - response.get('Content-Type', '').split(';')[0] in _HTML_TYPES: - toolbar.stats = {} + response.get('Content-Type', '').split(';')[0] in _HTML_TYPES: for panel in toolbar.panels: panel.process_response(request, response) response.content = replace_insensitive( -- cgit v1.2.3 From 78a8b4415163b8215d2a434a5dab4994871a4fc4 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Thu, 15 Sep 2011 10:03:37 -0500 Subject: Added convenience methods to make it easier to work with panel stats --- debug_toolbar/panels/__init__.py | 35 ++++++++++++++++++++++------------- debug_toolbar/toolbar/loader.py | 19 ++++++++++--------- 2 files changed, 32 insertions(+), 22 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index fa2e4b6..584ddb7 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -1,4 +1,6 @@ -"""Base DebugPanel class""" +from django.template.defaultfilters import slugify +from debug_toolbar.middleware import DebugToolbarMiddleware + class DebugPanel(object): """ @@ -6,43 +8,50 @@ class DebugPanel(object): """ # name = Base has_content = False # If content returns something, set to true in subclass - + # We'll maintain a local context instance so we can expose our template # context variables to panels which need them: context = {} - + # Panel methods def __init__(self, context={}): self.context.update(context) - + self.toolbar = DebugToolbarMiddleware.get_current() + self.slug = slugify(self.name) + def dom_id(self): return 'djDebug%sPanel' % (self.name.replace(' ', '')) - + def nav_title(self): """Title showing in toolbar""" raise NotImplementedError - + def nav_subtitle(self): """Subtitle showing until title in toolbar""" return '' - + def title(self): """Title showing in panel""" raise NotImplementedError - + def url(self): raise NotImplementedError - + def content(self): raise NotImplementedError - + + def record_stats(self, stats): + self.toolbar.stats[self.slug].update(stats) + + def get_stats(self): + return self.toolbar.stats[self.slug] + # Standard middleware methods def process_request(self, request): pass - + def process_view(self, request, view_func, view_args, view_kwargs): pass - + def process_response(self, request, response): pass - diff --git a/debug_toolbar/toolbar/loader.py b/debug_toolbar/toolbar/loader.py index 3501c69..cf7a243 100644 --- a/debug_toolbar/toolbar/loader.py +++ b/debug_toolbar/toolbar/loader.py @@ -9,7 +9,7 @@ from django.utils.datastructures import SortedDict from django.utils.safestring import mark_safe class DebugToolbar(object): - + def __init__(self, request): self.request = request self._panels = SortedDict() @@ -38,25 +38,26 @@ class DebugToolbar(object): 'debug_toolbar.panels.logger.LoggingPanel', ) self.load_panels() + self.stats = {} def _get_panels(self): return self._panels.values() panels = property(_get_panels) - + def get_panel(self, cls): return self._panels[cls] - + def load_panels(self): """ Populate debug panels """ from django.conf import settings from django.core import exceptions - + # Check if settings has a DEBUG_TOOLBAR_PANELS, otherwise use default if hasattr(settings, 'DEBUG_TOOLBAR_PANELS'): self.default_panels = settings.DEBUG_TOOLBAR_PANELS - + for panel_path in self.default_panels: try: dot = panel_path.rindex('.') @@ -71,14 +72,14 @@ class DebugToolbar(object): panel_class = getattr(mod, panel_classname) except AttributeError: raise exceptions.ImproperlyConfigured, 'Toolbar Panel module "%s" does not define a "%s" class' % (panel_module, panel_classname) - + try: panel_instance = panel_class(context=self.template_context) except: raise # Bubble up problem loading panel - + self._panels[panel_class] = panel_instance - + def render_toolbar(self): """ Renders the overall Toolbar with panels inside. @@ -91,5 +92,5 @@ class DebugToolbar(object): 'js': mark_safe(open(os.path.join(media_path, 'js', 'toolbar.min.js'), 'r').read()), 'css': mark_safe(open(os.path.join(media_path, 'css', 'toolbar.min.css'), 'r').read()), }) - + return render_to_string('debug_toolbar/base.html', context) -- cgit v1.2.3 From c20e83fc946c8898d40b0210f71286575891ae94 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Thu, 15 Sep 2011 10:09:53 -0500 Subject: Correct some issues with the stats methods --- debug_toolbar/panels/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index 584ddb7..baebf02 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -41,10 +41,14 @@ class DebugPanel(object): raise NotImplementedError def record_stats(self, stats): - self.toolbar.stats[self.slug].update(stats) + panel_stats = self.toolbar.stats.get(self.slug) + if panel_stats: + panel_stats.update(stats) + else: + self.toolbar.stats[self.slug] = stats def get_stats(self): - return self.toolbar.stats[self.slug] + return self.toolbar.stats.get(self.slug, {}) # Standard middleware methods def process_request(self, request): -- cgit v1.2.3 From ed9bca7c00f6f326842d79e843f678787fac8b15 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Thu, 15 Sep 2011 10:26:00 -0500 Subject: Add a default 'content' method, since the method is now identical on every panel --- debug_toolbar/panels/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index baebf02..e44d388 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -1,4 +1,5 @@ from django.template.defaultfilters import slugify +from django.template.loader import render_to_string from debug_toolbar.middleware import DebugToolbarMiddleware @@ -6,7 +7,8 @@ class DebugPanel(object): """ Base class for debug panels. """ - # name = Base + # name = 'Base' + # template = 'debug_toolbar/panels/base.html' has_content = False # If content returns something, set to true in subclass # We'll maintain a local context instance so we can expose our template @@ -38,7 +40,10 @@ class DebugPanel(object): raise NotImplementedError def content(self): - raise NotImplementedError + if self.has_content: + context = self.context.copy() + context.update(self.get_stats()) + return render_to_string(self.template, context) def record_stats(self, stats): panel_stats = self.toolbar.stats.get(self.slug) -- cgit v1.2.3 From 717dc6815a9d4ddcd30efc17db11ade0f8f38354 Mon Sep 17 00:00:00 2001 From: bkonkle Date: Thu, 15 Sep 2011 10:36:11 -0500 Subject: Edited all of the panels to use the stats API and not override the content method --- debug_toolbar/panels/cache.py | 14 +++--------- debug_toolbar/panels/headers.py | 14 +++--------- debug_toolbar/panels/logger.py | 15 +++--------- debug_toolbar/panels/profiling.py | 27 ++++++++-------------- debug_toolbar/panels/request_vars.py | 19 ++++------------ debug_toolbar/panels/settings_vars.py | 14 +++--------- debug_toolbar/panels/signals.py | 12 ++-------- debug_toolbar/panels/sql.py | 20 ++++++++-------- debug_toolbar/panels/template.py | 17 ++++---------- debug_toolbar/panels/timer.py | 43 +++++++++++++++++------------------ debug_toolbar/panels/version.py | 15 +++--------- 11 files changed, 67 insertions(+), 143 deletions(-) (limited to 'debug_toolbar') diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index ad3f844..c9dae6d 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -3,9 +3,7 @@ import inspect from django.core import cache from django.core.cache.backends.base import BaseCache -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ -from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel class CacheStatTracker(BaseCache): @@ -75,6 +73,7 @@ class CacheDebugPanel(DebugPanel): Panel that displays the cache statistics. """ name = 'Cache' + template = 'debug_toolbar/panels/cache.html' has_content = True def __init__(self, *args, **kwargs): @@ -97,15 +96,8 @@ class CacheDebugPanel(DebugPanel): return '' def process_response(self, request, response): - self.stats = { + self.record_stats({ 'cache_calls': len(self.cache.calls), 'cache_time': self.cache.total_time, 'cache': self.cache, - } - toolbar = DebugToolbarMiddleware.get_current() - toolbar.stats['cache'] = self.stats - - def content(self): - context = self.context.copy() - context.update(self.stats) - return render_to_string('debug_toolbar/panels/cache.html', context) + }) diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py index a88fbd9..181e88d 100644 --- a/debug_toolbar/panels/headers.py +++ b/debug_toolbar/panels/headers.py @@ -1,7 +1,5 @@ -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel -from debug_toolbar.middleware import DebugToolbarMiddleware class HeaderDebugPanel(DebugPanel): @@ -9,6 +7,7 @@ class HeaderDebugPanel(DebugPanel): A panel to display HTTP headers. """ name = 'Header' + template = 'debug_toolbar/panels/headers.html' has_content = True # List of headers we want to display header_filter = ( @@ -49,13 +48,6 @@ class HeaderDebugPanel(DebugPanel): ) def process_response(self, request, response): - self.stats = { + self.record_stats({ 'headers': self.headers - } - toolbar = DebugToolbarMiddleware.get_current() - toolbar.stats['headers'] = self.stats - - def content(self): - context = self.context.copy() - context.update(self.stats) - return render_to_string('debug_toolbar/panels/headers.html', context) + }) diff --git a/debug_toolbar/panels/logger.py b/debug_toolbar/panels/logger.py index ba34700..55ae9bd 100644 --- a/debug_toolbar/panels/logger.py +++ b/debug_toolbar/panels/logger.py @@ -4,10 +4,8 @@ try: import threading except ImportError: threading = None -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel -from debug_toolbar.middleware import DebugToolbarMiddleware class LogCollector(object): @@ -88,13 +86,14 @@ if logbook_supported: 'channel': record.channel, } self.collector.add_record(record) - + logbook_handler = LogbookThreadTrackingHandler(collector) logbook_handler.push_application() # register with logbook class LoggingPanel(DebugPanel): name = 'Logging' + template = 'debug_toolbar/panels/logger.html' has_content = True def process_request(self, request): @@ -102,9 +101,7 @@ class LoggingPanel(DebugPanel): def process_response(self, request, response): records = self.get_and_delete() - self.stats = {'records': records} - toolbar = DebugToolbarMiddleware.get_current() - toolbar.stats['logger'] = self.stats + self.record_stats({'records': records}) def get_and_delete(self): records = collector.get_records() @@ -123,9 +120,3 @@ class LoggingPanel(DebugPanel): def url(self): return '' - - def content(self): - context = self.context.copy() - context.update(self.stats) - return render_to_string('debug_toolbar/panels/logger.html', context) - diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index e08591a..8913621 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -1,9 +1,7 @@ from __future__ import division -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from django.utils.safestring import mark_safe -from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel try: @@ -143,6 +141,7 @@ class ProfilingDebugPanel(DebugPanel): Panel that displays the Django version. """ name = 'Profiling' + template = 'debug_toolbar/panels/profiling.html' has_content = True def nav_title(self): @@ -178,16 +177,6 @@ class ProfilingDebugPanel(DebugPanel): out = self.profiler.runcall(view_func, *args, **view_kwargs) return out - def process_response(self, request, response): - self.profiler.create_stats() - self.stats = DjangoDebugToolbarStats(self.profiler) - if DJ_PROFILE_USE_LINE_PROFILER: - self.stats.line_stats = self.line_profiler.get_stats() - self.stats.calc_callees() - toolbar = DebugToolbarMiddleware.get_current() - toolbar.stats['profiling'] = self.stats - return response - def add_node(self, func_list, func, max_depth, cum_time=0.1): func_list.append(func) func.has_subfuncs = False @@ -199,14 +188,16 @@ class ProfilingDebugPanel(DebugPanel): func.has_subfuncs = True self.add_node(func_list, subfunc, max_depth, cum_time=cum_time) - def content(self): + def process_response(self, request, response): + self.profiler.create_stats() + self.stats = DjangoDebugToolbarStats(self.profiler) + if DJ_PROFILE_USE_LINE_PROFILER: + self.stats.line_stats = self.line_profiler.get_stats() + self.stats.calc_callees() + root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0) func_list = [] self.add_node(func_list, root, 10, root.stats[3]/8) - context = self.context.copy() - context.update({ - 'func_list': func_list, - }) - return render_to_string('debug_toolbar/panels/profiling.html', context) + self.stats_record({'func_list': func_list}) diff --git a/debug_toolbar/panels/request_vars.py b/debug_toolbar/panels/request_vars.py index 80cd018..ee9cdc5 100644 --- a/debug_toolbar/panels/request_vars.py +++ b/debug_toolbar/panels/request_vars.py @@ -1,7 +1,5 @@ -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ -from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel from debug_toolbar.utils import get_name_from_obj @@ -10,6 +8,7 @@ class RequestVarsDebugPanel(DebugPanel): A panel to display request variables (POST/GET, session, cookies). """ name = 'RequestVars' + template = 'debug_toolbar/panels/request_vars.html' has_content = True def __init__(self, *args, **kwargs): @@ -36,11 +35,11 @@ class RequestVarsDebugPanel(DebugPanel): self.view_kwargs = view_kwargs def process_response(self, request, response): - self.stats = { + self.record_stats({ 'get': [(k, self.request.GET.getlist(k)) for k in self.request.GET], 'post': [(k, self.request.POST.getlist(k)) for k in self.request.POST], 'cookies': [(k, self.request.COOKIES.get(k)) for k in self.request.COOKIES], - } + }) if hasattr(self, 'view_func'): if self.view_func is not None: @@ -48,21 +47,13 @@ class RequestVarsDebugPanel(DebugPanel): else: name = '' - self.stats.update({ + self.record_stats({ 'view_func': name, 'view_args': self.view_args, 'view_kwargs': self.view_kwargs }) if hasattr(self.request, 'session'): - self.stats.update({ + self.record_stats({ 'session': [(k, self.request.session.get(k)) for k in self.request.session.iterkeys()] }) - - toolbar = DebugToolbarMiddleware.get_current() - toolbar.stats['request_vars'] = self.stats - - def content(self): - context = self.context.copy() - context.update(self.stats) - return render_to_string('debug_toolbar/panels/request_vars.html', context) diff --git a/debug_toolbar/panels/settings_vars.py b/debug_toolbar/panels/settings_vars.py index 029496e..e154dda 100644 --- a/debug_toolbar/panels/settings_vars.py +++ b/debug_toolbar/panels/settings_vars.py @@ -1,8 +1,6 @@ from django.conf import settings -from django.template.loader import render_to_string from django.views.debug import get_safe_settings from django.utils.translation import ugettext_lazy as _ -from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel @@ -11,6 +9,7 @@ class SettingsVarsDebugPanel(DebugPanel): A panel to display all variables in django.conf.settings """ name = 'SettingsVars' + template = 'debug_toolbar/panels/settings_vars.html' has_content = True def nav_title(self): @@ -23,13 +22,6 @@ class SettingsVarsDebugPanel(DebugPanel): return '' def process_response(self, request, response): - self.stats = { + self.record_stats({ 'settings': get_safe_settings(), - } - toolbar = DebugToolbarMiddleware.get_current() - toolbar.stats['settings_vars'] = self.stats - - def content(self): - context = self.context.copy() - context.update(self.stats) - return render_to_string('debug_toolbar/panels/settings_vars.html', context) + }) diff --git a/debug_toolbar/panels/signals.py b/debug_toolbar/panels/signals.py index 9855299..205b3c5 100644 --- a/debug_toolbar/panels/signals.py +++ b/debug_toolbar/panels/signals.py @@ -6,7 +6,6 @@ from django.core.signals import request_started, request_finished, \ from django.db.models.signals import class_prepared, pre_init, post_init, \ pre_save, post_save, pre_delete, post_delete, post_syncdb from django.dispatch.dispatcher import WEAKREF_TYPES -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ try: @@ -14,11 +13,11 @@ try: except ImportError: connection_created = None -from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel class SignalDebugPanel(DebugPanel): name = "Signals" + template = 'debug_toolbar/panels/signals.html' has_content = True SIGNALS = { @@ -82,11 +81,4 @@ class SignalDebugPanel(DebugPanel): receivers.append(text) signals.append((name, signal, receivers)) - self.stats = {'signals': signals} - toolbar = DebugToolbarMiddleware.get_current() - toolbar.stats['signals'] = self.stats - - def content(self): - context = self.context.copy() - context.update(self.stats) - return render_to_string('debug_toolbar/panels/signals.html', context) + self.record_stats({'signals': signals}) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 9527410..188e1eb 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -2,7 +2,6 @@ import re import uuid from django.db.backends import BaseDatabaseWrapper -from django.template.loader import render_to_string from django.utils.html import escape from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _, ungettext_lazy as __ @@ -14,6 +13,7 @@ from debug_toolbar.utils import sqlparse from debug_toolbar.utils.tracking.db import CursorWrapper from debug_toolbar.utils.tracking import replace_call + # Inject our tracking cursor @replace_call(BaseDatabaseWrapper.cursor) def cursor(func, self): @@ -26,6 +26,7 @@ def cursor(func, self): return CursorWrapper(result, self, logger=logger) + def get_isolation_level_display(engine, level): if engine == 'psycopg2': import psycopg2.extensions @@ -41,6 +42,7 @@ def get_isolation_level_display(engine, level): return choices.get(level) + def get_transaction_status_display(engine, level): if engine == 'psycopg2': import psycopg2.extensions @@ -56,12 +58,14 @@ def get_transaction_status_display(engine, level): return choices.get(level) + class SQLDebugPanel(DebugPanel): """ Panel that displays information about the SQL queries run while processing the request. """ name = 'SQL' + template = 'debug_toolbar/panels/sql.html' has_content = True def __init__(self, *args, **kwargs): @@ -205,18 +209,12 @@ class SQLDebugPanel(DebugPanel): if trans_id: self._queries[i-1][1]['ends_trans'] = True - self.stats = { + self.record_stats({ 'databases': sorted(self._databases.items(), key=lambda x: -x[1]['time_spent']), 'queries': [q for a, q in self._queries], 'sql_time': self._sql_time, - } - toolbar = DebugToolbarMiddleware.get_current() - toolbar.stats['sql'] = self.stats - - def content(self): - context = self.context.copy() - context.update(self.stats) - return render_to_string('debug_toolbar/panels/sql.html', context) + }) + class BoldKeywordFilter(sqlparse.filters.Filter): """sqlparse filter to bold SQL keywords""" @@ -230,10 +228,12 @@ class BoldKeywordFilter(sqlparse.filters.Filter): if is_keyword: yield sqlparse.tokens.Text, '' + def swap_fields(sql): return re.sub('SELECT (.*) FROM', 'SELECT ••• ' + '\g<1> FROM', sql) + def reformat_sql(sql): stack = sqlparse.engine.FilterStack() stack.preprocess.append(BoldKeywordFilter()) # add our custom filter diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index d0ab6cc..41e0afc 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -4,10 +4,8 @@ from pprint import pformat from django import http from django.conf import settings from django.template.context import get_standard_processors -from django.template.loader import render_to_string from django.test.signals import template_rendered from django.utils.translation import ugettext_lazy as _ -from debug_toolbar.middleware import DebugToolbarMiddleware from debug_toolbar.panels import DebugPanel # Code taken and adapted from Simon Willison and Django Snippets: @@ -28,6 +26,7 @@ else: Template.original_render = Template._render Template._render = instrumented_test_render + # MONSTER monkey-patch old_template_init = Template.__init__ def new_template_init(self, template_string, origin=None, name=''): @@ -35,11 +34,13 @@ def new_template_init(self, template_string, origin=None, name='