Search code examples
pythonloggingerror-logging

Using logging basicConfig with multiple handlers


I'm trying to understand the behaviour of the logging module when using basicConfig with multiple handlers.

My aim is to have warning level on syslog messages, and debug level to a log file.

This is my setup:

import logging
import logging.handlers
import os
from datetime import datetime
 
log_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
f_handler = logging.FileHandler(f'{os.path.expanduser("~")}/logs/test_{datetime.now().strftime("%Y%m%d%H%M%S")}.log')
s_handler = logging.handlers.SysLogHandler(address='/dev/log')


f_handler.setLevel(logging.DEBUG)
s_handler.setLevel(logging.WARN)
f_handler.setFormatter(log_format)
s_handler.setFormatter(log_format)

logging.basicConfig(handlers=[f_handler, s_handler])

print (logging.getLogger().getEffectiveLevel())


logging.warning('This is a warning')
logging.error('This is an error')
logging.info('This is an info')
logging.debug('This is debug')

This does not work - my log file only contains the warning and error messages, not the debug and info messages as intended.

If I change this line to:

logging.basicConfig(handlers=[f_handler, s_handler], level=logging.DEBUG)

Then this does seem to work, i.e. the file contains all messages and syslog contains only the error and warning message.

I don't understand why the original code did not work, given that I set the level on the file handler specifically.


Solution

  • It's because you need to set a level on the logger, as that's checked first, and if there is further processing to be done, then the event is passed to handlers, where it's checked against their levels.

    • Level on logger - overall verbosity of application
    • Level on handler - verbosity for the destination represented by that handler

    See the diagram below for more information.

    enter image description here