forked from abh/geodns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zone_stats.go
113 lines (95 loc) · 1.92 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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package main
import (
"sort"
)
type zoneLabelStats struct {
pos int
rotated bool
log []string
in chan string
out chan []string
reset chan bool
close chan bool
}
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),
in: make(chan string, 100),
out: make(chan []string),
reset: make(chan bool),
close: make(chan bool),
}
go zs.receiver()
return zs
}
func (zs *zoneLabelStats) receiver() {
for {
select {
case new := <-zs.in:
zs.add(new)
case zs.out <- zs.log:
case <-zs.reset:
zs.pos = 0
zs.log = make([]string, len(zs.log))
zs.rotated = false
case <-zs.close:
close(zs.in)
return
}
}
}
func (zs *zoneLabelStats) Close() {
zs.close <- true
}
func (zs *zoneLabelStats) Reset() {
zs.reset <- true
}
func (zs *zoneLabelStats) Add(l string) {
zs.in <- l
}
func (zs *zoneLabelStats) add(l string) {
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 {
log := (<-zs.out)
counts := make(map[string]int)
for i, l := range log {
if zs.rotated == false && i >= zs.pos {
break
}
counts[l]++
}
return counts
}