xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/msg_rate_delay.c (revision a30b880ed60a24c405edba78187a04247f4d9d33)
1 /*	$NetBSD: msg_rate_delay.c,v 1.1.1.1 2013/01/02 18:59:13 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	msg_rate_delay 3
6 /* SUMMARY
7 /*	diagnostic interface
8 /* SYNOPSIS
9 /*	#include <msg.h>
10 /*
11 /*	void	msg_rate_delay(stamp, delay, log_fn, fmt, ...)
12 /*	time_t	*stamp;
13 /*	int	delay;
14 /*	void	(*log_fn)(const char *fmt, ...);
15 /*	const char *fmt;
16 /* DESCRIPTION
17 /*	msg_rate_delay() produces log output at a reduced rate: no
18 /*	more than one message per 'delay' seconds. It discards log
19 /*	output that would violate the output rate policy.
20 /*
21 /*	This is typically used to log errors accessing a cache with
22 /*	high-frequency access but low-value information, to avoid
23 /*	spamming the logfile with the same kind of message.
24 /*
25 /*	Arguments:
26 /* .IP stamp
27 /*	Time stamp of last log output; specify a zero time stamp
28 /*	on the first call.  This is an input-output parameter.
29 /*	This parameter is ignored when verbose logging is enabled
30 /*	or when the delay value is zero.
31 /* .IP delay
32 /*	The minimum time between log outputs; specify zero to log
33 /*	all output for debugging purposes.  This parameter is ignored
34 /*	when verbose logging is enabled.
35 /* .IP log_fn
36 /*	The function that produces log output. Typically, this will
37 /*	be msg_info() or msg_warn().
38 /* .IP fmt
39 /*	Format string as used with msg(3) routines.
40 /* SEE ALSO
41 /*	msg(3) diagnostics interface
42 /* DIAGNOSTICS
43 /*	Fatal errors: memory allocation problem.
44 /* LICENSE
45 /* .ad
46 /* .fi
47 /*	The Secure Mailer license must be distributed with this software.
48 /* AUTHOR(S)
49 /*	Wietse Venema
50 /*	IBM T.J. Watson Research
51 /*	P.O. Box 704
52 /*	Yorktown Heights, NY 10598, USA
53 /*--*/
54 
55 
56 /* System library. */
57 
58 #include <sys_defs.h>
59 #include <time.h>
60 
61 /* Utility library. */
62 
63 #include <msg.h>
64 #include <vstring.h>
65 #include <events.h>
66 
67 /* SLMs. */
68 
69 #define STR(x) vstring_str(x)
70 
71 /* msg_rate_delay - rate-limit message logging */
72 
msg_rate_delay(time_t * stamp,int delay,void (* log_fn)(const char *,...),const char * fmt,...)73 void    msg_rate_delay(time_t *stamp, int delay,
74 		               void (*log_fn) (const char *,...),
75 		               const char *fmt,...)
76 {
77     const char *myname = "msg_rate_delay";
78     static time_t saved_event_time;
79     time_t  now;
80     VSTRING *buf;
81     va_list ap;
82 
83     /*
84      * Sanity check.
85      */
86     if (delay < 0)
87 	msg_panic("%s: bad message rate delay: %d", myname, delay);
88 
89     /*
90      * This function may be called frequently. Avoid an unnecessary syscall
91      * if possible. Deal with the possibility that a program does not use the
92      * events(3) engine, so that event_time() always produces the same
93      * result.
94      */
95     if (msg_verbose == 0 && delay > 0) {
96 	if (saved_event_time == 0)
97 	    now = saved_event_time = event_time();
98 	else if ((now = event_time()) == saved_event_time)
99 	    now = time((time_t *) 0);
100 
101 	/*
102 	 * Don't log if time is too early.
103 	 */
104 	if (*stamp + delay > now)
105 	    return;
106 	*stamp = now;
107     }
108 
109     /*
110      * OK to log. This is a low-rate event, so we can afford some overhead.
111      */
112     buf = vstring_alloc(100);
113     va_start(ap, fmt);
114     vstring_vsprintf(buf, fmt, ap);
115     va_end(ap);
116     log_fn("%s", STR(buf));
117     vstring_free(buf);
118 }
119 
120 #ifdef TEST
121 
122  /*
123   * Proof-of-concept test program: log messages but skip messages during a
124   * two-second gap.
125   */
126 #include <unistd.h>
127 
main(int argc,char ** argv)128 int     main(int argc, char **argv)
129 {
130     int     n;
131     time_t  stamp = 0;
132 
133     for (n = 0; n < 6; n++) {
134 	msg_rate_delay(&stamp, 2, msg_info, "text here %d", n);
135 	sleep(1);
136     }
137     return (0);
138 }
139 
140 #endif
141