Небольшое исправление к отличному решению Дениса.
Система имен журналирования на основе иерархической структуры:
name
потенциально представляет собой иерархическое значение, разделенное точками, например
foo.bar.baz
(хотя это также может быть просто foo
, например).
Регистраторы, которые находятся ниже в иерархическом списке, являются потомками
регистраторы выше в списке. Например, дан логгер с именем
foo
, регистраторы с именами foo.bar
, foo.bar.baz
и foo.bam
все потомки foo
.
Например, когда вы setLevel () для какого-либо регистратора, этот уровень также будет применяться к дочерним регистраторам. Вот почему вы можете захотеть, чтобы ваш форматтер использовался для логгеров, а также для дочерних логгеров. Например, '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)
Пример:
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>