Files
flask-debugtoolbar/flask_debugtoolbar/panels/logger.py
Matt Good 3d9faa52af Fix missing log output from development server.
Initialize the logging panel log handler on the first request so that
werkzeug sets up its default logger first.  Werkzeug now only adds its
default log handler if no others are set up yet.  So, when the logging
panel set up its logger first, it suppressed the output from the
development server.
2012-01-03 11:07:10 -08:00

107 lines
2.9 KiB
Python

from __future__ import with_statement
import datetime
import logging
try:
import threading
except ImportError:
threading = None
from flask_debugtoolbar.panels import DebugPanel
from flask_debugtoolbar.utils import format_fname
_ = lambda x: x
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 = None
_init_lock = threading.Lock()
def _init_once():
# Initialize the logging handler once, but after werkzeug has set up its
# default logger. Otherwise, if this sets up the logging first, werkzeug
# will not create a default logger, so the development server's output will
# not get printed.
global handler
if handler is not None:
return
with _init_lock:
if handler is not None:
return
handler = ThreadTrackingHandler()
logging.root.addHandler(handler)
class LoggingPanel(DebugPanel):
name = 'Logging'
has_content = True
def process_request(self, request):
_init_once()
handler.clear_records()
def get_and_delete(self):
records = handler.get_records()
handler.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')
def title(self):
return _('Log Messages')
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': format_fname(record.pathname),
'file_long': record.pathname,
'line': record.lineno,
})
context = self.context.copy()
context.update({'records': records})
return self.render('panels/logger.html', context)