我目前正在从事一个使用单根记录器的项目。我从阅读有关日志记录的文章中了解到这是一件坏事,但我正在努力寻找一个好的解决方案来为我们带来好处。
我们做的事情(部分是为了避免没有不同的记录器,但部分是为了给我们一个很好的特性)是有一个 log_prefix 装饰器。
例如
@log_prefix("Download")
def download_file():
logging.info("Downloading file..")
connection = get_connection("127.0.0.1")
//Do other stuff
return file
@log_prefix("GetConnection")
def get_connection(url):
logging.info("Making connection")
//Do other stuff
logging.info("Finished making connection")
return connection
这为我们提供了一些格式良好的日志,可能如下所示:
Download:Downloading file..
Download:GetConnection:Making Connection
Download:GetConnection:Other stuff
Download:GetConnection:Finished making connection
Download:Other stuff
这也意味着如果我们有
@log_prefix("StartTelnetSession")
logging.info("Starting telnet session..")
connection = get_connection("127.0.0.1")
我们在最后得到相同的前缀:
StartTelnetSession:Starting telnet session..
StartTelnetSession:GetConnection:Making Connection
StartTelnetSession:GetConnection:Other stuff
StartTelnetSession:GetConnection:Finished making connection
事实证明,这对开发和支持非常有用。
我可以看到很多情况,实际上只需为操作使用一个单独的记录器就可以解决我们的问题,但我也可以看到丢弃我们现有的嵌套会使事情变得更糟的情况。
嵌套记录器是否有任何模式或常见用途?即
logging.getLogger("Download").getLogger("MakingConnection")
还是我在这里遗漏了什么?
请您参考如下方法:
你可以使用 LoggerAdapter添加额外的上下文信息:
utils_logging.py:
import functools
def log_prefix(logger, label, prefix=list()):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
prefix.append(label)
logger.extra['prefix'] = ':'.join(prefix)
result = func(*args, **kwargs)
prefix.pop()
logger.extra['prefix'] = ':'.join(prefix)
return result
return wrapper
return decorator
foo.py:
import logging
import utils_logging as UL
import bar
logger = logging.LoggerAdapter(logging.getLogger(__name__), {'prefix':''})
@UL.log_prefix(logger, "Download")
def download_file():
logger.info("Downloading file..")
connection = bar.get_connection("127.0.0.1")
if __name__ == '__main__':
logging.basicConfig(
level=logging.INFO,
format='%(prefix)s %(name)s %(levelname)s %(message)s')
download_file()
bar.get_connection('foo')
bar.py:
import logging
import utils_logging as UL
logger = logging.LoggerAdapter(logging.getLogger(__name__), {'prefix':''})
@UL.log_prefix(logger, "GetConnection")
def get_connection(url):
logger.info("Making connection")
logger.info("Finished making connection")
产量
Download __main__ INFO Downloading file..
Download:GetConnection bar INFO Making connection
Download:GetConnection bar INFO Finished making connection
GetConnection bar INFO Making connection
GetConnection bar INFO Finished making connection
注意:我不认为为每个对象创建一个新的 Logger 实例是个好主意 前缀因为these instances are not garbage collected .全部 你需要的是一些 prefix 变量取不同的值取决于 语境。你不需要一个新的 Logger 实例——一个 LoggerAdapter 会 做。
