-
Notifications
You must be signed in to change notification settings - Fork 711
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Log something only once (or only N times) #383
Comments
Hi @MatthewScholefield. Sorry for replying so late. This seems to be a very interesting idea. I remember at some point I was also looking for a way to prevent excessive logging of the same message. Finally I did not implement anything because I was not sure such rate-limiting for logging was good practice or not. I wish I could just extend Alternatively, one could use another library like So, yeah, thanks for your suggestion! It could be worth integrating it into Loguru, I will keep thinking about it. |
I'm quite interested in this feature as well. Can you expand on the |
@liz-zither Ok, my bad. The Here is another example using a custom class: from loguru import logger
from unittest.mock import MagicMock
class LimitedLogger:
def __init__(self, limit=None):
self._limit = limit
self._count = 0
def get(self):
if self._limit is None or self._count < self._limit:
self._count += 1
return logger
else:
return MagicMock()
limited_logger = LimitedLogger(limit=10)
for i in range(100):
limited_logger.get().info("Iteration #{}", i) |
It seems that the documentation on this feature got missed. Can someone write the final usage of this feature here? Perhaps we can also add it to the Help Guide. |
@DeflateAwning It's not yet documented because it's not yet implemented. :) Actually I don't know if this should be provided as built-in in Loguru or as a third-library. |
I'd love this feature as well! I've worked with internal logging systems before that offered a Playing around a bit, I can get a
This would apply to every message, so I'd need to think of a way to easily set per-message N values. |
Same feature request here! Expect the updates on this topic. |
also requests this feature. log_N_times is useful in simple warning cases |
I wanted to do something similar but only showing 1 of any message per minute. I don't know if there's any potential issues, but I managed to get this working through a custom 'Debounce' log level:
|
Same feature request! |
I came up with this simple POC: import atexit as _atexit
import sys as _sys
from collections import defaultdict
from loguru import _defaults
from loguru._logger import Core as _Core
from loguru._logger import Logger as _Logger
class MyLogger(_Logger):
_msg_history = defaultdict(set)
def _log(self, level, from_decorator, options, message, args, kwargs):
once = kwargs.pop("once", False)
if once:
if message in self._msg_history[level]:
return
self._msg_history[level].add(message)
super()._log(level, from_decorator, options, message, args, kwargs)
logger = MyLogger(
core=_Core(),
exception=None,
depth=0,
record=False,
lazy=False,
colors=False,
raw=False,
capture=True,
patchers=[],
extra={},
)
if _defaults.LOGURU_AUTOINIT and _sys.stderr:
logger.add(_sys.stderr)
_atexit.register(logger.remove)
logger.warning("This is a warning message", once=True)
logger.warning("This is a warning message", once=True)
logger.warning("This is a warning message", once=True)
logger.warning("This is a warning message 123", once=True)
logger.info("This is a warning message", once=True)
logger.info("This is a warning message", once=True) Asking the core devs here - do you think it can be plugged into the current implementation? |
@noamgot It looks like you can use the existing import sys
from collections import defaultdict
from loguru import logger
_msg_history = defaultdict(set)
def filter(record):
if "once" in record["extra"]:
level = record["level"].no
message = record["message"]
if message in _msg_history[level]:
return False
_msg_history[level].add(message)
return True
logger.remove()
logger.add(sys.stderr, filter=filter)
logger.warning("This is a warning message", once=True)
logger.warning("This is a warning message", once=True)
logger.warning("This is a warning message", once=True)
logger.warning("This is a warning message 123", once=True)
logger.info("This is a warning message", once=True)
logger.info("This is a warning message", once=True) |
Looks like a decent solution, works for me. thanks @Delgan |
I have a situation where I want to log something only once. It would be nice to have some
logger.opt(once=True)
. For example:Without such an option, either a non-fatal warning bloats the logs repeating the same message, or I'd need to unpleasantly use a global variable:
Naturally, this would lead to me writing a help function,
log_once
. So, I figured it would make sense to include something like this with loguru. What do you think?To support the
log_once = logger.opt(once=True); log_once('here'); log_once('there')
, it could store a set of printed log statements based on the line number of the logger call. Alternatively, using a new method, it could simply store it once per instance likelogger.limit(1).warning('hello')
which would implicitly allow another use case of constraining the number of lines of some related set of warnings ie.:The text was updated successfully, but these errors were encountered: