dubbo.apache.org/dubbo-go/v3@v3.1.1/metrics/util/aggregate/counter.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package aggregate 19 20 import ( 21 "sync" 22 "time" 23 ) 24 25 // TimeWindowCounter wrappers sliding window around a counter. 26 // 27 // It is concurrent-safe. 28 // When it works for calculating QPS, the counter's value means the number of requests in a pane. 29 type TimeWindowCounter struct { 30 window *slidingWindow 31 mux sync.RWMutex 32 } 33 34 func NewTimeWindowCounter(paneCount int, timeWindowSeconds int64) *TimeWindowCounter { 35 return &TimeWindowCounter{ 36 window: newSlidingWindow(paneCount, timeWindowSeconds*1000), 37 } 38 } 39 40 // Count returns the sum of all panes' value. 41 func (t *TimeWindowCounter) Count() float64 { 42 t.mux.RLock() 43 defer t.mux.RUnlock() 44 45 total := float64(0) 46 for _, v := range t.window.values(time.Now().UnixMilli()) { 47 total += v.(*counter).value 48 } 49 return total 50 } 51 52 // LivedSeconds returns the lived seconds of the sliding window. 53 func (t *TimeWindowCounter) LivedSeconds() int64 { 54 t.mux.RLock() 55 defer t.mux.RUnlock() 56 57 windowLength := len(t.window.values(time.Now().UnixMilli())) 58 return int64(windowLength) * t.window.paneIntervalInMs / 1000 59 } 60 61 // Add adds a step to the counter. 62 func (t *TimeWindowCounter) Add(step float64) { 63 t.mux.Lock() 64 defer t.mux.Unlock() 65 66 t.window.currentPane(time.Now().UnixMilli(), t.newEmptyValue).value.(*counter).add(step) 67 } 68 69 // Inc increments the counter by 1. 70 func (t *TimeWindowCounter) Inc() { 71 t.Add(1) 72 } 73 74 func (t *TimeWindowCounter) newEmptyValue() interface{} { 75 return &counter{0} 76 } 77 78 type counter struct { 79 value float64 80 } 81 82 func (c *counter) add(v float64) { 83 c.value += v 84 }