...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package v2stats
16
17 import (
18 "sync"
19 "time"
20 )
21
22 const (
23 queueCapacity = 200
24 )
25
26
27
28 type RequestStats struct {
29 SendingTime time.Time
30 Size int
31 }
32
33 type statsQueue struct {
34 items [queueCapacity]*RequestStats
35 size int
36 front int
37 back int
38 totalReqSize int
39 rwl sync.RWMutex
40 }
41
42 func (q *statsQueue) Len() int {
43 return q.size
44 }
45
46 func (q *statsQueue) ReqSize() int {
47 return q.totalReqSize
48 }
49
50
51
52 func (q *statsQueue) frontAndBack() (*RequestStats, *RequestStats) {
53 q.rwl.RLock()
54 defer q.rwl.RUnlock()
55 if q.size != 0 {
56 return q.items[q.front], q.items[q.back]
57 }
58 return nil, nil
59 }
60
61
62 func (q *statsQueue) Insert(p *RequestStats) {
63 q.rwl.Lock()
64 defer q.rwl.Unlock()
65
66 q.back = (q.back + 1) % queueCapacity
67
68 if q.size == queueCapacity {
69 q.totalReqSize -= q.items[q.front].Size
70 q.front = (q.back + 1) % queueCapacity
71 } else {
72 q.size++
73 }
74
75 q.items[q.back] = p
76 q.totalReqSize += q.items[q.back].Size
77
78 }
79
80
81 func (q *statsQueue) Rate() (float64, float64) {
82 front, back := q.frontAndBack()
83
84 if front == nil || back == nil {
85 return 0, 0
86 }
87
88 if time.Since(back.SendingTime) > time.Second {
89 q.Clear()
90 return 0, 0
91 }
92
93 sampleDuration := back.SendingTime.Sub(front.SendingTime)
94
95 pr := float64(q.Len()) / float64(sampleDuration) * float64(time.Second)
96
97 br := float64(q.ReqSize()) / float64(sampleDuration) * float64(time.Second)
98
99 return pr, br
100 }
101
102
103 func (q *statsQueue) Clear() {
104 q.rwl.Lock()
105 defer q.rwl.Unlock()
106 q.back = -1
107 q.front = 0
108 q.size = 0
109 q.totalReqSize = 0
110 }
111
View as plain text