How to Add a Custom Loglevel to Python's Logging Facility

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

To people reading in 2022 and beyond: you should probably check out the currently next-highest-rated answer here: https://stackoverflow.com/a/35804945/1691778

My original answer is below.

--

@Eric S.

Eric S.'s answer is excellent, but I learned by experimentation that this will always cause messages logged at the new debug level to be printed -- regardless of what the log level is set to. So if you make a new level number of 9, if you call setLevel(50), the lower level messages will erroneously be printed.

To prevent that from happening, you need another line inside the "debugv" function to check if the logging level in question is actually enabled.

Fixed example that checks if the logging level is enabled:

import logging
DEBUG_LEVELV_NUM = 9
logging.addLevelName(DEBUG_LEVELV_NUM, "DEBUGV")
def debugv(self, message, *args, **kws):
if self.isEnabledFor(DEBUG_LEVELV_NUM):
# Yes, logger takes its '*args' as 'args'.
self._log(DEBUG_LEVELV_NUM, message, args, **kws)
logging.Logger.debugv = debugv

If you look at the code for class Logger in logging.__init__.py for Python 2.7, this is what all the standard log functions do (.critical, .debug, etc.).

I apparently can't post replies to others' answers for lack of reputation... hopefully Eric will update his post if he sees this. =)

Add custom log level for pytest tests to python the logging module

In this code there is a misunderstanding between a logger instance and the logger module.

To be able to call the test_log method in the original code you need to obtain a logger instance eg:

# After the existing code

logger = logging.getLogger()
logger.test_info("Some log data.")

As you have added the test_info method to the loggerClass it will be available to the logger instance.

To have the method available on the logging module the function needs to be created for that purpose and added to the module:

# After the existing code

def module_test_info(message, *args, **kwargs):
logging.log(level_number, message, *args, **kwargs)

setattr(logging, level_name.lower(), module_test_info)

This will add the module_test_info function to the logging module with the name test_info you will be able to call it as such logging.test_level("Some log data.")

Adding log level with Python 3.7

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.

Python logger not respecting setLevel?

Apparently, logging.NOTSET does not mean "All levels", but rather defaults. So setting the parent logger to level 0 does only reverts it to it's default accepted levels. That being said, if I set logger.setLevel to logging.DEBUG that essentially sets logging to accept ALL levels then passes filtering on to the various handlers to filter further.

To get around this (and potential custom log levels) I've set the initial logger level to 1



Related Topics



Leave a reply



Submit