Source code for thriftpool.app.log
"""Configure logging subsystem."""
from __future__ import absolute_import
from logging.handlers import WatchedFileHandler
import logging
import sys
import os
from thriftpool.signals import setup_logging, after_logging_setup
from thriftpool.utils.logs import ColorFormatter, LoggingProxy
from thriftpool.utils.term import colored, isatty
from thriftpool.utils.debug import RequestLogger
__all__ = ['Logging']
[docs]class Logging(object):
"""Setup logging subsystem."""
app = None
def __init__(self):
config = self.app.config
logfile = self.logfile = config.LOG_FILE
self.loglevel = config.LOGGING_LEVEL
self.format = config.DEFAULT_WORKER_LOG_FMT \
if os.getenv('IS_WORKER', False) \
else config.DEFAULT_LOG_FMT
colorized = config.LOG_FORCE_COLORIZED = self.colorized = \
config.LOG_FORCE_COLORIZED or self.colorize(logfile)
self.colored = colored(enabled=colorized)
self.request_logger = None
self.tornado_logger = None
[docs] def redirect_stdouts_to_logger(self, logger, loglevel=None, stdout=True,
stderr=True):
"""Redirect :class:`sys.stdout` and :class:`sys.stderr` to a
logging instance.
:param logger: The :class:`logging.Logger` instance to redirect to.
:param loglevel: The loglevel redirected messages will be logged as.
"""
proxy = LoggingProxy(logger, loglevel)
if stdout:
sys.stdout = proxy
if stderr:
sys.stderr = proxy
return proxy
[docs] def get_handler(self, logfile=None):
"""Create log handler with either a filename, an open stream
or :const:`None` (stderr).
"""
logfile = sys.stderr if logfile is None else logfile
if hasattr(logfile, 'write'):
return logging.StreamHandler(logfile)
return WatchedFileHandler(logfile)
[docs] def colorize(self, logfile=None):
"""Can be output colored?"""
return isatty(sys.stderr) if logfile is None else False
[docs] def setup_handlers(self, logger, logfile, format,
formatter=ColorFormatter):
"""Register needed handlers for given logger. If ``logfile`` equal to
:const:`None` use :attr:`sys.stderr` as ``logfile``.
"""
colorize = self.colorize(logfile)
datefmt = '%H:%M:%S' if logfile is None else '%Y-%m-%d %H:%M:%S'
handler = self.get_handler(logfile)
handler.setFormatter(formatter(format, use_color=colorize,
datefmt=datefmt))
logger.addHandler(handler)
return logger
[docs] def setup_request_logging(self):
"""Setup system to log requests."""
logger = logging.getLogger('thriftpool.requests')
self.request_logger = RequestLogger(logger, self.colored)
self.request_logger.setup()
[docs] def setup_tornado_logger(self):
self.tornado_logger = logging.getLogger('thriftpool.tornado')
[docs] def setup(self):
root = logging.getLogger()
root.setLevel(self.loglevel)
receivers = setup_logging.send(sender=self, root=root,
logfile=self.logfile,
loglevel=self.loglevel)
if not receivers:
self.setup_handlers(root, self.logfile, self.format)
after_logging_setup.send(sender=self, root=root,
logfile=self.logfile,
loglevel=self.loglevel)
if self.app.config.LOG_REQUESTS:
self.setup_request_logging()
if self.app.config.LOG_TORNADO_REQUESTS:
self.setup_tornado_logger()
[docs] def log_tornado_request(self, handler):
logger = self.tornado_logger
if logger is None:
return
if handler.get_status() < 400:
log_method = logger.info
elif handler.get_status() < 500:
log_method = logger.warning
else:
log_method = logger.error
request_time = 1000.0 * handler.request.request_time()
log_method("%d %s %.2fms", handler.get_status(),
handler._request_summary(), request_time)