zone_stats.go 1.6 KB

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