nopenpilot/common/logging_es.py

70 lines
2.0 KiB
Python

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")