Python 在日志格式化程序中提取日志调用中的额外字段

Python 在日志格式化程序中提取日志调用中的额外字段,python,python-3.x,logging,Python,Python 3.x,Logging,因此,我可以像这样向日志消息中添加其他字段 logging.info(“我的日志消息”,extra={“someContext”:1,“someOtherContext”:2}) 这很好 但不清楚如何提取日志格式化程序中的所有额外字段 def格式(自我,记录): record\u dict=记录 打印(记录) 在上面,我可以在输出dict中看到我所有的额外字段,但它们被压缩成一个dict,其中包含我不想要的其他垃圾 {'name': 'root', 'msg': 'My log Messag

因此,我可以像这样向日志消息中添加其他字段

logging.info(“我的日志消息”,extra={“someContext”:1,“someOtherContext”:2})
这很好

但不清楚如何提取日志格式化程序中的所有额外字段

def格式(自我,记录):
record\u dict=记录
打印(记录)
在上面,我可以在输出dict中看到我所有的额外字段,但它们被压缩成一个dict,其中包含我不想要的其他垃圾

{'name': 'root', 'msg': 'My log Message', 'args': (), 'levelname': 'INFO', 'levelno': 20, 'pathname': '.\\handler.py', 'filename': 'handler.py', 'module': 'handler', 'exc_info': None, 'exc_text': None, 'stack_info': None, 'lineno': 27, 'funcName': 'getPlan', 'created': 1575461352.0664868, 'msecs': 66.48683547973633, 'relativeCreated': 1253.0038356781006, 'thread': 15096, 'threadName': 'MainThread', 'processName': 'MainProcess', 'process': 23740, 'someContext': 1, 'someOtherContext':2}
有没有办法不用事先知道就可以拿到我所有的备用钥匙

我正在编写一个json格式化程序,并希望创建一个dict a la

justMyExtra = ?????
to_log = {
"message" record_dict["message"], 
**justMyExtra
}

我想到了两种方法:

  • 将所有额外字段转储到主词典中的词典中。调用键“additionalContext”并获取所有额外的条目
  • 创建原始字典的副本并删除所有已知的键:“name”、“msg”、“args”等,直到只有justYourExtra

  • 如果您阅读该方法的源代码,该方法返回一个带有给定日志信息的
    LogRecord
    对象,您会发现它将
    extra
    dict与returing
    LogRecord
    对象的
    \uu dict\uu
    属性合并,因此,您无法在格式化程序中检索原始的
    extra
    dict

    相反,您可以使用包装函数修补
    logging.Logger.makeRecord
    方法,该包装函数将给定的
    extra
    dict存储为返回的
    LogRecord
    对象的
    \u extra
    属性:

    def make_record_with_extra(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None):
        record = original_makeRecord(self, name, level, fn, lno, msg, args, exc_info, func, extra, sinfo)
        record._extra = extra
        return record
    
    original_makeRecord = logging.Logger.makeRecord
    logging.Logger.makeRecord = make_record_with_extra
    
    以便:

    class myFormatter(logging.Formatter):
        def format(self, record):
            print('Got extra:', record._extra) # or do whatever you want with _extra
            return super().format(record)
    
    logger = logging.getLogger(__name__)
    handler = logging.StreamHandler()
    handler.setFormatter(myFormatter('%(name)s - %(levelname)s - %(message)s - %(foo)s'))
    logger.addHandler(handler)
    logger.warning('test', extra={'foo': 'bar'})
    
    产出:

    Got extra: {'foo': 'bar'}
    __main__ - WARNING - test - bar
    
    演示: