forked from ECSTeam/cloudfoundry-top-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
avgtracker.go
126 lines (106 loc) · 2.6 KB
/
avgtracker.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
114
115
116
117
118
119
120
121
122
123
124
125
126
package util
import (
//"strconv"
"time"
//"fmt"
"sync"
//"gopkg.in/eapache/queue.v1"
"github.com/eapache/queue"
//"github.com/kkellner/cloudfoundry-top-plugin/debug"
//"fmt"
)
/*
func main() {
//rateCounter := NewRateCounter(time.Minute)
avgTracker := NewAvgTracker(time.Second)
for i := 0; i < 9; i++ {
avgTracker.Incr(100)
time.Sleep(time.Millisecond * 50)
}
avgTracker.Incr(200)
fmt.Printf("Rate: %v\n", avgTracker.Rate())
fmt.Printf("Avg: %f\n", avgTracker.Avg())
}
*/
// A RateCounter is a thread-safe counter which returns the number of times
// 'Incr' has been called in the last interval
type AvgTracker struct {
//counter Counter
interval time.Duration
timeQueue *queue.Queue
valueQueue *queue.Queue
mu *sync.Mutex
totalValue int64
}
func AvgMultipleTrackers(trackers []*AvgTracker) float64 {
totalLen := 0
totalValue := int64(0)
//fmt.Printf("\n\n***** len: [%v] **** \n", len(trackers))
for _, tracker := range trackers {
//fmt.Printf("\n\n***** interval: [%v] **** \n", tracker)
//debug.Debug(msg)
//time.Sleep(10 * time.Second)
tracker.mu.Lock()
tracker.removeOld()
totalLen = totalLen + tracker.valueQueue.Length()
totalValue = totalValue + tracker.totalValue
tracker.mu.Unlock()
}
avg := float64(-1)
if totalLen > 0 {
avg = float64(totalValue) / float64(totalLen)
}
return avg
}
// Constructs a new RateCounter, for the interval provided
func NewAvgTracker(intrvl time.Duration) *AvgTracker {
return &AvgTracker {
interval: intrvl,
timeQueue: queue.New(),
valueQueue: queue.New(),
mu: &sync.Mutex{},
}
}
// Add an event into the RateCounter
func (r *AvgTracker) Track(val int64) {
r.mu.Lock()
r.removeOld()
r.totalValue = r.totalValue + val
r.timeQueue.Add(time.Now())
r.valueQueue.Add(val)
r.mu.Unlock()
}
// Return the current number of events in the last interval
func (r *AvgTracker) Rate() int {
r.mu.Lock()
r.removeOld()
len := r.timeQueue.Length()
r.mu.Unlock()
return len
}
func (r *AvgTracker) Avg() float64 {
r.mu.Lock()
r.removeOld()
len := r.valueQueue.Length()
avg := float64(-1)
if len > 0 {
avg = float64(r.totalValue) / float64(len)
}
r.mu.Unlock()
return avg
}
func (r *AvgTracker) removeOld() {
if r.timeQueue.Length() > 0 {
now := time.Now()
for r.timeQueue.Length() > 0 {
ts := r.timeQueue.Peek().(time.Time)
if now.Sub(ts) < r.interval {
break;
}
//fmt.Printf("Remove - Now:[%v] ts:[%v] len:%v\n", now, ts, r.queue.Length())
r.timeQueue.Remove()
oldValue := r.valueQueue.Remove().(int64)
r.totalValue = r.totalValue - oldValue
}
}
}