Created
March 26, 2015 13:43
-
-
Save evilkost/61b977458cd4949318f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RedisLogHandler(Process): | |
""" | |
Single point to collect logs through redis pub/sub and write | |
them through standard python logging lib | |
""" | |
def __init__(self, opts): | |
Process.__init__(self, name="log_handler") | |
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", "job_grab", "backend"] | |
def setup_logging(self): | |
formatter = logging.Formatter( | |
'[%(asctime)s][%(levelname)6s][%(name)10s][%(pathname)s:%(funcName)s:%(lineno)d] %(message)s') | |
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(formatter) | |
self.main_logger.addHandler(self.main_handler) | |
self.router_logger = logging.Logger("log_router") | |
self.router_logger.addFilter(CustomFilter()) | |
for component in self.components: | |
handler = logging.handlers.WatchedFileHandler( | |
filename=os.path.join(self.log_dir, "{}.log".format(component))) | |
handler.setFormatter(formatter) | |
# not very good from performance point: | |
# filter called for each message, but only one handler process record | |
# but it shouldn't be a real problem | |
handler.addFilter(filter=LogRouterFilter(component)) | |
self.router_logger.addHandler(handler) | |
def handle_msg(self, raw): | |
try: | |
event = json.loads(raw["data"]) | |
# expected fields: | |
# - who: self.components | |
# - level: "info", "debug", "error", None --> default is "info" | |
# - msg: str with log msg | |
# [- traceback: str with error traceback ] | |
# [ more LogRecord kwargs, see: https://docs.python.org/2/library/logging.html#logrecord-objects] | |
for key in ["who", "msg"]: | |
if key not in event: | |
raise Exception("Handler received msg without `{}` field, msg: {}".format(key, event)) | |
who = event["who"] | |
if who not in self.components: | |
raise Exception("Handler received msg with unknown `who` field, msg: {}".format(event)) | |
level = level_map[event.pop("level", "info")] | |
msg = event.pop("msg") | |
self.router_logger.log(level, msg, extra={"event": event}) | |
except Exception as err: | |
self.main_logger.exception(err) | |
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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment