sds
sds

Reputation: 60054

Temporarily change logging level - safely

According to Dynamically changing log level without restarting the application I can temporarily change logging level:

logger_level = my_logger.level
my_logger.setLevel(logging.DEBUG)
a = do_something_with_higher_logging1()
b,c = do_something_with_higher_logging2()
d = do_something_with_higher_logging3()
my_logger.setLevel(logger_level)

The problem is that if do_something_with_higher_logging[123] raise an exception (which is caught outside this, so my program is not terminated), the level of my_logger is not reset back and stays at DEBUG.

I can do

def call_with_loglevel(logger, level, f, **kwargs):
    "Call f with logger at a different level"
    saved_logger_level = logger.level
    logger.setLevel(level)
    try:
        return f(**kwargs)
    finally:
        logger.setLevel(saved_logger_level)

but this requires me to define f out of the do_something_with_higher_logging[123]...

What I want is something like

with my_logger.setLevel(logging.DEBUG):
    a = do_something_with_higher_logging1()
    b,c = do_something_with_higher_logging2()
    d = do_something_with_higher_logging3()

Upvotes: 2

Views: 198

Answers (1)

sds
sds

Reputation: 60054

Making Logger.setLevel return a context manager seems like a backwards-compatible change (should I create an RFE?) but for now it looks like I can do

from contextlib import contextmanager

@contextmanager
def log_level(logger, level):
    "Run body with logger at a different level"
    saved_logger_level = logger.level
    logger.setLevel(level)
    try:
        yield saved_logger_level
    finally:
        logger.setLevel(saved_logger_level)

Note that if we are increasing verbosity (e.g., to the "DEBUG" level), we need to also change the verbosity of the handlers (otherwise they will not show the messages that were sent to them), but then the change is no longer backwards compatible:

from contextlib import contextmanager

@contextmanager
def logLevel(logger, level=None):
    "Run body with logger at a different level."
    # https://stackoverflow.com/q/78035371/850781
    saved_logger_level = logger.level
    saved_handler_levels = [ha.level for ha in logger.handlers]
    new_level = logger.getEffectiveLevel()+10 if level is None else level
    logger.setLevel(new_level)
    for ha in logger.handlers:
        ha.setLevel(new_level)
    try:
        yield saved_logger_level, saved_handler_levels
    finally:
        logger.setLevel(saved_logger_level)
        for ha,le in zip(logger.handlers,saved_handler_levels):
            ha.setLevel(le)

Upvotes: 1

Related Questions