import json import logging import socket import sys import traceback from xid import Xid LEVELS = { "DEBUG": 0, "INFO": 1, "WARN": 2, "WARNING": 2, "ERROR": 3 } def new_xid(): return Xid().string() class LogagHandler(logging.Handler): def __init__(self, service_name: str, pod_name: str, ip: str, port: int): super().__init__() self.service_name = service_name self.pod_name = pod_name self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.connection = (ip, port) self.backup_handler = logging.StreamHandler(sys.stdout) self.backup_handler.setFormatter( logging.Formatter(u'[%(levelname)-8s][%(asctime)s][%(filename)s:%(lineno)d] %(message)s')) self.backup_handler.setLevel(logging.INFO) def __send_to_udp(self, data: dict): data = json.dumps(data).encode('utf-8') self.sock.sendto(data, self.connection) def emit(self, record): trace = None if record.exc_info: if isinstance(record.exc_info, tuple) and len(record.exc_info) == 3: trace = ''.join(traceback.format_exception(*record.exc_info)) record.exc_info = None # get xid xid = getattr(record, "xid", None) if xid is None or len(xid) != 20: xid = new_xid() msg = self.format(record) try: json_ = { "timestamp": int(record.created * 1000), "svc": self.service_name, "pod": self.pod_name, "xid": xid, "lvl": LEVELS[record.levelname], "msg": msg, "trace": trace, "requestId": getattr(record, "request_id", None), } self.__send_to_udp(json_) except BaseException as e: self.backup_handler.emit(record)