两种方式来用 Python logging 记录额外的值
前言
有两种方式来用 Python logging 记录额外的值
- 使用
extra
参数 - 向 args 传入字典结构的数据
使用 extra
参数
通过 log
方法的 extra
参数可以来记录而外的值。通过 LogRecord.extra
获取,配合 LogFilter
及 LoggerAdapter
使用。还可以通过配置 Formatter
打印出该值
logging.basicConfig(format="%(ip)s - %(message)s")
logging.info("test message", extra={"ip": "127.0.0.1"})
其输出
127.0.0.1 - test message
使用 Formatter
十分方便,但一旦没有通过 extra
传入对应的键值,则会导致日志写出异常
logger = logging.getLogger()
adapted_logger = logging.LoggerAdapter(logger, extra={"ip": "127.0.0.1"})
adapted_logger.info("test message")
可通过 LoggerAdapter
来给所有 log
方法加上 extra
参数
不过官方的实现很奇怪,直接覆盖掉了原本的 extra
参数。
通过继承它,修改 process
方法即可
def process(self, msg, kwargs):
kwargs["extra"] = {**self.extra, **kwargs.get("extra", {})}
return msg, kwargs
除了以上这个通过传入 extra
参数来添加额外键值的方法,还有什么更方便的方法来记录额外的数据?
向 args 传入字典结构的数据
logging.basicConfig(format="%(message)s")
logging.info("test message from %(ip)r", {"ip": "127.0.0.1"})
logging.info("test message from %(ip)r", {"ip": "127.0.0.2", "delay": 200})
其输出
test message from "127.0.0.1"
test message from "127.0.0.2"
以这样的方式传入日志参数,比起 extra 来有更高的自由度。打日志时,可以随意的在 msg
中使用 args
传入的
args
参数,可以从LogRecord.args
获取 LogRecord.__init__
同样,我们可以实现一个类似 LoggerAdapter
的来提供默认的 args
class ArgsLoggerAdapter(logging.LoggerAdapter):
def process_with_args(self, msg, args, kwargs):
if (args and len(args) == 1 and isinstance(args[0], collections.abc.Mapping)
and args[0]):
args[0] = {**self.extra, **args[0]}
return msg, args, kwargs
def log(self, level, msg, *args, **kwargs):
if self.isEnabledFor(level):
msg, args, kwargs = self.process_with_args(msg, kwargs)
self.logger.log(level, msg, *args, **kwargs)
使用这个向 args
传入字典结构数据的方法,配合用 LogFilter
十分的方便