summaryrefslogtreecommitdiffstats
path: root/src/util/msg_rate_delay.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 12:06:34 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 12:06:34 +0000
commit5e61585d76ae77fd5e9e96ebabb57afa4d74880d (patch)
tree2b467823aaeebc7ef8bc9e3cabe8074eaef1666d /src/util/msg_rate_delay.c
parentInitial commit. (diff)
downloadpostfix-upstream/3.5.24.tar.xz
postfix-upstream/3.5.24.zip
Adding upstream version 3.5.24.upstream/3.5.24upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/util/msg_rate_delay.c')
-rw-r--r--src/util/msg_rate_delay.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/util/msg_rate_delay.c b/src/util/msg_rate_delay.c
new file mode 100644
index 0000000..e21b021
--- /dev/null
+++ b/src/util/msg_rate_delay.c
@@ -0,0 +1,138 @@
+/*++
+/* NAME
+/* msg_rate_delay 3
+/* SUMMARY
+/* diagnostic interface
+/* SYNOPSIS
+/* #include <msg.h>
+/*
+/* void msg_rate_delay(stamp, delay, log_fn, fmt, ...)
+/* time_t *stamp;
+/* int delay;
+/* void (*log_fn)(const char *fmt, ...);
+/* const char *fmt;
+/* DESCRIPTION
+/* msg_rate_delay() produces log output at a reduced rate: no
+/* more than one message per 'delay' seconds. It discards log
+/* output that would violate the output rate policy.
+/*
+/* This is typically used to log errors accessing a cache with
+/* high-frequency access but low-value information, to avoid
+/* spamming the logfile with the same kind of message.
+/*
+/* Arguments:
+/* .IP stamp
+/* Time stamp of last log output; specify a zero time stamp
+/* on the first call. This is an input-output parameter.
+/* This parameter is ignored when verbose logging is enabled
+/* or when the delay value is zero.
+/* .IP delay
+/* The minimum time between log outputs; specify zero to log
+/* all output for debugging purposes. This parameter is ignored
+/* when verbose logging is enabled.
+/* .IP log_fn
+/* The function that produces log output. Typically, this will
+/* be msg_info() or msg_warn().
+/* .IP fmt
+/* Format string as used with msg(3) routines.
+/* SEE ALSO
+/* msg(3) diagnostics interface
+/* DIAGNOSTICS
+/* Fatal errors: memory allocation problem.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <time.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <events.h>
+
+/* SLMs. */
+
+#define STR(x) vstring_str(x)
+
+/* msg_rate_delay - rate-limit message logging */
+
+void msg_rate_delay(time_t *stamp, int delay,
+ void (*log_fn) (const char *,...),
+ const char *fmt,...)
+{
+ const char *myname = "msg_rate_delay";
+ static time_t saved_event_time;
+ time_t now;
+ VSTRING *buf;
+ va_list ap;
+
+ /*
+ * Sanity check.
+ */
+ if (delay < 0)
+ msg_panic("%s: bad message rate delay: %d", myname, delay);
+
+ /*
+ * This function may be called frequently. Avoid an unnecessary syscall
+ * if possible. Deal with the possibility that a program does not use the
+ * events(3) engine, so that event_time() always produces the same
+ * result.
+ */
+ if (msg_verbose == 0 && delay > 0) {
+ if (saved_event_time == 0)
+ now = saved_event_time = event_time();
+ else if ((now = event_time()) == saved_event_time)
+ now = time((time_t *) 0);
+
+ /*
+ * Don't log if time is too early.
+ */
+ if (*stamp + delay > now)
+ return;
+ *stamp = now;
+ }
+
+ /*
+ * OK to log. This is a low-rate event, so we can afford some overhead.
+ */
+ buf = vstring_alloc(100);
+ va_start(ap, fmt);
+ vstring_vsprintf(buf, fmt, ap);
+ va_end(ap);
+ log_fn("%s", STR(buf));
+ vstring_free(buf);
+}
+
+#ifdef TEST
+
+ /*
+ * Proof-of-concept test program: log messages but skip messages during a
+ * two-second gap.
+ */
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+ int n;
+ time_t stamp = 0;
+
+ for (n = 0; n < 6; n++) {
+ msg_rate_delay(&stamp, 2, msg_info, "text here %d", n);
+ sleep(1);
+ }
+ return (0);
+}
+
+#endif