Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Currently, the following panels have been written and are working:
- Templates and context used, and their template paths
- SQL queries including time to execute and links to EXPLAIN each query
- List of signals, their args and receivers
- Logging output via Python's built-in logging module
- Logging output via Python's built-in logging, or via the `logbook <http://logbook.pocoo.org>`_ module

There is also one Django management command currently:

Expand Down
78 changes: 58 additions & 20 deletions debug_toolbar/panels/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel

class ThreadTrackingHandler(logging.Handler):

class LogCollector(object):
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 add_record(self, record, thread=None):
self.get_records(thread).append(record)

def get_records(self, thread=None):
"""
Expand All @@ -36,28 +36,75 @@ def clear_records(self, thread=None):
if thread in self.records:
del self.records[thread]

handler = ThreadTrackingHandler()

class ThreadTrackingHandler(logging.Handler):
def __init__(self, collector):
logging.Handler.__init__(self)
self.collector = collector

def emit(self, record):
record = {
'message': record.getMessage(),
'time': datetime.datetime.fromtimestamp(record.created),
'level': record.levelname,
'file': record.pathname,
'line': record.lineno,
'channel': record.name,
}
self.collector.add_record(record)


collector = LogCollector()
logging_handler = ThreadTrackingHandler(collector)
logging.root.setLevel(logging.NOTSET)
logging.root.addHandler(handler)
logging.root.addHandler(logging_handler) # register with logging

try:
import logbook
logbook_supported = True
except ImportError:
# logbook support is optional, so fail silently
logbook_supported = False

if logbook_supported:
class LogbookThreadTrackingHandler(logbook.handlers.Handler):
def __init__(self, collector):
logbook.handlers.Handler.__init__(self, bubble=True)
self.collector = collector

def emit(self, record):
record = {
'message': record.message,
'time': record.time,
'level': record.level_name,
'file': record.filename,
'line': record.lineno,
'channel': record.channel,
}
self.collector.add_record(record)


logbook_handler = LogbookThreadTrackingHandler(collector)
logbook_handler.push_application() # register with logbook

class LoggingPanel(DebugPanel):
name = 'Logging'
has_content = True

def process_request(self, request):
handler.clear_records()
collector.clear_records()

def get_and_delete(self):
records = handler.get_records()
handler.clear_records()
records = collector.get_records()
collector.clear_records()
return records

def nav_title(self):
return _("Logging")

def nav_subtitle(self):
# FIXME l10n: use ngettext
return "%s message%s" % (len(handler.get_records()), (len(handler.get_records()) == 1) and '' or 's')
return "%s message%s" % (len(collector.get_records()), (len(collector.get_records()) == 1) and '' or 's')

def title(self):
return _('Log Messages')
Expand All @@ -66,16 +113,7 @@ 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,
})

records = self.get_and_delete()
context = self.context.copy()
context.update({'records': records})

Expand Down
2 changes: 2 additions & 0 deletions debug_toolbar/templates/debug_toolbar/panels/logger.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<tr>
<th>{% trans "Level" %}</th>
<th>{% trans "Time" %}</th>
<th>{% trans "Channel" %}</th>
<th>{% trans "Message" %}</th>
<th>{% trans "Location" %}</th>
</tr>
Expand All @@ -14,6 +15,7 @@
<tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}">
<td>{{ record.level }}</td>
<td>{{ record.time|date:"h:i:s m/d/Y" }}</td>
<td>{{ record.channel|default:"-" }}</td>
<td>{{ record.message }}</td>
<td>{{ record.file }}:{{ record.line }}</td>
</tr>
Expand Down