Commit af131a3c by Harry Marr

Refactor tracker, add stack traces to queries

parent 330f1177
......@@ -2,7 +2,7 @@ from django.template.loader import render_to_string
from debug_toolbar.panels import DebugPanel
from operation_tracker import MongoOperationTracker
import operation_tracker
class MongoDebugPanel(DebugPanel):
......@@ -13,23 +13,18 @@ class MongoDebugPanel(DebugPanel):
def __init__(self, *args, **kwargs):
super(self.__class__, self).__init__(*args, **kwargs)
self.op_tracker = MongoOperationTracker()
self.op_tracker.install()
operation_tracker.install_tracker()
def process_request(self, request):
self.op_tracker.reset()
self.op_tracker.start()
def process_response(self, request, response):
self.op_tracker.stop()
operation_tracker.reset()
def nav_title(self):
return 'MongoDB'
def nav_subtitle(self):
num_queries = len(self.op_tracker.queries)
num_queries = len(operation_tracker.queries)
attrs = ['queries', 'inserts', 'updates', 'removes']
total_time = sum(sum(o['time'] for o in getattr(self.op_tracker, a))
total_time = sum(sum(o['time'] for o in getattr(operation_tracker, a))
for a in attrs)
return '{0} operations in {1:.2f}ms'.format(num_queries, total_time)
......@@ -41,10 +36,10 @@ class MongoDebugPanel(DebugPanel):
def content(self):
context = self.context.copy()
context['queries'] = self.op_tracker.queries
context['inserts'] = self.op_tracker.inserts
context['updates'] = self.op_tracker.updates
context['removes'] = self.op_tracker.removes
context['queries'] = operation_tracker.queries
context['inserts'] = operation_tracker.inserts
context['updates'] = operation_tracker.updates
context['removes'] = operation_tracker.removes
return render_to_string('mongo-panel.html', context)
......@@ -5,11 +5,23 @@ pre.mongo-highlight, pre.mongo-highlight span {
font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', 'Monaco', 'Courier New', monospace !important;
font-size: 1.05em !important;
}
pre.mongo-stack-trace {
line-height: 2.3em !important;
}
table.mongo-stack-trace th {
text-align: left !important;
}
table.mongo-stack-trace td.code, table.mongo-stack-trace td.code span, table.mongo-stack-trace td.function {
font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', 'Monaco', 'Courier New', monospace !important;
}
table.mongo-op-table tbody {
width: 100% !important;
}
</style>
<h4>Queries</h4>
{% if queries %}
<table>
<table class="mongo-op-table">
<thead>
<tr>
<th>Time (ms)</th>
......@@ -19,6 +31,7 @@ pre.mongo-highlight, pre.mongo-highlight span {
<th>Ordering</th>
<th>Skip</th>
<th>Limit</th>
<th>Stack Trace</th>
</tr>
</thead>
<tbody>
......@@ -29,12 +42,38 @@ pre.mongo-highlight, pre.mongo-highlight span {
<td>{{ query.collection }}</td>
<td>
{% if query.query %}
<pre class="mongo-highlight">{{ query.query|format_dict|highlight_json|safe }}</pre>
<pre class="mongo-highlight">{{ query.query|format_dict|highlight:"javascript"|safe }}</pre>
{% endif %}
</td>
<td><pre class="mongo-highlight">{% if query.ordering %}{{ query.ordering }}{% endif %}</pre></td>
<td>{% if query.skip %}{{ query.skip }}{% endif %}</td>
<td>{% if query.limit %}{{ query.limit }}{% endif %}</td>
<td><a href="javascript:void(0);" class="mongo-toggle-trace" data-row="{{ forloop.counter }}">Toggle</a></td>
</tr>
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td colspan="8">
<table class="mongo-stack-trace "id="mongo-stack-trace-{{ forloop.counter }}">
<thead>
<tr>
<th>Line</th>
<th>File</th>
<th>Function</th>
<th>Code</th>
</tr>
</thead>
<tbody>
{% for line in query.stack_trace %}
<tr>
<td class="lineno">{{ line.1 }}</td>
<td class="file">{{ line.0 }}</td>
<td class="function">{{ line.2 }}</td>
<td class="code">{{ line.3|highlight:"python"|safe }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!--<pre class="mongo-stack-trace">{{ query.stack_trace|format_stack_trace }}</pre>-->
</td>
</tr>
{% endfor %}
</tbody>
......@@ -45,7 +84,7 @@ pre.mongo-highlight, pre.mongo-highlight span {
<h4>Inserts</h4>
{% if inserts %}
<table>
<table class="mongo-op-table">
<thead>
<tr>
<th>Time (ms)</th>
......@@ -58,7 +97,7 @@ pre.mongo-highlight, pre.mongo-highlight span {
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td>{{ insert.time|floatformat:"4" }}</td>
<td>
<pre class="mongo-highlight">{{ insert.document|format_dict:120|highlight_json|safe }}</pre>
<pre class="mongo-highlight">{{ insert.document|format_dict:120|highlight:"javascript"|safe }}</pre>
</td>
<td>{{ insert.safe }}</td>
</tr>
......@@ -71,7 +110,7 @@ pre.mongo-highlight, pre.mongo-highlight span {
<h4>Removes</h4>
{% if removes %}
<table>
<table class="mongo-op-table">
<thead>
<tr>
<th>Time (ms)</th>
......@@ -84,7 +123,7 @@ pre.mongo-highlight, pre.mongo-highlight span {
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td>{{ remove.time|floatformat:"4" }}</td>
<td>
<pre class="mongo-highlight">{{ remove.spec_or_id|format_dict:120|highlight_json|safe }}</pre>
<pre class="mongo-highlight">{{ remove.spec_or_id|format_dict:120|highlight:"javascript"|safe }}</pre>
</td>
<td>{{ remove.safe }}</td>
</tr>
......@@ -97,7 +136,7 @@ pre.mongo-highlight, pre.mongo-highlight span {
<h4>Updates</h4>
{% if updates %}
<table>
<table class="mongo-op-table">
<thead>
<tr>
<th>Time (ms)</th>
......@@ -113,10 +152,10 @@ pre.mongo-highlight, pre.mongo-highlight span {
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td>{{ update.time|floatformat:"4" }}</td>
<td>
<pre class="mongo-highlight">{{ update.spec|format_dict:120|highlight_json|safe }}</pre>
<pre class="mongo-highlight">{{ update.spec|format_dict:120|highlight:"javascript"|safe }}</pre>
</td>
<td>
<pre class="mongo-highlight">{{ update.document|format_dict:120|highlight_json|safe }}</pre>
<pre class="mongo-highlight">{{ update.document|format_dict:120|highlight:"javascript"|safe }}</pre>
</td>
<td>{{ update.safe }}</td>
<td>{{ update.multi }}</td>
......@@ -129,3 +168,24 @@ pre.mongo-highlight, pre.mongo-highlight span {
<p>No updates recorded</p>
{% endif %}
<script>
(function() {
var toggleButtons = document.querySelectorAll('a.mongo-toggle-trace');
for (var i = 0; i < toggleButtons.length; i++) {
(function() {
var button = toggleButtons[i];
var index = button.dataset.row;
var trace = document.getElementById('mongo-stack-trace-' + index);
trace.style.display = "none";
button.addEventListener("click", function() {
if (trace.style.display == "none") {
trace.style.display = "";
} else {
trace.style.display = "none";
}
}, true);
})();
}
})();
</script>
from django import template
from django.utils.html import escape
from django.utils.safestring import mark_safe
import pprint
register = template.Library()
@register.filter
def format_stack_trace(value):
stack_trace = []
fmt = (
'<span class="path">{0}/</span>'
'<span class="file">{1}</span> in <span class="func">{3}</span>'
'(<span class="lineno">{2}</span>) <span class="code">{4}</span>'
)
for frame in value:
params = map(escape, frame[0].rsplit('/', 1) + list(frame[1:]))
stack_trace.append(fmt.format(*params))
return mark_safe('\n'.join(stack_trace))
@register.filter
def format_dict(value, width=60):
return pprint.pformat(value, width=int(width))
@register.filter
def highlight_json(value):
def highlight(value, language):
try:
from pygments import highlight
from pygments.lexers import JavascriptLexer
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
except ImportError:
return value
# Can't use class-based colouring because the debug toolbar's css rules
# are more specific so take precedence
formatter = HtmlFormatter(style='friendly', nowrap=True, noclasses=True)
return highlight(value, JavascriptLexer(), formatter)
return highlight(value, get_lexer_by_name(language), formatter)
......@@ -37,10 +37,10 @@ DEBUG_TOOLBAR_PANELS = (
'debug_toolbar.panels.headers.HeaderDebugPanel',
'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
'debug_toolbar.panels.template.TemplateDebugPanel',
'debug_toolbar_mongo.panel.MongoDebugPanel',
'debug_toolbar.panels.sql.SQLDebugPanel',
'debug_toolbar.panels.signals.SignalDebugPanel',
'debug_toolbar.panels.logger.LoggingPanel',
'debug_toolbar_mongo.panel.MongoDebugPanel',
)
ROOT_URLCONF = 'example.urls'
......
......@@ -8,7 +8,9 @@ conn = pymongo.Connection()
db = conn.debug_test
def index(request):
list(db.test.find({'name': 'test'}))
#list(db.test.find({'name': 'test'}))
db.test.find({'name': 'test'}).count()
db.test.find({'name': 'test'}).count()
list(db.test.find({'name': 'test', 'age': {'$lt': 134234}}).skip(1))
db.test.find({'name': 'test'}).count()
db.test.find({'name': 'test'}).skip(1).count(with_limit_and_skip=True)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment