python-3.x 在日志格式化程序中提取日志调用中的额外字段

s5a0g9ez  于 2022-12-01  发布在  Python
关注(0)|答案(3)|浏览(127)

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

logging.info("My log Message", extra={"someContext":1, "someOtherContext":2})

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

def format(self, record):
  record_dict = record.__dict__.copy()
  print(record_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
}
mv1qrgav

mv1qrgav1#

我想到了两种方法:
1.将所有额外的字段转储到主字典中的一个字典中。调用键“additionalContext”并获取所有额外的条目。
1.创建原始字典的副本并删除所有已知键:“name”、“msg”、“args”等,直到您只剩下YourExtra

tvokkenx

tvokkenx2#

如果您阅读logging.Logger.makeRecord方法的源代码(该方法返回一个带有给定日志信息的LogRecord对象),您会发现它将extra dict与返回的LogRecord对象的__dict__属性合并在一起,因此您无法在格式化程序中检索原始的extra dict。
相反,您可以使用 Package 函数来修补logging.Logger.makeRecord方法,该函数将给定的extra dict存储为返回的LogRecord对象的_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

演示:https://repl.it/@blhsing/WorthyTotalLivedistro

xu3bshqb

xu3bshqb3#

这两种方法与@james-hendricks的方法类似,但不那么脆弱:
1.使用LogRecord上现有的args字典,而不是使用您自己的字典。
1.创建一个虚拟LogRecord并检查其键,以获取LogRecord特殊键的非脆弱字符串列表:

dummy = logging.LogRecord('dummy', 0, 'dummy', 0, None, None, None, None, None)
  reserved_keys = dummy.__dict__.keys()

相关问题