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.
		
		
		
		
		
			
		
			
				
					
					
						
							94 lines
						
					
					
						
							2.0 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							94 lines
						
					
					
						
							2.0 KiB
						
					
					
				
								package stats
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"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
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								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) {
							 | 
						|
									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) {
							 | 
						|
									for _, val := range rrc.Values {
							 | 
						|
										if max < val {
							 | 
						|
											max = val
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return
							 | 
						|
								}
							 | 
						|
								func (rrc *RoundRobinCounter) Count() (cnt int64) {
							 | 
						|
									for _, c := range rrc.Counts {
							 | 
						|
										cnt += c
							 | 
						|
									}
							 | 
						|
									return
							 | 
						|
								}
							 | 
						|
								func (rrc *RoundRobinCounter) Sum() (sum int64) {
							 | 
						|
									for _, val := range rrc.Values {
							 | 
						|
										sum += val
							 | 
						|
									}
							 | 
						|
									return
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (rrc *RoundRobinCounter) ToList() (ret []int64) {
							 | 
						|
									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)
							 | 
						|
								}
							 |