1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
// SPDX-License-Identifier: GPL-3.0-or-later
#include "nd_log_limit.h"
void nd_log_limits_reset(void) {
usec_t now_ut = now_monotonic_usec();
spinlock_lock(&nd_log.std_output.spinlock);
spinlock_lock(&nd_log.std_error.spinlock);
for(size_t i = 0; i < _NDLS_MAX ;i++) {
spinlock_lock(&nd_log.sources[i].spinlock);
nd_log.sources[i].limits.prevented = 0;
nd_log.sources[i].limits.counter = 0;
nd_log.sources[i].limits.started_monotonic_ut = now_ut;
nd_log.sources[i].limits.logs_per_period = nd_log.sources[i].limits.logs_per_period_backup;
spinlock_unlock(&nd_log.sources[i].spinlock);
}
spinlock_unlock(&nd_log.std_output.spinlock);
spinlock_unlock(&nd_log.std_error.spinlock);
}
void nd_log_limits_unlimited(void) {
nd_log_limits_reset();
for(size_t i = 0; i < _NDLS_MAX ;i++) {
nd_log.sources[i].limits.logs_per_period = 0;
}
}
bool nd_log_limit_reached(struct nd_log_source *source) {
if(source->limits.throttle_period == 0 || source->limits.logs_per_period == 0)
return false;
usec_t now_ut = now_monotonic_usec();
if(!source->limits.started_monotonic_ut)
source->limits.started_monotonic_ut = now_ut;
source->limits.counter++;
if(now_ut - source->limits.started_monotonic_ut > (usec_t)source->limits.throttle_period) {
if(source->limits.prevented) {
BUFFER *wb = buffer_create(1024, NULL);
buffer_sprintf(wb,
"LOG FLOOD PROTECTION: resuming logging "
"(prevented %"PRIu32" logs in the last %"PRIu32" seconds).",
source->limits.prevented,
source->limits.throttle_period);
if(source->pending_msg)
freez((void *)source->pending_msg);
source->pending_msg = strdupz(buffer_tostring(wb));
buffer_free(wb);
}
// restart the period accounting
source->limits.started_monotonic_ut = now_ut;
source->limits.counter = 1;
source->limits.prevented = 0;
// log this error
return false;
}
if(source->limits.counter > source->limits.logs_per_period) {
if(!source->limits.prevented) {
BUFFER *wb = buffer_create(1024, NULL);
buffer_sprintf(wb,
"LOG FLOOD PROTECTION: too many logs (%"PRIu32" logs in %"PRId64" seconds, threshold is set to %"PRIu32" logs "
"in %"PRIu32" seconds). Preventing more logs from process '%s' for %"PRId64" seconds.",
source->limits.counter,
(int64_t)((now_ut - source->limits.started_monotonic_ut) / USEC_PER_SEC),
source->limits.logs_per_period,
source->limits.throttle_period,
program_name,
(int64_t)(((source->limits.started_monotonic_ut + (source->limits.throttle_period * USEC_PER_SEC) - now_ut)) / USEC_PER_SEC)
);
if(source->pending_msg)
freez((void *)source->pending_msg);
source->pending_msg = strdupz(buffer_tostring(wb));
buffer_free(wb);
}
source->limits.prevented++;
// prevent logging this error
#ifdef NETDATA_INTERNAL_CHECKS
return false;
#else
return true;
#endif
}
return false;
}
|