123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- 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
- }
|