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  }