Home | History | Annotate | Line # | Download | only in util
      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 
     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 
    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