aboutsummaryrefslogtreecommitdiffstats
path: root/debug_toolbar/panels
diff options
context:
space:
mode:
Diffstat (limited to 'debug_toolbar/panels')
-rw-r--r--debug_toolbar/panels/__init__.py9
-rw-r--r--debug_toolbar/panels/cache.py5
-rw-r--r--debug_toolbar/panels/headers.py3
-rw-r--r--debug_toolbar/panels/logger.py9
-rw-r--r--debug_toolbar/panels/request_vars.py5
-rw-r--r--debug_toolbar/panels/settings_vars.py7
-rw-r--r--debug_toolbar/panels/signals.py4
-rw-r--r--debug_toolbar/panels/sql.py81
-rw-r--r--debug_toolbar/panels/template.py4
-rw-r--r--debug_toolbar/panels/timer.py14
-rw-r--r--debug_toolbar/panels/version.py10
11 files changed, 112 insertions, 39 deletions
diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py
index 54b3318..cf65aa8 100644
--- a/debug_toolbar/panels/__init__.py
+++ b/debug_toolbar/panels/__init__.py
@@ -14,7 +14,16 @@ class DebugPanel(object):
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):
diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py
index 613d4d9..a05d3cc 100644
--- a/debug_toolbar/panels/cache.py
+++ b/debug_toolbar/panels/cache.py
@@ -87,9 +87,12 @@ class CacheDebugPanel(DebugPanel):
self.cache = CacheStatTracker(cache.cache)
cache.cache = self.cache
- def title(self):
+ def nav_title(self):
return 'Cache: %.2fms' % self.cache.total_time
+ def title(self):
+ return 'Cache Usage'
+
def url(self):
return ''
diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py
index 213198a..06858ef 100644
--- a/debug_toolbar/panels/headers.py
+++ b/debug_toolbar/panels/headers.py
@@ -31,6 +31,9 @@ class HeaderDebugPanel(DebugPanel):
'SERVER_SOFTWARE',
)
+ def nav_title(self):
+ return 'HTTP Headers'
+
def title(self):
return 'HTTP Headers'
diff --git a/debug_toolbar/panels/logger.py b/debug_toolbar/panels/logger.py
index cb88148..a16b933 100644
--- a/debug_toolbar/panels/logger.py
+++ b/debug_toolbar/panels/logger.py
@@ -5,6 +5,7 @@ try:
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
class ThreadTrackingHandler(logging.Handler):
@@ -51,8 +52,14 @@ class LoggingPanel(DebugPanel):
handler.clear_records()
return records
+ def nav_title(self):
+ return _("Logging")
+
+ def nav_subtitle(self):
+ return "%s message%s" % (len(handler.get_records()), (len(handler.get_records()) == 1) and '' or 's')
+
def title(self):
- return "Logging (%s message%s)" % (len(handler.get_records()), (len(handler.get_records()) == 1) and '' or 's')
+ return 'Log Messages'
def url(self):
return ''
diff --git a/debug_toolbar/panels/request_vars.py b/debug_toolbar/panels/request_vars.py
index 88a7204..d0a8c19 100644
--- a/debug_toolbar/panels/request_vars.py
+++ b/debug_toolbar/panels/request_vars.py
@@ -8,9 +8,12 @@ class RequestVarsDebugPanel(DebugPanel):
name = 'RequestVars'
has_content = True
+ def nav_title(self):
+ return 'Request Vars'
+
def title(self):
return 'Request Vars'
-
+
def url(self):
return ''
diff --git a/debug_toolbar/panels/settings_vars.py b/debug_toolbar/panels/settings_vars.py
index e090718..f30f601 100644
--- a/debug_toolbar/panels/settings_vars.py
+++ b/debug_toolbar/panels/settings_vars.py
@@ -1,8 +1,10 @@
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.panels import DebugPanel
+
class SettingsVarsDebugPanel(DebugPanel):
"""
A panel to display all variables in django.conf.settings
@@ -10,8 +12,11 @@ class SettingsVarsDebugPanel(DebugPanel):
name = 'SettingsVars'
has_content = True
+ def nav_title(self):
+ return _('Settings')
+
def title(self):
- return 'Settings'
+ return 'Settings from <code>%s</code>' % settings.SETTINGS_MODULE
def url(self):
return ''
diff --git a/debug_toolbar/panels/signals.py b/debug_toolbar/panels/signals.py
index 7fe382e..56fbfd4 100644
--- a/debug_toolbar/panels/signals.py
+++ b/debug_toolbar/panels/signals.py
@@ -7,6 +7,7 @@ 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:
from django.db.backends.signals import connection_created
@@ -34,6 +35,9 @@ class SignalDebugPanel(DebugPanel):
'post_syncdb': post_syncdb,
}
+ def nav_title(self):
+ return _("Signals")
+
def title(self):
return "Signals"
diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py
index c8d50d9..3903b54 100644
--- a/debug_toolbar/panels/sql.py
+++ b/debug_toolbar/panels/sql.py
@@ -1,6 +1,6 @@
import os
import SocketServer
-import time
+from datetime import datetime
import traceback
import django
@@ -18,6 +18,21 @@ from debug_toolbar.panels import DebugPanel
django_path = os.path.realpath(os.path.dirname(django.__file__))
socketserver_path = os.path.realpath(os.path.dirname(SocketServer.__file__))
+# TODO:This should be set in the toolbar loader as a default and panels should
+# get a copy of the toolbar object with access to its config dictionary
+SQL_WARNING_THRESHOLD = getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}).get('SQL_WARNING_THRESHOLD', 500)
+
+SQL_KEYWORDS = (
+ 'SELECT',
+ 'FROM',
+ 'WHERE',
+ 'INNER JOIN',
+ 'LEFT OUTER JOIN',
+ 'ORDER BY',
+ 'HAVING',
+ 'GROUP BY',
+)
+
def tidy_stacktrace(strace):
"""
Clean up stacktrace and remove all entries that:
@@ -41,11 +56,12 @@ class DatabaseStatTracker(util.CursorDebugWrapper):
in `connection.queries`.
"""
def execute(self, sql, params=()):
- start = time.time()
+ start = datetime.now()
try:
return self.cursor.execute(sql, params)
finally:
- stop = time.time()
+ stop = datetime.now()
+ duration = ms_from_timedelta(stop - start)
stacktrace = tidy_stacktrace(traceback.extract_stack())
_params = ''
try:
@@ -55,11 +71,14 @@ class DatabaseStatTracker(util.CursorDebugWrapper):
# We keep `sql` to maintain backwards compatibility
self.db.queries.append({
'sql': self.db.ops.last_executed_query(self.cursor, sql, params),
- 'time': (stop - start) * 1000, # convert to ms
+ 'duration': duration,
'raw_sql': sql,
'params': _params,
'hash': sha_constructor(settings.SECRET_KEY + sql + _params).hexdigest(),
'stacktrace': stacktrace,
+ 'start_time': start,
+ 'stop_time': stop,
+ 'is_slow': (duration > SQL_WARNING_THRESHOLD)
})
util.CursorDebugWrapper = DatabaseStatTracker
@@ -74,47 +93,53 @@ class SQLDebugPanel(DebugPanel):
def __init__(self):
self._offset = len(connection.queries)
self._sql_time = 0
+ self._queries = []
- def title(self):
- self._sql_time = sum(map(lambda q: float(q['time']), connection.queries))
- num_queries = len(connection.queries) - self._offset
- return '%d SQL %s (%.2fms)' % (
+ def nav_title(self):
+ return 'SQL'
+
+ def nav_subtitle(self):
+ self._queries = connection.queries[self._offset:]
+ self._sql_time = sum([q['duration'] for q in self._queries])
+ num_queries = len(self._queries)
+ return "%d %s in %.2fms" % (
num_queries,
(num_queries == 1) and 'query' or 'queries',
self._sql_time
)
+ def title(self):
+ return 'SQL Queries'
+
def url(self):
return ''
def content(self):
- sql_queries = connection.queries[self._offset:]
- for query in sql_queries:
+ width_ratio_tally = 0
+ for query in self._queries:
query['sql'] = reformat_sql(query['sql'])
+ try:
+ query['width_ratio'] = (query['duration'] / self._sql_time) * 100
+ except ZeroDivisionError:
+ query['width_ratio'] = 0
+ query['start_offset'] = width_ratio_tally
+ width_ratio_tally += query['width_ratio']
context = {
- 'queries': sql_queries,
+ 'queries': self._queries,
'sql_time': self._sql_time,
'is_mysql': settings.DATABASE_ENGINE == 'mysql',
}
return render_to_string('debug_toolbar/panels/sql.html', context)
+def ms_from_timedelta(td):
+ """
+ Given a timedelta object, returns a float representing milliseconds
+ """
+ return (td.seconds * 1000) + (td.microseconds / 1000.0)
+
def reformat_sql(sql):
- sql = sql.replace(',', ', ')
- sql = sql.replace('SELECT ', 'SELECT\n\t')
- sql = sql.replace(' FROM ', '\nFROM\n\t')
- sql = sql.replace(' WHERE ', '\nWHERE\n\t')
- sql = sql.replace(' INNER JOIN', '\n\tINNER JOIN')
- sql = sql.replace(' LEFT OUTER JOIN' , '\n\tLEFT OUTER JOIN')
- sql = sql.replace(' ORDER BY ', '\nORDER BY\n\t')
- sql = sql.replace(' HAVING ', '\nHAVING\n\t')
- sql = sql.replace(' GROUP BY ', '\nGROUP BY\n\t')
- # Use Pygments to highlight SQL if it's available
- try:
- from pygments import highlight
- from pygments.lexers import SqlLexer
- from pygments.formatters import HtmlFormatter
- sql = highlight(sql, SqlLexer(), HtmlFormatter())
- except ImportError:
- pass
+ for kwd in SQL_KEYWORDS:
+ sql = sql.replace(kwd, '<strong>%s</strong>' % (kwd,))
return sql
+
diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py
index e99b9c5..f090c78 100644
--- a/debug_toolbar/panels/template.py
+++ b/debug_toolbar/panels/template.py
@@ -7,6 +7,7 @@ from django.dispatch import Signal
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.panels import DebugPanel
# Code taken and adapted from Simon Willison and Django Snippets:
@@ -41,6 +42,9 @@ class TemplateDebugPanel(DebugPanel):
def _store_template_info(self, sender, **kwargs):
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.startswith('debug_toolbar/')])
diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py
index 352bf55..4e390f6 100644
--- a/debug_toolbar/panels/timer.py
+++ b/debug_toolbar/panels/timer.py
@@ -4,9 +4,9 @@ except ImportError:
pass # Will fail on Win32 systems
import time
from django.template.loader import render_to_string
+from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel
-
class TimerDebugPanel(DebugPanel):
"""
Panel that displays the time a response took in milliseconds.
@@ -31,13 +31,19 @@ class TimerDebugPanel(DebugPanel):
if self.has_resource:
self._end_rusage = resource.getrusage(resource.RUSAGE_SELF)
- def title(self):
+ def nav_title(self):
+ return _('Time')
+
+ def nav_subtitle(self):
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 'Time: %0.2fms, %0.2fms CPU' % (self.total_time, (utime + stime) * 1000.0)
+ return 'CPU: %0.2fms (%0.2fms)' % ((utime + stime) * 1000.0, self.total_time)
else:
- return 'Time: %0.2fms' % (self.total_time)
+ return 'TOTAL: %0.2fms' % (self.total_time)
+
+ def title(self):
+ return 'Resource Usage'
def url(self):
return ''
diff --git a/debug_toolbar/panels/version.py b/debug_toolbar/panels/version.py
index 7ea6543..3d82dd0 100644
--- a/debug_toolbar/panels/version.py
+++ b/debug_toolbar/panels/version.py
@@ -1,4 +1,5 @@
import django
+from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel
class VersionDebugPanel(DebugPanel):
@@ -6,9 +7,12 @@ class VersionDebugPanel(DebugPanel):
Panel that displays the Django version.
"""
name = 'Version'
-
- def title(self):
- return 'Version: %s' % (django.get_version())
+
+ def nav_title(self):
+ return _('Django Version')
+
+ def nav_subtitle(self):
+ return django.get_version()
def url(self):
return ''