import logging from common.compat import basestring from common.logging_extra import SwagFormatter, json_robust_dumps from logstash_async.handler import AsynchronousLogstashHandler from logstash_async.transport import UdpTransport # elasticsearch doesnt allow different 'keys' with the different types in the same index class SwagLogstashFormatter(SwagFormatter): def __init__(self, swaglogger): super(SwagLogstashFormatter, self).__init__(swaglogger) def fix_kv(self, k, v): if isinstance(v, basestring): k += "$s" elif isinstance(v, float): k += "$f" elif isinstance(v, bool): k += "$b" elif isinstance(v, int): k += "$i" elif isinstance(v, dict): nv = {} for ik, iv in v.items(): ik, iv = self.fix_kv(ik, iv) nv[ik] = iv v = nv elif isinstance(v, list): k += "$a" return k, v def format(self, record): v = self.format_dict(record) mk, mv = self.fix_kv('msg', v['msg']) del v['msg'] v[mk] = mv return json_robust_dumps(v) class SwagLogstashHandler(AsynchronousLogstashHandler): def __init__(self, host, port, name, formatter): super(SwagLogstashHandler, self).__init__(host, port, database_path=None, transport=UdpTransport) self.name = name if not isinstance(formatter, SwagLogstashFormatter): raise ValueError("formatter must be swag") self.setFormatter(formatter) def emit(self, record): record.name = self.name super(SwagLogstashHandler, self).emit(record) if __name__ == "__main__": from common.logging_extra import SwagLogger log = SwagLogger() ls_formatter = SwagLogstashFormatter(log) ls_handler = SwagLogstashHandler("logstash.comma.life", 5040, "pipeline", ls_formatter) log.addHandler(ls_handler) s_handler = logging.StreamHandler() log.addHandler(s_handler) log.info("asynclogtest %s", "1") log.info({'asynclogtest': 2}) log.warning("asynclogtest warning") log.error("asynclogtest error") log.critical("asynclogtest critical") log.event("asynclogtest", a="b")