forked from abh/geodns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathzone_stats.go
95 lines (79 loc) · 1.62 KB
/
zone_stats.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
package main
import (
"sort"
"sync"
)
type zoneLabelStats struct {
pos int
rotated bool
log []string
mu sync.Mutex
}
type labelStats []labelStat
func (s labelStats) Len() int { return len(s) }
func (s labelStats) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
type labelStatsByCount struct{ labelStats }
func (s labelStatsByCount) Less(i, j int) bool { return s.labelStats[i].Count > s.labelStats[j].Count }
type labelStat struct {
Label string
Count int
}
func NewZoneLabelStats(size int) *zoneLabelStats {
zs := &zoneLabelStats{
log: make([]string, size),
}
return zs
}
func (zs *zoneLabelStats) Close() {
zs.log = []string{}
}
func (zs *zoneLabelStats) Reset() {
zs.mu.Lock()
defer zs.mu.Unlock()
zs.pos = 0
zs.log = make([]string, len(zs.log))
zs.rotated = false
}
func (zs *zoneLabelStats) Add(l string) {
zs.add(l)
}
func (zs *zoneLabelStats) add(l string) {
zs.mu.Lock()
defer zs.mu.Unlock()
zs.log[zs.pos] = l
zs.pos++
if zs.pos+1 > len(zs.log) {
zs.rotated = true
zs.pos = 0
}
}
func (zs *zoneLabelStats) TopCounts(n int) labelStats {
cm := zs.Counts()
top := make(labelStats, len(cm))
i := 0
for l, c := range cm {
top[i] = labelStat{l, c}
i++
}
sort.Sort(labelStatsByCount{top})
if len(top) > n {
others := 0
for _, t := range top[n:] {
others += t.Count
}
top = append(top[:n], labelStat{"Others", others})
}
return top
}
func (zs *zoneLabelStats) Counts() map[string]int {
zs.mu.Lock()
defer zs.mu.Unlock()
counts := make(map[string]int)
for i, l := range zs.log {
if zs.rotated == false && i >= zs.pos {
break
}
counts[l]++
}
return counts
}