Poco arreglo a la excelente solución de Denis.
Logging name system basado en estructura jerárquica:
El name
es potencialmente un valor jerárquico período separados, como foo.bar.baz
(aunque también podría ser simplemente foo
, por ejemplo). Los registradores que están más abajo en la lista jerárquica son hijos de registradores más arriba en la lista. Por ejemplo, dado un registrador con un nombre de foo
, los registradores con nombres de foo.bar
, foo.bar.baz
y foo.bam
son todos descendientes de foo
.
Por ejemplo, cuando setLevel() para algún registrador, este nivel también se aplicará a los registradores de niños. Es por eso que es posible que desee que su formateador se utilice para el registrador y también para los registradores hijos. Por ejemplo, el formateador 'one.two'
también se debe aplicar al registrador 'one.two.three'
(si no se configuró ningún formateador para 'one.two.three'
). Aquí está la versión de DispatchingFormatter que hacer el trabajo (código 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)
Ejemplo:
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>
excelente solución, elegante. Para el registro esto también funciona basado en record.levelno, de modo que la clave del diccionario de formateadores podría ser 'logging.DEBUG' en lugar de' 'base.foo'' – lorenzog