是否可以使用FileHandler多个记录器(即logging.getLogger("base.foo")和logging.getLogger("base.bar"))登录到单个目标(即使用一个),并为每个记录器使用不同的格式化程序.
根据我的理解,只能为每个句柄分配一个格式化程序.也许可以将格式化程序与记录器而不是处理程序相关联?
Den*_*ach 17
很容易派遣到基于的不同格式化程序record.name.以下是概念验证示例代码:
import logging
class DispatchingFormatter:
def __init__(self, formatters, default_formatter):
self._formatters = formatters
self._default_formatter = default_formatter
def format(self, record):
formatter = self._formatters.get(record.name, self._default_formatter)
return formatter.format(record)
handler = logging.StreamHandler()
handler.setFormatter(DispatchingFormatter({
'base.foo': logging.Formatter('FOO: %(message)s'),
'base.bar': logging.Formatter('BAR: %(message)s'),
},
logging.Formatter('%(message)s'),
))
logging.getLogger().addHandler(handler)
logging.getLogger('base.foo').error('Log from foo')
logging.getLogger('base.bar').error('Log from bar')
logging.getLogger('base.baz').error('Log from baz')
Run Code Online (Sandbox Code Playgroud)
另一种方法是手动打开文件并使用不同的格式化程序从中创建两个流处理程序.
对优秀的丹尼斯解决方案的修复很少。
基于层次结构的日志命名系统:
可能
name是一个以句点分隔的层次结构值,例如foo.bar.baz(尽管它也可能只是普通的foo)。层次结构列表中靠下的记录器是列表中靠上的记录器的子项。例如,给定一个名称为 的记录器foo,名称为foo.bar、foo.bar.baz和 的记录器foo.bam都是 的后代foo。
例如,当您为某些记录器设置Level()时,该级别也将应用于子记录器。这就是为什么您可能希望格式化程序用于记录器并且它也是子记录器。例如,'one.two'格式化程序也应该应用于'one.two.three'记录器(如果没有'one.two.three'设置格式化程序)。以下是完成这项工作的 DispatchingFormatter 版本(Python 3 代码):
class DispatchingFormatter:
"""Dispatch formatter for logger and it's sub logger."""
def __init__(self, formatters, default_formatter):
self._formatters = formatters
self._default_formatter = default_formatter
def format(self, record):
# Search from record's logger up to it's parents:
logger = logging.getLogger(record.name)
while logger:
# Check if suitable formatter for current logger exists:
if logger.name in self._formatters:
formatter = self._formatters[logger.name]
break
else:
logger = logger.parent
else:
# If no formatter found, just use default:
formatter = self._default_formatter
return formatter.format(record)
Run Code Online (Sandbox Code Playgroud)
例子:
handler = logging.StreamHandler()
handler.setFormatter(DispatchingFormatter({
'one': logging.Formatter('%(message)s -> one'),
'one.two': logging.Formatter('%(message)s -> one.two'),
},
logging.Formatter('%(message)s -> <default>'),
))
logging.getLogger().addHandler(handler)
print('Logger used -> formatter used:')
logging.getLogger('one').error('one')
logging.getLogger('one.two').error('one.two')
logging.getLogger('one.two.three').error('one.two.three') # parent formatter 'one.two' will be used here
logging.getLogger('other').error('other')
# OUTPUT:
# Logger used -> formatter used:
# one -> one
# one.two -> one.two
# one.two.three -> one.two
# other -> <default>
Run Code Online (Sandbox Code Playgroud)