一
LoggingAdapter
是一个单独的对象,它不替换
logging.getLogger()
电话。您需要将它存储在可以在不同模块之间共享的地方。例如,您可以使用一个单独的模块,将项目中的其他内容从中导入。
下面我将详细介绍如何处理这个问题,但是还有一个替代方案,它完全不涉及适配器,而是使用附加到您创建的处理程序的筛选器,这样您就可以避免完全处理适配器。再往下看。
我还将配置和日志对象处理分开;让主模块调用“set up”函数来配置处理程序和日志级别,并在模块中设置适配器以供其他人导入:
log.py
:
import logging
import socket
def setup_logging():
"""Adds a configured stream handler to the root logger"""
syslog = logging.StreamHandler()
formatter = logging.Formatter(
'{"label":"%(name)s", "level":"%(levelname)s",'
' "hostname":"%(hostname)s", "logEntry": %(message)s,'
' "timestamp", "%(asctime)s"}')
syslog.setFormatter(formatter)
logger = logging.getLogger()
logger.addHandler(syslog)
logger.setLevel(logging.DEBUG)
def host_log_adapter(logger):
hostname = {"hostname": socket.gethostname()}
return logging.LoggerAdapter(logger, hostname)
logger = host_log_adapter(logging.getLogger())
然后在
main
做:
import log
import test
log.setup_logging()
def entry_point():
log.logger.debug("entry_point")
test.test_function()
entry_point()
而在
test
:
from log import logger
def test_function():
logger.debug("test_function")
或者,不要使用
适配器
,可以通过(ab)使用筛选器将信息添加到日志记录中:
class HostnameInjectingFilter(logging.Filter):
def __init__(self):
self.hostname = socket.gethostname()}
def filter(self, record):
record.hostname = self.hostname
return True
这将直接在record对象上添加额外的字段,并
总是
收益率
True
. 然后将此筛选器添加到需要有可用主机名的处理程序中:
syslog = logging.StreamHandler()
formatter = logging.Formatter(
'{"label":"%(name)s", "level":"%(levelname)s",'
' "hostname":"%(hostname)s", "logEntry": %(message)s,'
' "timestamp", "%(asctime)s"}')
syslog.setFormatter(formatter)
syslog.setFilter(HostnameInjectingFilter())
这消除了完全使用适配器的需要,因此您可以删除
host_log_adapter()
功能齐全,使用方便
日志记录.getLogger()
到处都是。