Reputation: 544
I'm trying to set up three different loggers using dictConfig and for some reason the last logger always seems to overwrite the configuration of the two loggers created before it. Here is the code I'm using:
import logging
import logging.config
def setup_logger(name, level, ContentFormat='%(asctime)s %(levelname)s %(message)s', DateTimeFormat='%Y-%m-%d %H:%M:%S'):
logging.config.dictConfig({
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'default': {'format': ContentFormat, 'datefmt': DateTimeFormat},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': level,
'formatter': 'default',
'stream': 'ext://sys.stdout'
}
},
'loggers': {
'a': {
'level': level,
'handlers': ['console']
},
'b': {
'level': level,
'handlers': ['console']
},
'c': {
'level': level,
'handlers': ['console']
}
}
})
return logging.getLogger(name)
logger_a = setup_logger(name='a', level=logging.INFO, ContentFormat='A: %(message)s')
logger_b = setup_logger(name='b', level=logging.INFO, ContentFormat='B: %(message)s')
logger_c = setup_logger(name='c', level=logging.INFO, ContentFormat='C: %(message)s')
logger_a.info('logger_a')
logger_b.info('logger_b')
logger_b.info('logger_c')
And this is the output:
C: logger_a
C: logger_b
C: logger_c
Instead what I'd like to see is:
A: logger_a
B: logger_b
C: logger_c
Any ideas what I'm doing wrong? I've even tried making multiple handlers and I still run into the same problem.
I have another version of this function that uses the following code and I'm able to call it multiple times to create multiple separate loggers with different settings, but I really wanted to figure out how to do this with dictConfig instead, or at least understand where I'm going wrong:
logger = logging.getLogger(name)
logger.setLevel(level)
# create console handler for printing logging output to the screen as well
formatter = logging.Formatter(ContentFormat, DateTimeFormat)
handler = logging.StreamHandler()
handler.setLevel(level)
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
Upvotes: 3
Views: 4539
Reputation: 2887
It happens because you created and overrode the global configuration 3 times. You used default
formatter to configure specific logger and the last one C
used to log you records.
You can easily check it with this code:
def setup_logger(name, level, DateTimeFormat='%Y-%m-%d %H:%M:%S'):
cfg = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'default_for_a': {'format': 'A: %(message)s', 'datefmt': DateTimeFormat},
'default_for_b': {'format': 'B: %(message)s', 'datefmt': DateTimeFormat},
'default_for_c': {'format': 'C: %(message)s', 'datefmt': DateTimeFormat}
},
'handlers': {
'console_for_a': {
'class': 'logging.StreamHandler',
'level': level,
'formatter': 'default_for_a',
'stream': 'ext://sys.stdout'
},
'console_for_b': {
'class': 'logging.StreamHandler',
'level': level,
'formatter': 'default_for_b',
'stream': 'ext://sys.stdout'
},
'console_for_c': {
'class': 'logging.StreamHandler',
'level': level,
'formatter': 'default_for_c',
'stream': 'ext://sys.stdout'
},
},
'loggers': {
'a': {
'level': level,
'handlers': ['console_for_a']
},
'b': {
'level': level,
'handlers': ['console_for_b']
},
'c': {
'level': level,
'handlers': ['console_for_c']
}
}
}
logging.config.dictConfig(cfg)
return logging.getLogger(name)
logger_a = setup_logger(name='a', level=logging.INFO)
logger_b = setup_logger(name='b', level=logging.INFO)
logger_c = setup_logger(name='c', level=logging.INFO)
logger_a.info('logger_a')
logger_b.info('logger_b')
logger_c.info('logger_c')
Or make it more generic with the code
import logging
import logging.config
def setup_logger(name, level, ContentFormat='%(asctime)s %(levelname)s %(message)s', DateTimeFormat='%Y-%m-%d %H:%M:%S'):
cfg = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
f'default_for_{name}': {'format': ContentFormat, 'datefmt': DateTimeFormat}
},
'handlers': {
f'console_for_{name}': {
'class': 'logging.StreamHandler',
'level': level,
'formatter': f'default_for_{name}',
'stream': 'ext://sys.stdout'
},
},
'loggers': {
name: {
'level': level,
'handlers': [f'console_for_{name}']
}
}
}
logging.config.dictConfig(cfg)
return logging.getLogger(name)
logger_a = setup_logger(name='a', level=logging.INFO, ContentFormat='A: %(message)s')
logger_b = setup_logger(name='b', level=logging.INFO, ContentFormat='B: %(message)s')
logger_c = setup_logger(name='c', level=logging.INFO, ContentFormat='C: %(message)s')
logger_a.info('logger_a')
logger_b.info('logger_b')
logger_c.info('logger_c')
The output is:
A: logger_a
B: logger_b
C: logger_c
Upvotes: 6