Delgan / loguru

Python logging made (stupidly) simple
MIT License
19.62k stars 695 forks source link

Capturing warnings with the correct source location #1076

Closed ibro45 closed 8 months ago

ibro45 commented 8 months ago

https://loguru.readthedocs.io/en/stable/resources/recipes.html#capturing-standard-stdout-stderr-and-warnings

When logging the path from which the warning message occurred, it will show the exact location of where you patched showwarning instead of where the warning message was actually called from.

For example, the first and last warnings are coming from PyTorch Lightning, but here it says that they come from my logging.py module, where I did what's described in the link above.

image

Is there any viable solution to this? Thanks!

Delgan commented 8 months ago

You can certainly use the depth argument of the .opt() method:

def showwarning(message, *args, **kwargs):
    logger.opt(depth=2).warning(message)
    showwarning_(message, *args, **kwargs)

If you can confirm that works, I will update the documentation.

ibro45 commented 8 months ago

Yes, that did it, thanks for such a quick reply 😁

Delgan commented 8 months ago

Great, you're welcome. :+1:

ibro45 commented 7 months ago

Hi, sorry to bother you again. Have you ever passed the warnings.warn's stacklevel argument to loguru as depth? I don't see a clean way of doing it currently.

For example: https://github.com/Lightning-AI/utilities/blob/275edd4fdd7612faa9be2c7cf962780cf618d082/src/lightning_utilities/core/rank_zero.py#L74

Unfortunately seems like warnings.warn() doesn't pass stacklevel to warnings.showwarning https://github.com/python/cpython/blob/01dceba13e872e9ca24b8e00a2b75db3d0d6c1a3/Lib/warnings.py#L303

Delgan commented 7 months ago

Hum, that's a pitty... I don't think there's any clean way of doing it, unfortunately.

Technically, you could iterate the stack to retrieve the depth where warns.warn() was emitted. More realistically, I would just advice to add the filename and lineno to your logged message:

def showwarning(message, category, filename, lineno, file=None, line=None):
    logger.opt(depth=2).warning("Warning emitted from '{}:{}': {}", message, filename, lineno)
    showwarning_(message, category, filename, lineno, file, line)