zone_stats.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package main
  2. import (
  3. "sort"
  4. )
  5. type zoneLabelStats struct {
  6. pos int
  7. rotated bool
  8. log []string
  9. in chan string
  10. out chan []string
  11. reset chan bool
  12. close chan bool
  13. }
  14. type labelStats []labelStat
  15. func (s labelStats) Len() int { return len(s) }
  16. func (s labelStats) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  17. type labelStatsByCount struct{ labelStats }
  18. func (s labelStatsByCount) Less(i, j int) bool { return s.labelStats[i].Count > s.labelStats[j].Count }
  19. type labelStat struct {
  20. Label string
  21. Count int
  22. }
  23. func NewZoneLabelStats(size int) *zoneLabelStats {
  24. zs := &zoneLabelStats{
  25. log: make([]string, size),
  26. in: make(chan string, 100),
  27. out: make(chan []string),
  28. reset: make(chan bool),
  29. close: make(chan bool),
  30. }
  31. go zs.receiver()
  32. return zs
  33. }
  34. func (zs *zoneLabelStats) receiver() {
  35. for {
  36. select {
  37. case new := <-zs.in:
  38. zs.add(new)
  39. case zs.out <- zs.log:
  40. case <-zs.reset:
  41. zs.pos = 0
  42. zs.log = make([]string, len(zs.log))
  43. zs.rotated = false
  44. case <-zs.close:
  45. close(zs.in)
  46. return
  47. }
  48. }
  49. }
  50. func (zs *zoneLabelStats) Close() {
  51. zs.close <- true
  52. }
  53. func (zs *zoneLabelStats) Reset() {
  54. zs.reset <- true
  55. }
  56. func (zs *zoneLabelStats) Add(l string) {
  57. zs.in <- l
  58. }
  59. func (zs *zoneLabelStats) add(l string) {
  60. zs.log[zs.pos] = l
  61. zs.pos++
  62. if zs.pos+1 > len(zs.log) {
  63. zs.rotated = true
  64. zs.pos = 0
  65. }
  66. }
  67. func (zs *zoneLabelStats) TopCounts(n int) labelStats {
  68. cm := zs.Counts()
  69. top := make(labelStats, len(cm))
  70. i := 0
  71. for l, c := range cm {
  72. top[i] = labelStat{l, c}
  73. i++
  74. }
  75. sort.Sort(labelStatsByCount{top})
  76. if len(top) > n {
  77. others := 0
  78. for _, t := range top[n:] {
  79. others += t.Count
  80. }
  81. top = append(top[:n], labelStat{"Others", others})
  82. }
  83. return top
  84. }
  85. func (zs *zoneLabelStats) Counts() map[string]int {
  86. log := (<-zs.out)
  87. counts := make(map[string]int)
  88. for i, l := range log {
  89. if zs.rotated == false && i >= zs.pos {
  90. break
  91. }
  92. counts[l]++
  93. }
  94. return counts
  95. }