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