Source code for backend.daemons.log
# coding: utf-8
import json
import logging
import logging.handlers
import os
from setproctitle import setproctitle
# TODO: remove when RedisLogHandler works fine
from .. import constants
from .. import helpers
from ..constants import default_log_format
[docs]class RedisLogHandler(object):
"""
Single point to collect logs through redis pub/sub and write
them through standard python logging lib
"""
def __init__(self, opts):
self.opts = opts
self.log_dir = os.path.dirname(self.opts.log_dir)
if not os.path.exists(self.log_dir):
os.makedirs(self.log_dir, mode=0o750)
self.components = ["spawner", "terminator", "vmm", "build_dispatcher",
"action_dispatcher", "backend", "actions", "worker"]
[docs] def setup_logging(self):
self.main_logger = logging.Logger("logger", level=logging.DEBUG)
self.main_handler = logging.handlers.WatchedFileHandler(
filename=os.path.join(self.log_dir, "logger.log"))
self.main_handler.setFormatter(default_log_format)
self.main_logger.addHandler(self.main_handler)
level = getattr(logging, self.opts.log_level.upper(), None)
self.loggers = {}
for component in self.components:
logger = logging.Logger(component)
handler = logging.handlers.WatchedFileHandler(
filename=os.path.join(self.log_dir, "{}.log".format(component)))
handler.setFormatter(default_log_format)
handler.setLevel(level)
logger.addHandler(handler)
self.loggers[component] = logger
[docs] def handle_msg(self, raw):
try:
event = json.loads(raw["data"])
who = event.get('who', None)
if not who:
raise Exception("No LogRecord.who field, raw: {}".format(event))
if who not in self.loggers:
raise Exception("Unknown LogRecord.who field: {}, raw event: {}"
.format(who, event))
log_record = logging.makeLogRecord(event)
self.loggers[who].handle(log_record)
except Exception as err:
self.main_logger.exception(err)
[docs] def run(self):
self.setup_logging()
setproctitle("RedisLogHandler")
rc = helpers.get_redis_connection(self.opts)
channel = rc.pubsub(ignore_subscribe_messages=True)
channel.subscribe(constants.LOG_PUB_SUB)
for raw in channel.listen():
if raw is not None and raw.get("type") == "message" and "data" in raw:
self.handle_msg(raw)