I want to log messages of a specific logger name, of a certain level and higher (say INFO
and up) to a specific log handler, say a file handler, while still getting all log messages to the console. Python is version 2.7.
What I tried until now was to create two loggers:
For the root logger, I attached a logging.StreamHandler
, and set the log level to logging.DEBUG
.
Then I attached a handler to the named logger and set level to logging.INFO
for that logger.
When I now call my module, which uses the named logger, I do not get DEBUG
logs propagated to the root logger any more.
Note: the extraLogger has a StreamHandler here to demonstrate the issue. In my production code I'd use a FileHandler
import logging
def do_logging(turn):
logger = logging.getLogger('extra')
logger.info('some info turn %d' % turn)
logger.debug('this is debug fudge turn %d' % turn)
rootLogger = logging.getLogger()
handler = logging.StreamHandler()
rootFormatter = logging.Formatter('root - %(levelname)s: %(msg)s')
handler.setFormatter(rootFormatter)
rootLogger.addHandler(handler)
rootLogger.setLevel(logging.DEBUG)
do_logging(1)
extraLogger = logging.getLogger('extra')
extraHandler = logging.StreamHandler()
extraFormatter = logging.Formatter('extra - %(levelname)s: %(msg)s')
extraHandler.setFormatter(extraFormatter)
extraLogger.addHandler(extraHandler)
extraLogger.setLevel(logging.INFO)
do_logging(2)
Actual Output:
root - INFO: some info turn 1
root - DEBUG: this is debug fudge turn 1
extra - INFO: some info turn 2
root - INFO: some info turn 2
Output that I would like to have:
root - INFO: some info turn 1
root - DEBUG: this is debug fudge turn 1
extra - INFO: some info turn 2
root - INFO: some info turn 2
root - DEBUG: this is debug fudge turn 2
I suspect that a custom Filter
would be helpful in this case, but I do not know how...
Propagate: Decides whether a log should be propagated to the logger's parent. By default, its value is True. A level: Like the log handler level, the logger level is used to filter out “less important” logs.
getLogger('dev') name = "stackoverflow" logger.info(f"Hello {name}!") logger. critical('This message should go to the log file. ') logger. error('So should this.
You could use robert's LevelFilter like this:
# Put the Filter on the Handler so only INFO and higher is handled
extraHandler.addFilter(LevelFilter(logging.INFO))
# Let the Logger process everything (so it can propagate records to root)
extraLogger.setLevel(logging.DEBUG)
import logging
class LevelFilter(logging.Filter):
"""
https://stackoverflow.com/a/7447596/190597 (robert)
"""
def __init__(self, level):
self.level = level
def filter(self, record):
return record.levelno >= self.level
def do_logging(turn):
logger = logging.getLogger('extra')
logger.info('some info turn %d' % turn)
logger.debug('this is debug fudge turn %d' % turn)
rootLogger = logging.getLogger()
handler = logging.StreamHandler()
rootFormatter = logging.Formatter('root - %(levelname)s: %(msg)s')
handler.setFormatter(rootFormatter)
rootLogger.addHandler(handler)
rootLogger.setLevel(logging.DEBUG)
do_logging(1)
extraLogger = logging.getLogger('extra')
extraHandler = logging.StreamHandler()
extraFormatter = logging.Formatter('extra - %(levelname)s: %(msg)s')
extraHandler.setFormatter(extraFormatter)
extraLogger.addHandler(extraHandler)
# Put the Filter on the Handler so only INFO and higher is handled
extraHandler.addFilter(LevelFilter(logging.INFO))
# Handle everything (so it can propagate to root)
extraLogger.setLevel(logging.DEBUG)
do_logging(2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With