diff options
| author | Alex Gaynor | 2009-09-10 11:14:27 -0700 |
|---|---|---|
| committer | Alex Gaynor | 2009-09-10 11:14:27 -0700 |
| commit | d6190014abd950f032755fde33ce32c30fc0e754 (patch) | |
| tree | f070f1275da92ea9efc545ef049c798499286412 /debug_toolbar/panels/sql.py | |
| parent | 89a0b38316e1822bf22a4f013a6bb12f9db585b8 (diff) | |
| parent | 608e3ce3e79e3c2d073cf72d1071b71b324485ee (diff) | |
| download | django-debug-toolbar-d6190014abd950f032755fde33ce32c30fc0e754.tar.bz2 | |
handle merge conflicts
Diffstat (limited to 'debug_toolbar/panels/sql.py')
| -rw-r--r-- | debug_toolbar/panels/sql.py | 81 |
1 files changed, 53 insertions, 28 deletions
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 + |
