Question

In python 2.6 (and maybe later versions but I'm only looking at 2.6 now), it seems that the logging module's _levelnames mapping is a top-level object not part of any class:

_levelNames = {
    CRITICAL : 'CRITICAL',
    ERROR : 'ERROR',
    WARNING : 'WARNING',
    INFO : 'INFO',
    DEBUG : 'DEBUG',
    NOTSET : 'NOTSET',
    'CRITICAL' : CRITICAL,
    'ERROR' : ERROR,
    'WARN' : WARNING,
    'WARNING' : WARNING,
    'INFO' : INFO,
    'DEBUG' : DEBUG,
    'NOTSET' : NOTSET,
}

The module provides a way to override these names:

def addLevelName(level, levelName):
    """
    Associate 'levelName' with 'level'.

    This is used when converting levels to text during message formatting.
    """
    _acquireLock()
    try:    #unlikely to cause an exception, but you never know...
        _levelNames[level] = levelName
        _levelNames[levelName] = level
    finally:
        _releaseLock()

But this is on a global basis.

I have a requirement to log to syslog so that ERROR log messages are tagged "MAJOR" and WARNING log messages are tagged "MINOR".

Now it's easy enough to use the addLevelName() method to change the name, but again, this is on a global basis. I'd like my syslog handler to use the MAJOR and MINOR but leave ERROR and WARNING for program logs. I don't absolutely have to do this and could live with the global renames, but I'd rather not. I've been all over the source code and can't find a hook that would let me do this.

Am I missing something?

Was it helpful?

Solution

You can use a custom Formatter on the appropriate handler which changes the levelname attribute of the LogRecord to whatever you want. This won't make any global changes to level names:

class MyFormatter(logging.Formatter):
    def format(self, record):
        if record.levelname == 'ERROR':
            record.levelname = 'MAJOR'
        elif record.levelname == 'WARNING':
            record.levelname = 'MINOR'
        result = super(MyFormatter, self).format(record)
        if record.levelname == 'MAJOR':
            record.levelname = 'ERROR'
        elif record.levelname == 'MINOR':
            record.levelname = 'WARNING'
        return result

OTHER TIPS

Vinay Sajip's answer is basically the right idea but there is a syntax error, at least under python 2.6.

Here's my revision of his answer:

from logging import Formatter
class MyFormatter(Formatter):
    def format(self, record):
        orig_levelname = record.levelname
        if record.levelname == 'ERROR':
            record.levelname = 'MAJOR'
        elif record.levelname == 'WARNING':
            record.levelname = 'MINOR'
        result = Formatter.format(self, record)
        record.levelname = orig_levelname
        return result
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top