Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merging in the Logging panel from Alex Gaynor. Thanks Alex!

  • Loading branch information...
commit f04d10d966fe0cd335fb47829740c5318e5cf43c 3 parents 8d32dc2 + 8d32dc2 + c70df30
@robhudson robhudson authored
View
2  debug_toolbar/media/toolbar.css
@@ -22,7 +22,7 @@
margin: 0;
padding: 0;
line-height: 30px;
- padding: 8px 10px 9px;
+ padding: 8px 9px 9px;
position: relative;
width: auto;
}
View
70 debug_toolbar/panels/logger.py
@@ -0,0 +1,70 @@
+import datetime
+import logging
+try:
+ import threading
+except ImportError:
+ threading = None
+from django.template.loader import render_to_string
+from debug_toolbar.panels import DebugPanel
+
+class ThreadTrackingHandler(logging.Handler):
+ def __init__(self):
+ if threading is None:
+ raise NotImplementedError("threading module is not available, \
+ the logging panel cannot be used without it")
+ logging.Handler.__init__(self)
+ self.records = {} # a dictionary that maps threads to log records
+
+ def emit(self, record):
+ self.get_records().append(record)
+
+ def get_records(self, thread=None):
+ """
+ Returns a list of records for the provided thread, of if none is provided,
+ returns a list for the current thread.
+ """
+ if thread is None:
+ thread = threading.currentThread()
+ if thread not in self.records:
+ self.records[thread] = []
+ return self.records[thread]
+
+ def clear_records(self, thread=None):
+ if thread is None:
+ thread = threading.currentThread()
+ if thread in self.records:
+ del self.records[thread]
+
+handler = ThreadTrackingHandler()
+logging.root.setLevel(logging.NOTSET)
+logging.root.addHandler(handler)
+
+class LoggingPanel(DebugPanel):
+ name = 'Logging'
+ has_content = True
+
+ def process_request(self, request):
+ handler.clear_records()
+
+ def get_and_delete(self):
+ records = handler.get_records()
+ handler.clear_records()
+ return records
+
+ def title(self):
+ return "Logging (%s message%s)" % (len(handler.get_records()), (len(handler.get_records()) == 1) and '' or 's')
+
+ def url(self):
+ return ''
+
+ def content(self):
+ records = []
+ for record in self.get_and_delete():
+ records.append({
+ 'message': record.getMessage(),
+ 'time': datetime.datetime.fromtimestamp(record.created),
+ 'level': record.levelname,
+ 'file': record.pathname,
+ 'line': record.lineno,
+ })
+ return render_to_string('debug_toolbar/panels/logger.html', {'records': records})
View
2  debug_toolbar/templates/debug_toolbar/base.html
@@ -5,7 +5,7 @@
}
</script>
<style type="text/css">
- @import url({{ BASE_URL }}/__debug__/m/toolbar.css);
+ @import url({{ BASE_URL }}/__debug__/m/toolbar.css);
</style>
<div id="djDebug">
<div id="djDebugToolbar">
View
26 debug_toolbar/templates/debug_toolbar/panels/logger.html
@@ -0,0 +1,26 @@
+<h3>Log Messages</h3>
+{% if records %}
+ <table>
+ <thead>
+ <tr>
+ <th>Level</th>
+ <th>Time</th>
+ <th>Message</th>
+ <th>Location</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for record in records %}
+ <tr class="{% cycle 'row1' 'row2' %}">
+ <td>{{ record.level }}</td>
+ <td>{{ record.time|date:"h:i:s m/d/Y" }}</td>
+ <td>{{ record.message }}</td>
+ <td>{{ record.file }}:{{ record.line }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+{% else %}
+ <p>No messages logged.</p>
+{% endif %}
+
View
3  debug_toolbar/toolbar/loader.py
@@ -17,6 +17,7 @@ def __init__(self, request):
'debug_toolbar.panels.sql.SQLDebugPanel',
'debug_toolbar.panels.cache.CacheDebugPanel',
'debug_toolbar.panels.template.TemplateDebugPanel',
+ 'debug_toolbar.panels.logger.LoggingPanel',
)
self.load_panels()
@@ -60,5 +61,5 @@ def render_toolbar(self):
"""
return render_to_string('debug_toolbar/base.html', {
'panels': self.panels,
- 'BASE_URL': self.request.META.get('SCRIPT_NAME', '')
+ 'BASE_URL': self.request.META.get('SCRIPT_NAME', ''),
})
Please sign in to comment.
Something went wrong with that request. Please try again.