user2071786
user2071786

Reputation: 121

root logger invokes filehandler from non-root logger - I'm trying to understand why

So I have a logging dictconfig like so

import logging.handlers
from logging.config import dictConfig



LOGGING_DIR = '/homedir/LOGS'

LOGGING_CONFIG = {
    'version': 1,
    'disable_existing_loggers': False,
    'loggers': {
        '': {  # root logger - logs to sys.stdout
            'level': 'NOTSET',
            'handlers': ['rootLoggerStreamHandler'],
        },
        'opslog': {  # logs modules in their own logfile
            'level': 'NOTSET',
            'handlers': ['opsLogFileHandler'],
            'propagate': False
        }
    },
    'handlers': {
        'rootLoggerStreamHandler': {
            'level': 'DEBUG',
            'formatter': 'simpleFormatter',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',  # Default is stderr
        },
        'opsLogFileHandler': {
            'level': 'INFO',
            'formatter': 'simpleFormatter',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': f'{LOGGING_DIR}/opslog.log',
            'mode': 'a',
            'maxBytes': 200000000,
            'backupCount': 2,
            'encoding': None,
            'delay': False
        },
    },
    'formatters': {
        'simpleFormatter': {
            'format': '%(asctime)s: %(filename)s: module:%(funcName)s: %(levelname)s: %(message)s'
        },
    },

}

and I wrote a testscript like so :

import logging
import logging.config
import logger_config # file that contains a dict with logger config.


logging.config.dictConfig(logger_config.LOGGING_CONFIG)
logger = logging.getLogger() # will get the root logger


logger.info("this is a test")

when I run the script, 2 things happen

  1. on stdout, I get a log message. This is as expected
2021-12-19 20:49:06,428: streamhandler_test.py: module:<module>: INFO: this is a test
  1. in /homedir/LOGS an empty file opslog.log is created. This is (for me) unexpected.

the "opslog.log" is clearly created by the opsLogFileHandler So my script invokes the "opsLogFileHandler" somehow.

I guess it has something to do with inheritance, but as I invoke the root logger, I see no reason why the unrelated opsLogFileHandler (which is only bound to the 'opslog' logger) should create an empty file.

Also, if I understand inheritance correctly, there's a child -> parent relation from any non-root logger to the root logger (unless propagation is set to False), but not the other way around.

I"v tried finding an answer reading the docs, but frankly, doc is complex, and I can't work it out.

Any explanation on why that file "opslog.log' is created is very welcome

Upvotes: 0

Views: 81

Answers (1)

Vinay Sajip
Vinay Sajip

Reputation: 99365

The opslog.log file is created when you create the opsLogFileHandler handler, because the delay parameter is set to False in the configuration for it. (If delay is True, the file isn't opened until the first time something needs to be written to it.)

The handler is created when you do the configuration. So as soon as you call dictConfig(), that opslog.log file will be opened for append, and, if it doesn't exist, created as an empty file ready to be written to.

Upvotes: 1

Related Questions