python logging 自定义formatter

问题

自定义log formatter, 如添加request_id

方法

  • 定义Logging Filter
    class ServerFilter(logging.Filter):
        ...
        def filter(self, record):
            record.request_id = xxx
            return True
    
    handler.addFilter(ServerFilter())
    handler.setFormatter(ServerFormatter(f"%(asctime)s - {hostname} - [%(levelname)s] - %(filename)s:%(lineno)s: %(name)s: |%(request_id)s| %(message)s"))
    
  • 定义logging Formater
    class ServerFormatter(logging.Formatter):
        ...
        def format(self, record):
            record.request_id = xxx
            
            return super(ServerFormatter, self).format(record)
       
        handler.setFormatter(ServerFormatter(f"%(asctime)s - {hostname} - [%(levelname)s] - %(filename)s:%(lineno)s: %(name)s: |%(request_id)s| %(message)s"))
    
  • 深度自定义Formatter
    class JsonFormatter(logging.Formatter):
        def __init__(self, fmt=None, datefmt=None, style='%', mid="mid_unknown", event_id=None):
            super().__init__(fmt, datefmt, style)
            self.mid = mid
            self.event_id = event_id
    
        def format(self, record):
            # 将 record.message 转换为 JSON 字符串
            if isinstance(record.msg, dict):
                record.msg = json.dumps(record.msg, ensure_ascii=False)
            # 添加 mid 到 record
            record.mid = self.mid
            if 'event_id' in record.__dict__:
                record.event_id = record.__dict__['event_id']
            else:
                record.event_id = self.event_id
            
            # 创建日志字典
            log_dict = {
                "time_stamp": self.formatTime(record, self.datefmt),
                "mid": record.mid,
                "event_id": record.event_id,
                "level": record.levelname,
                "message": record.msg,
                "msg_type": "json" if isinstance(record.msg, str) and record.msg.startswith('{') else "text"
            }
            # print(f"================={record}")
            
            # 将日志字典转换为 JSON 字符串
            return json.dumps(log_dict, ensure_ascii=False)
    
    
    class ElapsedLog(logging.Logger):
        """
        日志记录
        """
    
        def __init__(self, name=None, verbose=False, file_handler=True, mid="mid_unknown", event_id=None):
            """
                verbose==False, 表示INFO level
                verbose==True, 表示DEBUG level
                file_handler=False, 表示不写入到文件
                file_handler=True, 表示写入到文件
            """
            super().__init__(name)
            super().setLevel(logging.DEBUG if verbose else logging.INFO)
    
            # 设置日志打印格式
            self.formatter = JsonFormatter(mid=mid, event_id=event_id)
    
            if file_handler:
                if not os.path.exists(log_dir):
                    os.makedirs(log_dir)
                file_handler = handlers.TimedRotatingFileHandler(
                    filename=log_path, when=when, backupCount=backupCount, encoding="utf-8")
                file_handler.suffix = "%Y%m%d-%H-%M-%S.log"
                file_handler.extMatch = re.compile(r"^\d{8}-\d{2}-\d{2}-\d{2}.log$")
                file_handler.setFormatter(self.formatter)
                self.addHandler(file_handler)
    
            stream_handler = logging.StreamHandler()
            stream_handler.setFormatter(self.formatter)
            self.addHandler(stream_handler)
    
        def set_mid(self, mid):
            """设置 mid"""
            self.formatter.mid = mid
    
        def set_event_id(self, event_id):
            """设置 event id"""
            self.formatter.event_id = event_id
    

# 创建日志记录器实例
logger = ElapsedLog(file_handler=True)

if __name__ == '__main__':
   # 设置 mid
   logger.set_mid('123456789')
   logger.set_event_id('ElapsedEvent')

   a = {"x": True}

问题

  1. 如何对自定义变量赋值?比如上述record.request_id = xxx, xxx的值如何获取?
    • 方式1: 使用app的request上下文,自动获取request_id并赋值
    • 方式2: 在打印日志的时候,Formatter 手动赋值self.formatter.request_id = "xxxx"
    • 方式3: 在打印日志的时候,手动赋值log.$filter.request_id = "xxxx" ,针对sanic可以在@bp.on_request阶段设置log.filter.request_id
    • 方式4: 打印日志的时候,手动赋值extra, log.info("", extra=extra);extra["request_id"] = "xxx"
posted @ 2022-03-17 22:08  春树&暮云  阅读(666)  评论(0)    收藏  举报