我想使用以下日志格式化程序:
'format': '{"message": "%(message)s", "user": "%(user)s"}'
但是,我想用两种不同的方式来称呼它:
log.info('hi', extra={"user": str(request.user)})
log.info("hi")
第一个日志语句有效,因为它具有user
kwarg,但第二个语句失败,并带有KeyError
。有什么方法可以使格式参数为可选?
答案 0 :(得分:2)
None
给定固定的日志记录格式字符串,可以使用自定义Formatter
类用None
替换缺少的参数。
import logging
import re
class CustomFormatter(logging.Formatter):
def format(self, record: logging.LogRecord) -> str:
arg_pattern = re.compile(r'%\((\w+)\)')
arg_names = [x.group(1) for x in arg_pattern.finditer(self._fmt)]
for field in arg_names:
if field not in record.__dict__:
record.__dict__[field] = None
return super().format(record)
logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
formatter = CustomFormatter('{"message": "%(message)s", "user": "%(user)s"}')
handler.setFormatter(formatter)
logger.setLevel(logging.INFO)
logger.addHandler(handler)
logger.info('hi')
logger.info('hi', extra={"user": "asmith"})
输出
{"message": "hi", "user": "None"}
{"message": "hi", "user": "asmith"}
自定义Formatter
可以根据传递给extra
的字典来动态更新格式字符串。
import logging
class ExtraFormatter(logging.Formatter):
def format(self, record: logging.LogRecord) -> str:
default_attrs = logging.LogRecord(None, None, None, None, None, None, None).__dict__.keys()
extras = set(record.__dict__.keys()) - default_attrs
log_items = ['"message": "%(message)s"']
for attr in extras:
log_items.append(f'"{attr}": "%({attr})s"')
format_str = f'{{{", ".join(log_items)}}}'
self._style._fmt = format_str
return super().format(record)
logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
formatter = ExtraFormatter()
handler.setFormatter(formatter)
logger.setLevel(logging.INFO)
logger.addHandler(handler)
logger.info('hi')
logger.info('hi', extra={"user": "asmith", "number": "42"})
输出
{"message": "hi"}
{"message": "hi", "user": "asmith", "number": "42"}