Update copyrights to 2021, using "make update-copyright"
[tor.git] / src / lib / log / ratelim.c
blob846cac0700e1e0c782f70779169614d38844775e
1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 /**
7 * \file ratelim.c
8 * \brief Summarize similar messages that would otherwise flood the logs.
9 **/
11 #include "lib/log/ratelim.h"
12 #include "lib/malloc/malloc.h"
13 #include "lib/string/printf.h"
14 #include "lib/intmath/muldiv.h"
16 /** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number
17 * of calls to rate_limit_is_ready (including this one!) since the last time
18 * rate_limit_is_ready returned nonzero. Otherwise return 0.
19 * If the call number hits <b>RATELIM_TOOMANY</b> limit, drop a warning
20 * about this event and stop counting. */
21 static int
22 rate_limit_is_ready(ratelim_t *lim, time_t now)
24 if (lim->rate + lim->last_allowed <= now) {
25 int res = lim->n_calls_since_last_time + 1;
26 lim->last_allowed = now;
27 lim->n_calls_since_last_time = 0;
28 return res;
29 } else {
30 if (lim->n_calls_since_last_time <= RATELIM_TOOMANY) {
31 ++lim->n_calls_since_last_time;
34 return 0;
38 /** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return a newly
39 * allocated string indicating how many messages were suppressed, suitable to
40 * append to a log message. Otherwise return NULL. */
41 char *
42 rate_limit_log(ratelim_t *lim, time_t now)
44 int n;
45 if ((n = rate_limit_is_ready(lim, now))) {
46 time_t started_limiting = lim->started_limiting;
47 lim->started_limiting = 0;
48 if (n == 1) {
49 return tor_strdup("");
50 } else {
51 char *cp=NULL;
52 const char *opt_over = (n >= RATELIM_TOOMANY) ? "over " : "";
53 unsigned difference = (unsigned)(now - started_limiting);
54 difference = round_to_next_multiple_of(difference, 60);
55 tor_asprintf(&cp,
56 " [%s%d similar message(s) suppressed in last %d seconds]",
57 opt_over, n-1, (int)difference);
58 return cp;
60 } else {
61 if (lim->started_limiting == 0) {
62 lim->started_limiting = now;
64 return NULL;