Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added support for LogBook. Thanks to Vincent Driessen for the idea and
patch.

Signed-off-by: Rob Hudson <rob@cogit8.org>
  • Loading branch information
nvie authored and robhudson committed Jan 9, 2011
1 parent 6578f0b commit 1d90d8e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.rst
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
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
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

0 comments on commit 1d90d8e

Please sign in to comment.