question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Logging adapter in readme doesn't resolve log level names

See original GitHub issue

summary

The readme provides a InterceptHandler class to hook existing logging calls and forward them into loguru. The hook itself works, however does not resolve log levels. The result is we get unexpected loguru output, where instead of getting the localized name 'INFO' we get 'Level 20'.

>>> logger.debug("loguru debug")
2019-10-13 21:21:33.728 | DEBUG    | __main__:<module>:1 - loguru debug
>>> logging.debug("logging debug")
2019-10-13 21:21:33.729 | Level 10 | logging:handle:905 - logging debug
>>>

This incorrect output also breaks loguru’s color formatting image

It appears that Loguru does not resolve integer log levels it can understand for message formatting.

Minimum reproduceable example

import logging
from loguru import logger

# class directly applied from the README
class InterceptHandler(logging.Handler):
    def emit(self, record):
        # Intercepts standard logging messages for the purpose of sending them to loguru
        logger_opt = logger.opt(depth=1, exception=record.exc_info)
        logger_opt.log(record.levelno, record.getMessage())


logging.basicConfig(handlers=[InterceptHandler()], level=0)


logger.debug("loguru debug")
logging.debug("logging debug")

logger.info("loguru info")
logging.info("logging info")


logger.warning("loguru warning")
logging.warning("logging warning")

logger.error("loguru error")
logging.error("logging error")

logger.critical("loguru critical")
logging.critical("logging critical")

Versions

>>> loguru.__version__
'0.3.2'
  • OS: Windows 10 x64, Ubuntu Xenial
  • CLI environment: Powershell, bash

Potential fix

After debugging and analyzing how loguru handles its own logging calls, it appears that its expecting string level names. e.g. "DEBUG" and "CRITICAL". With this expectation in mind, this bug can be resolved by having the InterceptHandler resolve the logging log level name prior to delegating the event to loguru.

It would be a one-line patch

class InterceptHandler(logging.Handler):
    def emit(self, record):
        # Intercepts standard logging messages for the purpose of sending them to loguru
        logger_opt = logger.opt(depth=1, exception=record.exc_info)
        # resolve the log level to a name, then emit the message to Loguru
        logger_opt.log(logging.getLevelName(record.levelno), record.getMessage())
        # logger_opt.log(record.levelno, record.getMessage())

image

I will open a PR soon to this effect.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:7 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
Delgancommented, Nov 1, 2019

So, I think I will replace the current snippet:

class InterceptHandler(logging.Handler):
    def emit(self, record):
        # Retrieve context where the logging call occurred, this happens to be in the 6th frame upward
        logger_opt = logger.opt(depth=6, exception=record.exc_info)
        logger_opt.log(record.levelno, record.getMessage())

With this one:

class InterceptHandler(logging.Handler):
    def emit(self, record):
        # Get corresponding Loguru level if it exists
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = record.levelno

        # Find caller from where originated the logging call
        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())

This should fix both #154 (level problem) and #78 (depth problem) in such situation:

import logging
logger_ = logging.getLogger()
logging.info("Foo")
logger_.log(42, "Bar")

Obviously, I’m not entirely satisfied with this solution. It’s not much pretty. Unfortunately, I don’t think there is any other possible workaround, and I do not want to make InterceptHandler() / PropagateHandler() part of the Loguru API.

There is also the possibility to use the logger.patch() to update the Loguru’s record dict, but this would not work well with .enable() and .disable() (because it’s resolved before patching) and hence would lead to other problems.

I will probably update the Readme and close this issue in the next few days, if by then I haven’t had a revelation. 🙂

0reactions
Delgancommented, Nov 9, 2019

Readme updated. 😉

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can't get this custom logging adapter example to work
You have to use the adapter for logging, not the logger. Try this: import logging class CustomAdapter(logging.LoggerAdapter): def process(self, msg, ...
Read more >
https://www.cpan.org/modules/by-module/Log/Log-Any...
NAME Log ::Any -- Bringing loggers and listeners together SYNOPSIS In a CPAN ... In your application: use Log::Any::Adapter; # Send all logs...
Read more >
ServiceDesk Plus readme, release notes, and version history
View the readme release notes of ServiceDesk Plus, an ITIL-ready help desk software with integrated asset management and project management functionalities.
Read more >
Events and logs - dbt Developer Hub
The debug log file ( logs/dbt.log ), to enable detailed debugging of ... well as contextual information, such as log level and thread...
Read more >
Apache log4net: Release Notes
logger name ; [LOG4NET-347] - Log4net not working in an ASP. ... CompareTo() may result a wrong Value -> sorting of Levels does...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found