Mayil-AI / loguru

MIT License
0 stars 0 forks source link

Ability to pass Exception to logger.exception (hashtag1087) #4

Open vikramsubramanian opened 3 months ago

vikramsubramanian commented 3 months ago

In asyncio callbacks, i.e.: a Starlette error handler, we have the exception but it's not part of the sys.exc_info(). Therefore I can't log the stacktrace via logger.exception().

It'd be great if I could pass the exception in, i.e.:

def exception(__self, __message, *args, exception: BaseException | tuple | bool = True, **kwargs):  hashtag noqa: N805
        r"""Convenience method for logging an ``'ERROR'`` with exception information."""
        options = (exception,) + __self._options[1:]
        __self._log("ERROR", False, options, __message, args, kwargs)

Right now the workaround is to use private options and functions

options = (error,) + logger._options[1:]
logger._log("ERROR", False, options, f'Server Error: {error}', [], {})

)

mayil-ai[bot] commented 3 months ago

Implementation ideas

To implement the feature request described in the Jira ticket, you will need to modify the loguru library's logging methods to allow passing an exception directly to the logger.exception() method. Here's a high-level overview of the steps to implement this feature:

Here's a more detailed breakdown:

  1. Update the ErrorInterceptor class to handle a passed exception:

    class ErrorInterceptor:
       # ... existing code ...
    
       def print(self, record=None, *, exception=None):
           # ... existing code ...
    
           if exception is not None:
               type_, value, traceback_ = (type(exception), exception, exception.__traceback__)
           else:
               type_, value, traceback_ = sys.exc_info()
    
           # ... existing code ...
  2. Modify the _log method in the _logger.py file to accept an exception parameter and pass it to the ErrorInterceptor:

    def _log(self, level, msg, *args, exception=None, **kwargs):
       # ... existing code ...
    
       if exception is not None:
           options = (exception,) + self._options[1:]
       else:
           options = self._options
    
       # ... existing code ...
  3. Update the exception method in the _logger.py file to accept the exception parameter and pass it to the _log method:

    def exception(self, msg, *args, exception=None, **kwargs):
       self._log("ERROR", msg, *args, exception=exception, **kwargs)
  4. Ensure that the exception method is exposed in the logger's interface so that it can be called with the new parameter.

After making these changes, you should be able to call logger.exception() with an exception object, and it will log the stack trace of the passed exception instead of the current exception from sys.exc_info().

Please note that this is a high-level overview, and you will need to ensure that the changes are compatible with the rest of the loguru library's codebase. Additionally, you should write unit tests to cover the new functionality and ensure that existing functionality is not broken by the changes.

Code snippets to check

loguru → _error_interceptor.py This snippet contains the ErrorInterceptor class which has a print method that could be modified to allow passing an exception directly, which is relevant to the issue. https://github.com/Mayil-AI/loguru/blob/871de74acb2382fb3982d3fb8e224e4a82de9073/loguru/_error_interceptor.py#L1-L34
loguru → _handler.py This snippet shows the use of the ErrorInterceptor's print method within a try-except block, which is relevant to the issue as it's part of the error handling flow where the enhancement could be applied. https://github.com/Mayil-AI/loguru/blob/871de74acb2382fb3982d3fb8e224e4a82de9073/loguru/_handler.py#L207-L210
loguru → _logger.py This snippet includes the logging logic where the exception is checked and processed. Modifications here could allow passing an exception directly to the logger.exception method, addressing the issue. https://github.com/Mayil-AI/loguru/blob/871de74acb2382fb3982d3fb8e224e4a82de9073/loguru/_logger.py#L1906-L2020