1

I've been trying to add a custom log level by following these two excellent posts:

How to add a custom loglevel to Python's logging facility

Python3 add logging level

In my top level __init__.py I've put:

    import logging

    logging.VERBOSE = 15 
    logging.addLevelName(logging.VERBOSE, "VERBOSE")

    def verbose(self, message, *args, **kws):
        if self.isEnabledFor(logging.VERBOSE):
            # Yes, logger takes its '*args' as 'args'.
            self._log(logging.VERBOSE, message, args, **kws) 

    setattr(logging, 'verbose', verbose)
    setattr(logging.Logger, 'verbose',verbose)
#also tried
# logging.Logger.verbose=verbose
# logging.verbose=verbose

logging.getLogger(__name__).addHandler(logging.NullHandler())

In the various other class and sub-modules, I'm expecting that I can then:

import logging
.
.
.
logging.verbose("Someone sent us up the bomb")

But, all that gets me is:

TypeError: verbose() missing 1 required positional argument: 'message'

If I switch to:

logging.log(logging.VERBOSE, "Intent Returned: " + intent_name)

I don't get an exception thrown, but I don't get any message printed either.

1 Answers1

5

The self is what is stopping this from working since it seems you are not operating from within a class.

If you are using Basic Config you can add a custom level this way in your __init__.py or __main__.py:

import logging
log_level = 15  

logging.basicConfig(
    level=int(log_level),
    format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-7.7s]  %(message)s",
    handlers=[
        logging.FileHandler('put your log path here'),
        logging.StreamHandler()
    ]
)

def verbose(msg, *args, **kwargs):
    if logging.getLogger().isEnabledFor(15):
        logging.log(15, msg)

logging.addLevelName(15, "VERBOSE")
logging.verbose = verbose
logging.Logger.verbose = verbose

# now try the new level
logging.verbose("This is verbose logging")

This also works in other files if you are using the standard logger across them all.

epak96
  • 306
  • 2
  • 7
  • The critical part was to leave off the args and **kwargs in the public call to log(). The absolute minimum code that can be put into the base init file and have it work anywhere in the project is: `import logging logging.getLogger(__name__).addHandler(logging.NullHandler()) logging.VERBOSE = 15 logging.addLevelName(logging.VERBOSE, "VERBOSE") def verbose(message, *args, **kws): if logging.getLogger().isEnabledFor(logging.VERBOSE): # Yes, logger takes its '*args' as 'args'. logging.log(logging.VERBOSE, message) logging.verbose=verbose` – Ernest Christley Mar 07 '19 at 22:41