blob: 2c3dff3d0ffc5e7ed0ae3155686da21ac9811ece [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001// Copyright 2015 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package v2stats
16
17import (
18 "sync"
19 "time"
20)
21
22const (
23 queueCapacity = 200
24)
25
26// RequestStats represent the stats for a request.
27// It encapsulates the sending time and the size of the request.
28type RequestStats struct {
29 SendingTime time.Time
30 Size int
31}
32
33type statsQueue struct {
34 items [queueCapacity]*RequestStats
35 size int
36 front int
37 back int
38 totalReqSize int
39 rwl sync.RWMutex
40}
41
42func (q *statsQueue) Len() int {
43 return q.size
44}
45
46func (q *statsQueue) ReqSize() int {
47 return q.totalReqSize
48}
49
50// FrontAndBack gets the front and back elements in the queue
51// We must grab front and back together with the protection of the lock
52func (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// Insert function insert a RequestStats into the queue and update the records
62func (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 { //dequeue
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// Rate function returns the package rate and byte rate
81func (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// Clear function clear up the statsQueue
103func (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}