-
Notifications
You must be signed in to change notification settings - Fork 1
/
muter.go
96 lines (76 loc) · 2.51 KB
/
muter.go
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
// Copyright 2022 Teal.Finance/Garcon contributors
// This file is part of Teal.Finance/Garcon,
// an API and website server under the MIT License.
// SPDX-License-Identifier: MIT
package garcon
import (
"time"
)
// Muter can be used to limit the logger/alerting verbosity.
// Muter detects when its internal counter is over the Threshold
// and waits the counter goes back to zero or after NoAlertDuration
// to return to normal situation.
// Muter uses the Hysteresis principle: https://wikiless.org/wiki/Hysteresis
// Similar wording: quieter, stopper, limiter, reducer, inhibitor, mouth-closer.
type Muter struct {
// Threshold is the level enabling the muted state.
Threshold int
// NoAlertDuration allows to consider the verbosity is back to normal.
NoAlertDuration time.Duration
// RemindMuteState allows to remind the state is still muted.
// Set value 100 to send this reminder every 100 increments.
// Set to zero to disable this feature,
RemindMuteState int
// counter is incremented/decremented, but is never negative.
counter int
// muted represent the Muter state.
muted bool
// quietTime is the first call of successive Decrement()
// without any Increment(). quietTime is used to
// inform the time since no Increment() has been called.
quietTime time.Time
// dropped is the number of Increment() calls after state became muted.
dropped int
}
// Increment increments the internal counter and returns false when in muted state.
// Every RemindMuteState calls, Increment also returns the number of times Increment has been called.
func (m *Muter) Increment() (ok bool, dropped int) {
m.counter++
if m.muted {
m.dropped++
if (m.RemindMuteState == 0) || (m.dropped%m.RemindMuteState) > 0 {
return false, -1
}
}
if m.muted {
return true, m.dropped
}
if m.counter > m.Threshold {
m.muted = true
m.dropped = 0
m.quietTime = time.Time{}
return true, 1
}
return true, 0
}
// Decrement decrements the internal counter and switches to un-muted state
// when counter reaches zero or after NoAlertDuration.
func (m *Muter) Decrement() (ok bool, _ time.Time, dropped int) {
if !m.muted {
return false, time.Time{}, 0 // already un-muted, do nothing
}
m.counter--
if m.counter > 0 {
if m.quietTime.IsZero() {
// first call to Decrement() since last Increment() call
m.quietTime = time.Now()
return false, time.Time{}, 0
}
if time.Since(m.quietTime) < m.NoAlertDuration {
return false, time.Time{}, 0
}
m.counter = 0
}
m.muted = false
return true, m.quietTime, m.dropped
}