forked from vitessio/vitess
-
Notifications
You must be signed in to change notification settings - Fork 1
/
throttled.go
78 lines (66 loc) · 1.77 KB
/
throttled.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
package logutil
import (
"sync"
"time"
log "github.com/golang/glog"
)
// ThrottledLogger will allow logging of messages but won't spam the
// logs.
type ThrottledLogger struct {
// set at construction
name string
maxInterval time.Duration
// mu protects the following members
mu sync.Mutex
lastlogTime time.Time
skippedCount int
}
// NewThrottledLogger will create a ThrottledLogger with the given
// name and throttling interval.
func NewThrottledLogger(name string, maxInterval time.Duration) *ThrottledLogger {
return &ThrottledLogger{
name: name,
maxInterval: maxInterval,
}
}
type logFunc func(string, ...interface{})
var (
infof = log.Infof
warningf = log.Warningf
errorf = log.Errorf
)
func (tl *ThrottledLogger) log(logF logFunc, format string, v ...interface{}) {
now := time.Now()
tl.mu.Lock()
defer tl.mu.Unlock()
logWaitTime := tl.maxInterval - (now.Sub(tl.lastlogTime))
if logWaitTime < 0 {
tl.lastlogTime = now
logF(tl.name+":"+format, v...)
return
}
// If this is the first message to be skipped, start a goroutine
// to log and reset skippedCount
if tl.skippedCount == 0 {
go func(d time.Duration) {
time.Sleep(d)
tl.mu.Lock()
defer tl.mu.Unlock()
logF("%v: skipped %v log messages", tl.name, tl.skippedCount)
tl.skippedCount = 0
}(logWaitTime)
}
tl.skippedCount++
}
// Infof logs an info if not throttled.
func (tl *ThrottledLogger) Infof(format string, v ...interface{}) {
tl.log(infof, format, v...)
}
// Warningf logs a warning if not throttled.
func (tl *ThrottledLogger) Warningf(format string, v ...interface{}) {
tl.log(warningf, format, v...)
}
// Errorf logs an error if not throttled.
func (tl *ThrottledLogger) Errorf(format string, v ...interface{}) {
tl.log(errorf, format, v...)
}