You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

106 lines
2.2 KiB

package stats
import (
"sync"
"time"
)
type TimedValue struct {
t time.Time
val int64
}
func NewTimedValue(t time.Time, val int64) *TimedValue {
return &TimedValue{t: t, val: val}
}
type RoundRobinCounter struct {
lastIndex int
values []int64
counts []int64
mutex sync.RWMutex
}
func NewRoundRobinCounter(slots int) *RoundRobinCounter {
return &RoundRobinCounter{lastIndex: -1, values: make([]int64, slots), counts: make([]int64, slots)}
}
func (rrc *RoundRobinCounter) Add(index int, val int64) {
rrc.mutex.Lock()
defer rrc.mutex.Unlock()
if index >= len(rrc.values) {
return
}
for rrc.lastIndex != index {
rrc.lastIndex = (rrc.lastIndex + 1) % len(rrc.values)
rrc.values[rrc.lastIndex] = 0
rrc.counts[rrc.lastIndex] = 0
}
rrc.values[index] += val
rrc.counts[index]++
}
func (rrc *RoundRobinCounter) Max() (max int64) {
rrc.mutex.RLock()
defer rrc.mutex.RUnlock()
for _, val := range rrc.values {
if max < val {
max = val
}
}
return
}
func (rrc *RoundRobinCounter) Count() (cnt int64) {
rrc.mutex.RLock()
defer rrc.mutex.RUnlock()
for _, c := range rrc.counts {
cnt += c
}
return
}
func (rrc *RoundRobinCounter) Sum() (sum int64) {
rrc.mutex.RLock()
defer rrc.mutex.RUnlock()
for _, val := range rrc.values {
sum += val
}
return
}
func (rrc *RoundRobinCounter) ToList() (ret []int64) {
rrc.mutex.RLock()
defer rrc.mutex.RUnlock()
index := rrc.lastIndex
step := len(rrc.values)
for step > 0 {
step--
index++
if index >= len(rrc.values) {
index = 0
}
ret = append(ret, rrc.values[index])
}
return
}
type DurationCounter struct {
MinuteCounter *RoundRobinCounter
HourCounter *RoundRobinCounter
DayCounter *RoundRobinCounter
WeekCounter *RoundRobinCounter
}
func NewDurationCounter() *DurationCounter {
return &DurationCounter{
MinuteCounter: NewRoundRobinCounter(60),
HourCounter: NewRoundRobinCounter(60),
DayCounter: NewRoundRobinCounter(24),
WeekCounter: NewRoundRobinCounter(7),
}
}
// Add is for cumulative counts
func (sc *DurationCounter) Add(tv *TimedValue) {
sc.MinuteCounter.Add(tv.t.Second(), tv.val)
sc.HourCounter.Add(tv.t.Minute(), tv.val)
sc.DayCounter.Add(tv.t.Hour(), tv.val)
sc.WeekCounter.Add(int(tv.t.Weekday()), tv.val)
}