Commit 9799edf3 by Rafael Viotti

Improvements on the MongoDB navigation panel

The sidebar now shows the count and time elapsed for each type of
operation performed: read, insert, update, remove.

Changed some code to better reflect MongoDB terminology. The default
operation is now find, instead of query. Queries table became the Reads
table since it displays finds, counts, commands etc. Also, query is
mostly a relational database term.

Corrected the layout of tables, which now properly occupy 100% width of
their containers.
parent 931055bd
...@@ -145,7 +145,7 @@ def _cursor_refresh(cursor_self): ...@@ -145,7 +145,7 @@ def _cursor_refresh(cursor_self):
__traceback_hide__ = True __traceback_hide__ = True
query_data = { query_data = {
'time': total_time, 'time': total_time,
'operation': 'query', 'operation': 'find',
'stack_trace': _get_stacktrace(), 'stack_trace': _get_stacktrace(),
} }
...@@ -161,7 +161,7 @@ def _cursor_refresh(cursor_self): ...@@ -161,7 +161,7 @@ def _cursor_refresh(cursor_self):
query_data['collection'] = query_son['count'] query_data['collection'] = query_son['count']
query_data['operation'] = 'count' query_data['operation'] = 'count'
query_data['skip'] = query_son.get('skip') query_data['skip'] = query_son.get('skip')
query_data['limit'] = query_son.get('limit') query_data['limit'] = abs(query_son.get('limit', 0))
query_data['query'] = query_son['query'] query_data['query'] = query_son['query']
elif 'aggregate' in query_son: elif 'aggregate' in query_son:
query_data['collection'] = query_son['aggregate'] query_data['collection'] = query_son['aggregate']
...@@ -172,7 +172,7 @@ def _cursor_refresh(cursor_self): ...@@ -172,7 +172,7 @@ def _cursor_refresh(cursor_self):
else: else:
# Normal Query # Normal Query
query_data['skip'] = privar('skip') query_data['skip'] = privar('skip')
query_data['limit'] = privar('limit') query_data['limit'] = abs(privar('limit') or 0)
query_data['query'] = query_son.get('$query') or query_son query_data['query'] = query_son.get('$query') or query_son
query_data['ordering'] = _get_ordering(query_son) query_data['ordering'] = _get_ordering(query_son)
......
from django.template import Template, Context
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
from debug_toolbar.panels import DebugPanel from debug_toolbar.panels import DebugPanel
import operation_tracker import operation_tracker
_NAV_SUBTITLE_TPL = u'''
{% for o, n, t in operations %}
{{ n }} {{ o }}{{ n|pluralize }} in {{ t }}ms<br/>
{% if forloop.last and forloop.counter0 %}
{{ count }} operation{{ count|pluralize }} in {{ time }}ms
{% endif %}
{% endfor %}
'''
class MongoDebugPanel(DebugPanel): class MongoDebugPanel(DebugPanel):
"""Panel that shows information about MongoDB operations. """Panel that shows information about MongoDB operations.
...@@ -22,11 +33,32 @@ class MongoDebugPanel(DebugPanel): ...@@ -22,11 +33,32 @@ class MongoDebugPanel(DebugPanel):
return 'MongoDB' return 'MongoDB'
def nav_subtitle(self): def nav_subtitle(self):
num_queries = len(operation_tracker.queries) fun = lambda x, y: (x, len(y), '%.2f' % sum(z['time'] for z in y))
attrs = ['queries', 'inserts', 'updates', 'removes'] ctx = {'operations': [], 'count': 0, 'time': 0}
total_time = sum(sum(o['time'] for o in getattr(operation_tracker, a))
for a in attrs) if operation_tracker.queries:
return '{0} operations in {1:.2f}ms'.format(num_queries, total_time) ctx['operations'].append(fun('read', operation_tracker.queries))
ctx['count'] += len(operation_tracker.queries)
ctx['time'] += sum(x['time'] for x in operation_tracker.queries)
if operation_tracker.inserts:
ctx['operations'].append(fun('insert', operation_tracker.inserts))
ctx['count'] += len(operation_tracker.inserts)
ctx['time'] += sum(x['time'] for x in operation_tracker.inserts)
if operation_tracker.updates:
ctx['operations'].append(fun('update', operation_tracker.updates))
ctx['count'] += len(operation_tracker.updates)
ctx['time'] += sum(x['time'] for x in operation_tracker.updates)
if operation_tracker.removes:
ctx['operations'].append(fun('remove', operation_tracker.removes))
ctx['count'] += len(operation_tracker.removes)
ctx['time'] += sum(x['time'] for x in operation_tracker.removes)
ctx['time'] = '%.2f' % ctx['time']
return mark_safe(Template(_NAV_SUBTITLE_TPL).render(Context(ctx)))
def title(self): def title(self):
return 'MongoDB Operations' return 'MongoDB Operations'
......
{% load mongo_debug_tags %} {% load mongo_debug_tags %}
<style type="text/css"> <style type="text/css">
#djDebug .panelContent tbody th {
width: auto;
}
#djDebug .panelContent table {
display: table;
}
#djDebug tr.row1 {
background-color: #F5F5F5;
}
#djDebug #djDebugRequestVarsPanel table:first-of-type tbody tr:nth-child(odd) {
background-color: #F5F5F5;
}
pre.mongo-highlight, pre.mongo-highlight span { pre.mongo-highlight, pre.mongo-highlight span {
font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', 'Monaco', 'Courier New', monospace !important; font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', 'Monaco', 'Courier New', monospace !important;
font-size: 1.05em !important; font-size: 1.05em !important;
...@@ -19,7 +31,7 @@ table.mongo-op-table tbody { ...@@ -19,7 +31,7 @@ table.mongo-op-table tbody {
} }
</style> </style>
<h4>Queries</h4> <h4>Reads</h4>
{% if queries %} {% if queries %}
<table class="mongo-op-table"> <table class="mongo-op-table">
<thead> <thead>
...@@ -27,7 +39,7 @@ table.mongo-op-table tbody { ...@@ -27,7 +39,7 @@ table.mongo-op-table tbody {
<th>Time (ms)</th> <th>Time (ms)</th>
<th>Operation</th> <th>Operation</th>
<th>Collection</th> <th>Collection</th>
<th>Query</th> <th style="width: 100%">Query</th>
<th>Ordering</th> <th>Ordering</th>
<th>Skip</th> <th>Skip</th>
<th>Limit</th> <th>Limit</th>
...@@ -42,12 +54,12 @@ table.mongo-op-table tbody { ...@@ -42,12 +54,12 @@ table.mongo-op-table tbody {
<td>{{ query.collection }}</td> <td>{{ query.collection }}</td>
<td> <td>
{% if query.query %} {% if query.query %}
<pre class="mongo-highlight">{{ query.query|format_dict|highlight:"javascript"|safe }}</pre> <pre class="mongo-highlight">{{ query.query|format_dict|highlight:"javascript"|safe }}</pre>
{% endif %} {% endif %}
</td> </td>
<td><pre class="mongo-highlight">{% if query.ordering %}{{ query.ordering }}{% endif %}</pre></td> <td>{% if query.ordering %}<pre class="mongo-highlight">{{ query.ordering }}</pre>{% endif %}</td>
<td>{% if query.skip %}{{ query.skip }}{% endif %}</td> <td>{{ query.skip|default:"" }}</td>
<td>{% if query.limit %}{{ query.limit }}{% endif %}</td> <td>{{ query.limit|default:"" }}</td>
<td><a href="javascript:void(0);" class="mongo-toggle-trace" data-row="queries-{{ forloop.counter }}">Toggle</a></td> <td><a href="javascript:void(0);" class="mongo-toggle-trace" data-row="queries-{{ forloop.counter }}">Toggle</a></td>
</tr> </tr>
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}"> <tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
...@@ -87,7 +99,7 @@ table.mongo-op-table tbody { ...@@ -87,7 +99,7 @@ table.mongo-op-table tbody {
<thead> <thead>
<tr> <tr>
<th>Time (ms)</th> <th>Time (ms)</th>
<th>Document</th> <th style="width: 100%">Document</th>
<th>Safe</th> <th>Safe</th>
<th>Stack Trace</th> <th>Stack Trace</th>
</tr> </tr>
...@@ -133,30 +145,38 @@ table.mongo-op-table tbody { ...@@ -133,30 +145,38 @@ table.mongo-op-table tbody {
<p>No inserts recorded</p> <p>No inserts recorded</p>
{% endif %} {% endif %}
<h4>Removes</h4> <h4>Updates</h4>
{% if removes %} {% if updates %}
<table class="mongo-op-table"> <table class="mongo-op-table">
<thead> <thead>
<tr> <tr>
<th>Time (ms)</th> <th>Time (ms)</th>
<th>Query / Id</th> <th>Query</th>
<th style="width: 100%">Update</th>
<th>Safe</th> <th>Safe</th>
<th>Multi</th>
<th>Upsert</th>
<th>Stack Trace</th> <th>Stack Trace</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for remove in removes %} {% for update in updates %}
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}"> <tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td>{{ remove.time|floatformat:"4" }}</td> <td>{{ update.time|floatformat:"4" }}</td>
<td> <td>
<pre class="mongo-highlight">{{ remove.spec_or_id|format_dict:120|highlight:"javascript"|safe }}</pre> <pre class="mongo-highlight">{{ update.spec|format_dict:120|highlight:"javascript"|safe }}</pre>
</td> </td>
<td>{{ remove.safe }}</td> <td>
<td><a href="javascript:void(0);" class="mongo-toggle-trace" data-row="removes-{{ forloop.counter }}">Toggle</a></td> <pre class="mongo-highlight">{{ update.document|format_dict:120|highlight:"javascript"|safe }}</pre>
</td>
<td>{{ update.safe }}</td>
<td>{{ update.multi }}</td>
<td>{{ update.upsert }}</td>
<td><a href="javascript:void(0);" class="mongo-toggle-trace" data-row="updates-{{ forloop.counter }}">Toggle</a></td>
</tr> </tr>
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}"> <tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td colspan="4"> <td colspan="7">
<table class="mongo-stack-trace "id="mongo-stack-trace-removes-{{ forloop.counter }}"> <table class="mongo-stack-trace "id="mongo-stack-trace-updates-{{ forloop.counter }}">
<thead> <thead>
<tr> <tr>
<th>Line</th> <th>Line</th>
...@@ -166,7 +186,7 @@ table.mongo-op-table tbody { ...@@ -166,7 +186,7 @@ table.mongo-op-table tbody {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for line in remove.stack_trace %} {% for line in update.stack_trace %}
<tr> <tr>
<td class="lineno">{{ line.1 }}</td> <td class="lineno">{{ line.1 }}</td>
<td class="file">{{ line.0|embolden_file }}</td> <td class="file">{{ line.0|embolden_file }}</td>
...@@ -182,41 +202,33 @@ table.mongo-op-table tbody { ...@@ -182,41 +202,33 @@ table.mongo-op-table tbody {
</tbody> </tbody>
</table> </table>
{% else %} {% else %}
<p>No removes recorded</p> <p>No updates recorded</p>
{% endif %} {% endif %}
<h4>Updates</h4> <h4>Removes</h4>
{% if updates %} {% if removes %}
<table class="mongo-op-table"> <table class="mongo-op-table">
<thead> <thead>
<tr> <tr>
<th>Time (ms)</th> <th>Time (ms)</th>
<th>Query</th> <th style="width: 100%">Query / Id</th>
<th>Update</th>
<th>Safe</th> <th>Safe</th>
<th>Multi</th>
<th>Upsert</th>
<th>Stack Trace</th> <th>Stack Trace</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for update in updates %} {% for remove in removes %}
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}"> <tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td>{{ update.time|floatformat:"4" }}</td> <td>{{ remove.time|floatformat:"4" }}</td>
<td>
<pre class="mongo-highlight">{{ update.spec|format_dict:120|highlight:"javascript"|safe }}</pre>
</td>
<td> <td>
<pre class="mongo-highlight">{{ update.document|format_dict:120|highlight:"javascript"|safe }}</pre> <pre class="mongo-highlight">{{ remove.spec_or_id|format_dict:120|highlight:"javascript"|safe }}</pre>
</td> </td>
<td>{{ update.safe }}</td> <td>{{ remove.safe }}</td>
<td>{{ update.multi }}</td> <td><a href="javascript:void(0);" class="mongo-toggle-trace" data-row="removes-{{ forloop.counter }}">Toggle</a></td>
<td>{{ update.upsert }}</td>
<td><a href="javascript:void(0);" class="mongo-toggle-trace" data-row="updates-{{ forloop.counter }}">Toggle</a></td>
</tr> </tr>
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}"> <tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td colspan="7"> <td colspan="4">
<table class="mongo-stack-trace "id="mongo-stack-trace-updates-{{ forloop.counter }}"> <table class="mongo-stack-trace "id="mongo-stack-trace-removes-{{ forloop.counter }}">
<thead> <thead>
<tr> <tr>
<th>Line</th> <th>Line</th>
...@@ -226,7 +238,7 @@ table.mongo-op-table tbody { ...@@ -226,7 +238,7 @@ table.mongo-op-table tbody {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for line in update.stack_trace %} {% for line in remove.stack_trace %}
<tr> <tr>
<td class="lineno">{{ line.1 }}</td> <td class="lineno">{{ line.1 }}</td>
<td class="file">{{ line.0|embolden_file }}</td> <td class="file">{{ line.0|embolden_file }}</td>
...@@ -242,7 +254,7 @@ table.mongo-op-table tbody { ...@@ -242,7 +254,7 @@ table.mongo-op-table tbody {
</tbody> </tbody>
</table> </table>
{% else %} {% else %}
<p>No updates recorded</p> <p>No removes recorded</p>
{% endif %} {% endif %}
<script> <script>
......
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