diff options
| author | Rob Hudson | 2009-03-21 10:54:56 -0700 | 
|---|---|---|
| committer | Rob Hudson | 2009-03-21 10:56:08 -0700 | 
| commit | 30ab58a69510f3fd35e19f6be9b669d2fdf956c0 (patch) | |
| tree | 5d03755816d3aa8e10cc435a2213e306d5572e3c | |
| parent | 2e0d4d3b7e2aad03743ca255b053caf55b0b73b2 (diff) | |
| parent | 1a52939905b7a43a9cf83cde6216a98cc5cbc595 (diff) | |
| download | django-debug-toolbar-30ab58a69510f3fd35e19f6be9b669d2fdf956c0.tar.bz2 | |
Adding stack traces to SQL panel to see where the calls are coming from.
Merge branch 'sql_stacktrace'
* sql_stacktrace:
  Tuple unpacking of stacktrace variables for niceness.
  Add preliminary support for stacktraces to see where SQL queries are coming from.
| -rw-r--r-- | debug_toolbar/media/toolbar.js | 5 | ||||
| -rw-r--r-- | debug_toolbar/media/toolbar.min.js | 2 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql.py | 29 | ||||
| -rw-r--r-- | debug_toolbar/templates/debug_toolbar/panels/sql.html | 22 | 
4 files changed, 55 insertions, 3 deletions
| diff --git a/debug_toolbar/media/toolbar.js b/debug_toolbar/media/toolbar.js index 400586a..c69a917 100644 --- a/debug_toolbar/media/toolbar.js +++ b/debug_toolbar/media/toolbar.js @@ -40,8 +40,11 @@ jQuery(function() {  				$j.djDebug.toggle_content($j(this).parent().next());  				return false;  			}); +			$j('#djDebugSQLPanel a.djSQLShowStacktrace').click(function() { +				$j.djDebug.toggle_content($j(this).parent().next()); +				return false; +			});  			$j('#djHideToolBarButton').click(function() { -				$j(document).trigger('close.djDebug');  				$j.djDebug.hide_toolbar(true);  				return false;  			}); diff --git a/debug_toolbar/media/toolbar.min.js b/debug_toolbar/media/toolbar.min.js index 0385252..4c967f8 100644 --- a/debug_toolbar/media/toolbar.min.js +++ b/debug_toolbar/media/toolbar.min.js @@ -1 +1 @@ -var _$=window.$;$j=jQuery.noConflict();jQuery(function(){var a="dj_debug_panel";$j.djDebug=function(c,b){$j.djDebug.init()};$j.extend($j.djDebug,{init:function(){var b=null;$j("#djDebugPanelList li a").click(function(){if(!this.className){return false}b=$j("#djDebug #"+this.className);if(b.is(":visible")){$j(document).trigger("close.djDebug")}else{$j(".panelContent").hide();b.show();$j.djDebug.open()}return false});$j("#djDebug a.close").click(function(){$j(document).trigger("close.djDebug");return false});$j("#djDebug a.remoteCall").click(function(){$j("#djDebugWindow").load(this.href,{},function(){$j("#djDebugWindow a.back").click(function(){$j(this).parent().hide();return false})});$j("#djDebugWindow").show();return false});$j("#djDebugTemplatePanel a.djTemplateShowContext").click(function(){$j.djDebug.toggle_content($j(this).parent().next());return false});$j("#djHideToolBarButton").click(function(){$j(document).trigger("close.djDebug");$j.djDebug.hide_toolbar(true);return false});$j("#djShowToolBarButton").click(function(){$j.djDebug.show_toolbar();return false});if($j.cookie(a)){$j.djDebug.hide_toolbar(false)}else{$j("#djDebugToolbar").show()}},open:function(){$j(document).bind("keydown.djDebug",function(b){if(b.keyCode==27){$j.djDebug.close()}})},toggle_content:function(b){if(b.is(":visible")){b.hide()}else{b.show()}},close:function(){$j(document).trigger("close.djDebug");return false},hide_toolbar:function(b){$j("#djDebugToolbar").hide("fast");$j("#djDebugToolbarHandle").show();if(b){$j.cookie(a,"hide",{path:"/",expires:10})}},show_toolbar:function(){$j("#djDebugToolbarHandle").hide();$j("#djDebugToolbar").show("fast");$j.cookie(a,null,{path:"/",expires:-1})}});$j(document).bind("close.djDebug",function(){$j(document).unbind("keydown.djDebug");$j(".panelContent").hide()})});jQuery(function(){jQuery.djDebug()});$=_$;jQuery.cookie=function(b,j,m){if(typeof j!="undefined"){m=m||{};if(j===null){j="";m.expires=-1}var e="";if(m.expires&&(typeof m.expires=="number"||m.expires.toUTCString)){var f;if(typeof m.expires=="number"){f=new Date();f.setTime(f.getTime()+(m.expires*24*60*60*1000))}else{f=m.expires}e="; expires="+f.toUTCString()}var l=m.path?"; path="+(m.path):"";var g=m.domain?"; domain="+(m.domain):"";var a=m.secure?"; secure":"";document.cookie=[b,"=",encodeURIComponent(j),e,l,g,a].join("")}else{var d=null;if(document.cookie&&document.cookie!=""){var k=document.cookie.split(";");for(var h=0;h<k.length;h++){var c=jQuery.trim(k[h]);if(c.substring(0,b.length+1)==(b+"=")){d=decodeURIComponent(c.substring(b.length+1));break}}}return d}};
\ No newline at end of file +var _$=window.$;$j=jQuery.noConflict();jQuery(function(){var a="dj_debug_panel";$j.djDebug=function(c,b){$j.djDebug.init()};$j.extend($j.djDebug,{init:function(){var b=null;$j("#djDebugPanelList li a").click(function(){if(!this.className){return false}b=$j("#djDebug #"+this.className);if(b.is(":visible")){$j(document).trigger("close.djDebug")}else{$j(".panelContent").hide();b.show();$j.djDebug.open()}return false});$j("#djDebug a.close").click(function(){$j(document).trigger("close.djDebug");return false});$j("#djDebug a.remoteCall").click(function(){$j("#djDebugWindow").load(this.href,{},function(){$j("#djDebugWindow a.back").click(function(){$j(this).parent().hide();return false})});$j("#djDebugWindow").show();return false});$j("#djDebugTemplatePanel a.djTemplateShowContext").click(function(){$j.djDebug.toggle_content($j(this).parent().next());return false});$j("#djDebugSQLPanel a.djSQLShowStacktrace").click(function(){$j.djDebug.toggle_content($j(this).parent().next());return false});$j("#djHideToolBarButton").click(function(){$j.djDebug.hide_toolbar(true);return false});$j("#djShowToolBarButton").click(function(){$j.djDebug.show_toolbar();return false});if($j.cookie(a)){$j.djDebug.hide_toolbar(false)}else{$j("#djDebugToolbar").show()}},open:function(){$j(document).bind("keydown.djDebug",function(b){if(b.keyCode==27){$j.djDebug.close()}})},toggle_content:function(b){if(b.is(":visible")){b.hide()}else{b.show()}},close:function(){$j(document).trigger("close.djDebug");return false},hide_toolbar:function(b){$j("#djDebugToolbar").hide("fast");$j("#djDebugToolbarHandle").show();if(b){$j.cookie(a,"hide",{path:"/",expires:10})}},show_toolbar:function(){$j("#djDebugToolbarHandle").hide();$j("#djDebugToolbar").show("fast");$j.cookie(a,null,{path:"/",expires:-1})}});$j(document).bind("close.djDebug",function(){$j(document).unbind("keydown.djDebug");$j(".panelContent").hide()})});jQuery(function(){jQuery.djDebug()});$=_$;jQuery.cookie=function(b,j,m){if(typeof j!="undefined"){m=m||{};if(j===null){j="";m.expires=-1}var e="";if(m.expires&&(typeof m.expires=="number"||m.expires.toUTCString)){var f;if(typeof m.expires=="number"){f=new Date();f.setTime(f.getTime()+(m.expires*24*60*60*1000))}else{f=m.expires}e="; expires="+f.toUTCString()}var l=m.path?"; path="+(m.path):"";var g=m.domain?"; domain="+(m.domain):"";var a=m.secure?"; secure":"";document.cookie=[b,"=",encodeURIComponent(j),e,l,g,a].join("")}else{var d=null;if(document.cookie&&document.cookie!=""){var k=document.cookie.split(";");for(var h=0;h<k.length;h++){var c=jQuery.trim(k[h]);if(c.substring(0,b.length+1)==(b+"=")){d=decodeURIComponent(c.substring(b.length+1));break}}}return d}};
\ No newline at end of file diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index b9800b8..8934fb3 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -1,5 +1,8 @@ +import os +import SocketServer  import time -from debug_toolbar.panels import DebugPanel +import traceback +import django  from django.conf import settings  from django.db import connection  from django.db.backends import util @@ -7,6 +10,28 @@ from django.template.loader import render_to_string  from django.utils import simplejson  from django.utils.encoding import force_unicode  from django.utils.hashcompat import sha_constructor +from debug_toolbar.panels import DebugPanel + +# Figure out some paths +django_path = os.path.realpath(os.path.dirname(django.__file__)) +socketserver_path = os.path.realpath(os.path.dirname(SocketServer.__file__)) + +def tidy_stacktrace(strace): +    """ +    Clean up stacktrace and remove all entries that: +    1. Are part of Django (except contrib apps) +    2. Are part of SocketServer (used by Django's dev server) +    3. Are the last entry (which is part of our stacktracing code) +    """ +    trace = [] +    for s in strace[:-1]: +        s_path = os.path.realpath(s[0]) +        if django_path in s_path and not 'django/contrib' in s_path: +            continue +        if socketserver_path in s_path: +            continue +        trace.append((s[0], s[1], s[2], s[3])) +    return trace  class DatabaseStatTracker(util.CursorDebugWrapper):      """ @@ -19,6 +44,7 @@ class DatabaseStatTracker(util.CursorDebugWrapper):              return self.cursor.execute(sql, params)          finally:              stop = time.time() +            stacktrace = tidy_stacktrace(traceback.extract_stack())              _params = ''              try:                  _params = simplejson.dumps([force_unicode(x) for x in params]) @@ -31,6 +57,7 @@ class DatabaseStatTracker(util.CursorDebugWrapper):                  'raw_sql': sql,                  'params': _params,                  'hash': sha_constructor(settings.SECRET_KEY + sql + _params).hexdigest(), +                'stacktrace': stacktrace,              })  util.CursorDebugWrapper = DatabaseStatTracker diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html index 0c8e9c3..f05ea97 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/sql.html +++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html @@ -4,6 +4,7 @@  		<tr>  			<th>Time (ms)</th>  			<th>Action</th> +			<th>Stacktrace</th>  			<th>Query</th>  		</tr>  	</thead> @@ -20,6 +21,27 @@  					{% endif %}  				{% endif %}  				</td> +				<td> +					{% if query.stacktrace %} +					<div class="djSQLShowStacktraceDiv"><a class="djSQLShowStacktrace" href="#">Toggle Stacktrace</a></div> +					<div class="djSQLHideStacktraceDiv" style="display:none;"> +						<table> +							<tr> +								<th>Line</th> +								<th>Method</th> +								<th>File</th> +							</tr> +							{% for file, line, method in query.stacktrace %} +								<tr> +									<td>{{ line }}</td> +									<td><pre>{{ method|escape }}<pre></td> +									<td><pre>{{ file|escape }}</pre></td> +								</tr> +							{% endfor %} +						</table> +					</div> +					{% endif %} +				</td>  				<td class="syntax">{{ query.sql|safe }}</td>  			</tr>  		{% endfor %} | 
