Search code examples
pythonloggingdecorator

addLevelName in python logging before a logging decorator doesn't see custom levels


So, in main.py I have set up different logging levels:

logging.METRICS = logging.INFO+1
logging.TIME = logging.METRICS+1
logging.DATAPROCESSING = logging.TIME+1
...and so on
logging.addLevelName(logging.METRICS, 'METRICS')
logging.addLevelName(logging.TIME, 'TIME')

The decorator elsewhere in the code actually sees it (and prints it out as such level) when it is called explicitly like this:

@decorator(logger_level=25)
def func(args):

but when I call it like this it doesn't recognize it as such level and prints out that logging has no such attribute:

@decorator(logger_level=logging.METRICS)
def func(args):

My question is, why is this so? Is logging in decorator loading faster than the new attributes setup? How do I overcome this, I would really need new custom logging levels.

The decorator looks like this:

    def decorator(logger_level=logging.INFO):
        def timedecorator(method):
            @functools.wraps(method)
            def timed(self, *args, **kw):
                ts = time.time()
                result = method(self, *args, **kw)
                te = time.time()
                logging.getLogger('time').log(logger_level, 'time: %r  %2.2f ms', method.__name__, (te - ts) * 1000)
            return result
        return timed
    return timeitdecorator

Solution

  • addLevelName doesn't add the level as variable on the module level. It does put it into the level name dictionary. You should call your decorator like this: @decorator(logger_level="METRICS"). Also works for the built-in levels.

    You also need to change the decorator a little bit:

    level = logging._checkLevel(logger_level) // translate level string to int
    logging.getLogger('time').log(level, /*other args*/)