mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
111 lines
2.5 KiB
Go
111 lines
2.5 KiB
Go
// Copyright 2015 The etcd Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package v2stats
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
queueCapacity = 200
|
|
)
|
|
|
|
// RequestStats represent the stats for a request.
|
|
// It encapsulates the sending time and the size of the request.
|
|
type RequestStats struct {
|
|
SendingTime time.Time
|
|
Size int
|
|
}
|
|
|
|
type statsQueue struct {
|
|
items [queueCapacity]*RequestStats
|
|
size int
|
|
front int
|
|
back int
|
|
totalReqSize int
|
|
rwl sync.RWMutex
|
|
}
|
|
|
|
func (q *statsQueue) Len() int {
|
|
return q.size
|
|
}
|
|
|
|
func (q *statsQueue) ReqSize() int {
|
|
return q.totalReqSize
|
|
}
|
|
|
|
// FrontAndBack gets the front and back elements in the queue
|
|
// We must grab front and back together with the protection of the lock
|
|
func (q *statsQueue) frontAndBack() (*RequestStats, *RequestStats) {
|
|
q.rwl.RLock()
|
|
defer q.rwl.RUnlock()
|
|
if q.size != 0 {
|
|
return q.items[q.front], q.items[q.back]
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
// Insert function insert a RequestStats into the queue and update the records
|
|
func (q *statsQueue) Insert(p *RequestStats) {
|
|
q.rwl.Lock()
|
|
defer q.rwl.Unlock()
|
|
|
|
q.back = (q.back + 1) % queueCapacity
|
|
|
|
if q.size == queueCapacity { //dequeue
|
|
q.totalReqSize -= q.items[q.front].Size
|
|
q.front = (q.back + 1) % queueCapacity
|
|
} else {
|
|
q.size++
|
|
}
|
|
|
|
q.items[q.back] = p
|
|
q.totalReqSize += q.items[q.back].Size
|
|
|
|
}
|
|
|
|
// Rate function returns the package rate and byte rate
|
|
func (q *statsQueue) Rate() (float64, float64) {
|
|
front, back := q.frontAndBack()
|
|
|
|
if front == nil || back == nil {
|
|
return 0, 0
|
|
}
|
|
|
|
if time.Since(back.SendingTime) > time.Second {
|
|
q.Clear()
|
|
return 0, 0
|
|
}
|
|
|
|
sampleDuration := back.SendingTime.Sub(front.SendingTime)
|
|
|
|
pr := float64(q.Len()) / float64(sampleDuration) * float64(time.Second)
|
|
|
|
br := float64(q.ReqSize()) / float64(sampleDuration) * float64(time.Second)
|
|
|
|
return pr, br
|
|
}
|
|
|
|
// Clear function clear up the statsQueue
|
|
func (q *statsQueue) Clear() {
|
|
q.rwl.Lock()
|
|
defer q.rwl.Unlock()
|
|
q.back = -1
|
|
q.front = 0
|
|
q.size = 0
|
|
q.totalReqSize = 0
|
|
}
|