Standard library logging plus loguru

Viewed 1637

Let's say I'm setting up a script or library that has a few dependencies which use Python's standard library logging module but I want to use loguru to capture all logs. My first naive attempt was a complete failure, but I'm not sure how to proceed.

To test I have two files

main.py:

from loguru import logger

from base_log import test_func

if __name__ == "__main__":
    logger.debug("In main")
    test_func()

and base_log.py:

import logging

logger = logging.getLogger(__name__)


def test_func():
    logger.warning("In test_func")

If I run main.py (i.e. python main.py) then I get the following output:

2020-12-16 10:57:48.269 | DEBUG    | __main__:<module>:6 - In main
In test_func

When I expect:

2020-12-16 11:01:34.408 | DEBUG    | __main__:<module>:6 - In main
2020-12-16 11:01:34.408 | WARNING  | base_log:test_func:9 - In test_func
1 Answers

You can use a custom handler to intercept standard logging messages toward your Loguru sinks as documented here.

main.py will then look something like this:

import logging

from loguru import logger

from base_log import test_func


class InterceptHandler(logging.Handler):
    def emit(self, record):
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = record.levelno

        frame, depth = logging.currentframe(), 2
        while frame.f_code.co_filename == logging.__file__:
            frame = frame.f_back
            depth += 1

        logger.opt(depth=depth, exception=record.exc_info).log(
            level, record.getMessage()
        )


if __name__ == "__main__":
    logging.basicConfig(handlers=[InterceptHandler()], level=0)
    logger.debug("In main")
    test_func()

Output:

2020-12-16 22:15:55.337 | DEBUG    | __main__:<module>:26 - In main
2020-12-16 22:15:55.337 | WARNING  | base_log:test_func:7 - In test_func

This should work for all well-behaved libraries that do not add any handlers other than NullHandler to the libraries' loggers. The rest may need extra work.

Related