简体   繁体   中英

universal logger name in python logging yaml config file

Ok, so the situation is I need to use a yaml config file for logging.(don't ask - I just need it :) ). And when writing the 'loggers:' directive I would like to use one logger and to be able to fetch it from multiple modules in my app using getLogger(__name__) . I know how to do it if I use a normal python config file for logging, but I can't to find a way to do the same with a yaml file. using python 2.7 So long story short, that's what I have(this is just a simplified example of my problem, not part of the actual application :) ):

#this is app.py
import logging.config
import yaml
import os

def init_logging():
    path = 'logging.yaml'
    if os.path.exists(path):
        with open(path, 'r') as f:
            config = yaml.safe_load(f.read())
        logging.config.dictConfig(config['logging'])
    main()


def main():
    logger = logging.getLogger('app')
    logger.debug("done!")


init_logging()

and here's the logging.yaml config file:

logging:
    version: 1
    formatters:
        brief:
            format: '%(message)s'
        default:
            format: '%(asctime)s %(levelname)-8s [%(name)s] %(message)s'
            datefmt: '%Y-%m-%d %H:%M:%S'

    handlers:
        console:
            class: logging.StreamHandler
            level: DEBUG

    loggers:
        app:
            handlers: [console]
            level: DEBUG

So as is it is here - it works. the 'done!' message shows in the console. But I want to be able to set in the config not some distinct logger (here I called it 'app') but a universal, like if it was in a .py config it'would be

"loggers": {
    "": {
        "handlers": ["console"],
        "level": "DEBUG",
    },
}

and then I would be using logging.getLogger(__name__) in different modules and it would always use the one "" logger and show me the messages. So is there a way to create a universal logger in yaml? like the "": in the python logging config? I tried (), ~, null - those don't do the work. Basically I need to be able to call loggers with any names I want and to get one specified logger. And yep - I can create a root directive in the yaml and call it by using logging.getLogger()

The trick is to use a special logger called root , outside the list of other loggers.

I found this in the Python documentation :

root - this will be the configuration for the root logger. Processing of the configuration will be as for any logger, except that the propagate setting will not be applicable.

Here's the configuration from your question changed to use the root key:

logging:
    version: 1
    formatters:
        brief:
            format: '%(message)s'
        default:
            format: '%(asctime)s %(levelname)-8s [%(name)s] %(message)s'
            datefmt: '%Y-%m-%d %H:%M:%S'

    handlers:
        console:
            class: logging.StreamHandler
            level: DEBUG

    root:
        handlers: [console]
        level: WARN
    loggers:
        app:
            level: DEBUG

That configures app at the DEBUG level, and everything else at the WARN level.

Okay, so I found an answer (thanks to @flyx!). I compared the original python dict config and the converted from yaml dict config and found out that logging automatically adds disable_existing_loggers: False to the python config. After that I added this line to the yaml and used '' in the loggers directive.. and it worked! So the resulting yaml config is like:

..............
disable_existing_loggers: False

loggers:
    '':
        handlers: [console, sentry]
        level: DEBUG
        propagate: False

and now it works. Even if I create a logger like logging.getLogger('something') and logger 'something' is not in the config then the app will use the '' logger.

@Don Kirkby's answer won't work if the logger is defined in the begining of the file(before configurating it). But it works with no problem if the logger is defined after configuring logging. So it's a resolve for the code from my question but not an answer to the question - "So is there a way to create a universal logger in yaml? like the "": in the python logging config?" That's why I didn't pick it as an answer. But he's comment is totally legit :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM