On Thu, Mar 26, 2026 at 03:20:20PM +0530, Anshu Kumari wrote: > Currently, some log messages that would be useful at info or warn level > are kept at debug level because there is no way to throttle them, and a > guest could otherwise flood the host logs. > > Add a logmsg_ratelimit() macro that uses per-call-site static variables > to independently track each call site's rate. It allows up to > LOG_RATELIMIT_BURST (5) messages per LOG_RATELIMIT_INTERVAL (1 second) > window, then prints a suppression notice. When a new window opens and > messages were suppressed, the count is reported after the next allowed > message. > > Link: https://bugs.passt.top/show_bug.cgi?id=134 > Signed-off-by: Anshu Kumari Reviewed-by: David Gibson > --- > v4: > - Print suppression notice immediately after the last allowed message, > not on the next call, to avoid confusion with unrelated messages > in between. > - Add Link: tag before Signed-off-by > --- > log.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 44 insertions(+) > > diff --git a/log.h b/log.h > index 6ceb686..dbab006 100644 > --- a/log.h > +++ b/log.h > @@ -48,6 +48,50 @@ void logmsg_perror(int pri, const char *format, ...) > passt_exit(EXIT_FAILURE); \ > } while (0) > > +#define LOG_RATELIMIT_INTERVAL 1 /* Default rate limit window in seconds */ > +#define LOG_RATELIMIT_BURST 5 /* Max messages per window per call site */ > + > +/** > + * logmsg_ratelimit() - Log a message with rate limiting > + * @fn: Logging function name (e.g. warn, info, debug) > + * @now: Current timestamp > + */ > +#define logmsg_ratelimit(fn, now, ...) \ > + do { \ > + static unsigned int rl_suppressed_; \ > + static unsigned int rl_printed_; \ > + static time_t rl_last_; \ > + \ > + if ((now)->tv_sec - rl_last_ > LOG_RATELIMIT_INTERVAL) {\ > + rl_last_ = (now)->tv_sec; \ > + rl_printed_ = 0; \ > + } \ > + \ > + if (rl_printed_ < LOG_RATELIMIT_BURST) { \ > + fn(__VA_ARGS__); \ > + if (rl_suppressed_) { \ > + fn("(suppressed %u similar messages)", \ > + rl_suppressed_); \ > + rl_suppressed_ = 0; \ > + } \ > + rl_printed_++; \ > + if (rl_printed_ == LOG_RATELIMIT_BURST) \ > + fn("(suppressing further similar" \ > + " messages)"); \ > + } else { \ > + rl_suppressed_++; \ > + } \ > + } while (0) > + > +#define err_ratelimit(now, ...) \ > + logmsg_ratelimit(err, now, __VA_ARGS__) > +#define warn_ratelimit(now, ...) \ > + logmsg_ratelimit(warn, now, __VA_ARGS__) > +#define info_ratelimit(now, ...) \ > + logmsg_ratelimit(info, now, __VA_ARGS__) > +#define debug_ratelimit(now, ...) \ > + logmsg_ratelimit(debug, now, __VA_ARGS__) > + > extern int log_file; > extern int log_trace; > extern bool log_conf_parsed; > -- > 2.53.0 > -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson