Permalink
Browse files

Track pymongo response message size and how raw response data and siz…

…e into the mongo-panel.
  • Loading branch information...
1 parent bcb016d commit 8f9fc12cec6e95a199277d6ee630ebc7bfd47f0b @jorgebastida jorgebastida committed Jan 23, 2012
Showing with 68 additions and 17 deletions.
  1. +28 −2 flaskext/mongoengine/operation_tracker.py
  2. +40 −15 flaskext/mongoengine/templates/panels/mongo-panel.html
View
30 flaskext/mongoengine/operation_tracker.py
@@ -1,29 +1,45 @@
import functools
import time
import inspect
+import copy
import sys
import os
import pymongo
import pymongo.collection
import pymongo.cursor
+import pymongo.helpers
+
__all__ = ['queries', 'inserts', 'updates', 'removes', 'install_tracker',
- 'uninstall_tracker', 'reset']
+ 'uninstall_tracker', 'reset', 'response_sizes']
_original_methods = {
'insert': pymongo.collection.Collection.insert,
'update': pymongo.collection.Collection.update,
'remove': pymongo.collection.Collection.remove,
'refresh': pymongo.cursor.Cursor._refresh,
+ '_unpack_response': pymongo.helpers._unpack_response,
}
queries = []
inserts = []
updates = []
removes = []
+response_sizes = []
+
+# Wrap helpers._unpack_response for getting response size
+@functools.wraps(_original_methods['_unpack_response'])
+def _unpack_response(response, *args, **kwargs):
+ result = _original_methods['_unpack_response'](
+ response,
+ *args,
+ **kwargs
+ )
+ response_sizes.append(sys.getsizeof(response) / 1024.0)
+ return result
# Wrap Cursor._refresh for getting queries
@functools.wraps(_original_methods['insert'])
@@ -45,6 +61,7 @@ def _insert(collection_self, doc_or_docs, manipulate=True,
'safe': safe,
'time': total_time,
'stack_trace': _tidy_stacktrace(),
+ 'size': response_sizes[-1],
})
return result
@@ -73,6 +90,7 @@ def _update(collection_self, spec, document, upsert=False,
'safe': safe,
'time': total_time,
'stack_trace': _tidy_stacktrace(),
+ 'size': response_sizes[-1]
})
return result
@@ -94,6 +112,7 @@ def _remove(collection_self, spec_or_id, safe=False, **kwargs):
'safe': safe,
'time': total_time,
' ': _tidy_stacktrace(),
+ 'size': response_sizes[-1]
})
return result
@@ -123,6 +142,8 @@ def privar(name):
'time': total_time,
'operation': 'query',
'stack_trace': _tidy_stacktrace(),
+ 'size': response_sizes[-1],
+ 'data': copy.copy(privar('data'))
}
# Collection in format <db_name>.<collection_name>
@@ -159,6 +180,8 @@ def install_tracker():
pymongo.collection.Collection.remove = _remove
if pymongo.cursor.Cursor._refresh != _cursor_refresh:
pymongo.cursor.Cursor._refresh = _cursor_refresh
+ if pymongo.helpers._unpack_response != _unpack_response:
+ pymongo.helpers._unpack_response = _unpack_response
def uninstall_tracker():
if pymongo.collection.Collection.insert == _insert:
@@ -169,13 +192,16 @@ def uninstall_tracker():
pymongo.collection.Collection.remove = _original_methods['remove']
if pymongo.cursor.Cursor._refresh == _cursor_refresh:
pymongo.cursor.Cursor._refresh = _original_methods['cursor_refresh']
+ if pymongo.helpers._unpack_response == _unpack_response:
+ pymongo.helpers._unpack_response = _original_methods['_unpack_response']
def reset():
- global queries, inserts, updates, removes
+ global queries, inserts, updates, removes, response_sizes
queries = []
inserts = []
updates = []
removes = []
+ response_sizes = []
def _get_ordering(son):
"""Helper function to extract formatted ordering from dict.
View
55 flaskext/mongoengine/templates/panels/mongo-panel.html
@@ -23,19 +23,22 @@
<thead>
<tr>
<th>Time (ms)</th>
+ <th>Size</th>
<th>Operation</th>
<th>Collection</th>
<th>Query</th>
<th>Ordering</th>
<th>Skip</th>
<th>Limit</th>
+ <th>Data</th>
<th>Stack Trace</th>
</tr>
</thead>
<tbody>
{% for query in queries %}
<tr class="{{ loop.cycle('djDebugOdd' 'djDebugEven') }}">
<td style="{{ 'color:red;' if query.time > slow_query_limit else '' }}">{{ query.time|round(3) }}</td>
+ <td>{{ query.size|round(2) }}Kb</td>
<td>{{ query.operation|title }}</td>
<td>{{ query.collection }}</td>
<td>
@@ -46,10 +49,18 @@
<td><span 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-data" data-row="data-{{ loop.index }}">Toggle</a></td>
<td><a href="javascript:void(0);" class="mongo-toggle-trace" data-row="queries-{{ loop.index }}">Toggle</a></td>
</tr>
<tr class="{{ loop.cycle('djDebugOdd' 'djDebugEven') }}">
<td colspan="8">
+ <div class="mongo-data" id="mongo-data-{{ loop.index }}">
+ <code>{{ query.data|pprint }}</code>
+ </div>
+ </td>
+ </tr>
+ <tr class="{{ loop.cycle('djDebugOdd' 'djDebugEven') }}">
+ <td colspan="8">
<table class="mongo-stack-trace "id="mongo-stack-trace-queries-{{ loop.index }}">
<thead>
<tr>
@@ -85,6 +96,7 @@
<thead>
<tr>
<th>Time (ms)</th>
+ <th>Size</th>
<th>Document</th>
<th>Safe</th>
<th>Stack Trace</th>
@@ -94,6 +106,7 @@
{% for insert in inserts %}
<tr class="{{ loop.cycle('djDebugOdd' 'djDebugEven') }}">
<td style="{{ 'color:red;' if insert.time > slow_query_limit else '' }}">{{ insert.time|round(3) }}</td>
+ <td>{{ insert.size|round(2) }}Kb</td>
<td>
<span class="mongo-highlight">{{ insert.document|safe }}</pre>
</td>
@@ -137,6 +150,7 @@
<thead>
<tr>
<th>Time (ms)</th>
+ <th>Size</th>
<th>Query / Id</th>
<th>Safe</th>
<th>Stack Trace</th>
@@ -146,6 +160,7 @@
{% for remove in removes %}
<tr class="{{ loop.cycle('djDebugOdd' 'djDebugEven') }}">
<td style="{{ 'color:red;' if remove.time > slow_query_limit else '' }}">{{ remove.time|round(3) }}</td>
+ <td>{{ remove.size|round(2) }}Kb</td>
<td>
<span class="mongo-highlight">{{ remove.spec_or_id|safe }}</pre>
</td>
@@ -189,6 +204,7 @@
<thead>
<tr>
<th>Time (ms)</th>
+ <th>Size</th>
<th>Query</th>
<th>Update</th>
<th>Safe</th>
@@ -201,6 +217,7 @@
{% for update in updates %}
<tr class="{{ loop.cycle('djDebugOdd' 'djDebugEven') }}">
<td>{{ update.time }}</td>
+ <td>{{ update.size|round(2) }}Kb</td>
<td>
<span class="mongo-highlight">{{ update.spec|safe }}</pre>
</td>
@@ -245,22 +262,30 @@
<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);
- })();
+ function register_toggles(toggle_selector, block_selector){
+ var toggleButtons = document.querySelectorAll(toggle_selector);
+ for (var i = 0; i < toggleButtons.length; i++) {
+ (function() {
+ var button = toggleButtons[i];
+ var index = button.dataset.row;
+ var trace = document.getElementById(block_selector + index);
+ console.log(block_selector);
+ console.log(block_selector + index);
+ trace.style.display = "none";
+
+ button.addEventListener("click", function() {
+ if (trace.style.display == "none") {
+ trace.style.display = "";
+ } else {
+ trace.style.display = "none";
+ }
+ }, true);
+ })();
+ }
}
+ register_toggles('a.mongo-toggle-trace', 'mongo-stack-trace-');
+ register_toggles('a.mongo-toggle-data', 'mongo-');
+
})();
</script>

0 comments on commit 8f9fc12

Please sign in to comment.