github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/monitor/stats/counter.go (about)

     1  /*
     2   *
     3   * Copyright 2017 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * 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  
    19  // Copyright (c) 2015 Arista Networks, Inc.
    20  // Use of this source code is governed by the Apache License 2.0
    21  // that can be found in the COPYING file.
    22  
    23  package stats
    24  
    25  import (
    26  	"sync"
    27  	"time"
    28  )
    29  
    30  var (
    31  	// TimeNow is used for testing.
    32  	TimeNow = time.Now
    33  )
    34  
    35  const (
    36  	hour       = 0
    37  	tenminutes = 1
    38  	minute     = 2
    39  )
    40  
    41  // Counter is a counter that keeps track of its recent values over a given
    42  // period of time, and with a given resolution. Use newCounter() to instantiate.
    43  type Counter struct {
    44  	mu         sync.RWMutex
    45  	ts         [3]*timeseries
    46  	lastUpdate time.Time
    47  }
    48  
    49  // newCounter returns a new Counter.
    50  func newCounter() *Counter {
    51  	now := TimeNow()
    52  	c := &Counter{}
    53  	c.ts[hour] = newTimeSeries(now, time.Hour, time.Minute)
    54  	c.ts[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second)
    55  	c.ts[minute] = newTimeSeries(now, time.Minute, time.Second)
    56  	return c
    57  }
    58  
    59  func (c *Counter) advance() time.Time {
    60  	now := TimeNow()
    61  	for _, ts := range c.ts {
    62  		ts.advanceTime(now)
    63  	}
    64  	return now
    65  }
    66  
    67  // Value returns the current value of the counter.
    68  func (c *Counter) Value() int64 {
    69  	c.mu.RLock()
    70  	defer c.mu.RUnlock()
    71  	return c.ts[minute].headValue()
    72  }
    73  
    74  // LastUpdate returns the last update time of the counter.
    75  func (c *Counter) LastUpdate() time.Time {
    76  	c.mu.RLock()
    77  	defer c.mu.RUnlock()
    78  	return c.lastUpdate
    79  }
    80  
    81  // Set updates the current value of the counter.
    82  func (c *Counter) Set(value int64) {
    83  	c.mu.Lock()
    84  	defer c.mu.Unlock()
    85  	c.lastUpdate = c.advance()
    86  	for _, ts := range c.ts {
    87  		ts.set(value)
    88  	}
    89  }
    90  
    91  // Incr increments the current value of the counter by 'delta'.
    92  func (c *Counter) Incr(delta int64) {
    93  	c.mu.Lock()
    94  	defer c.mu.Unlock()
    95  	c.lastUpdate = c.advance()
    96  	for _, ts := range c.ts {
    97  		ts.incr(delta)
    98  	}
    99  }
   100  
   101  // Delta1h returns the delta for the last hour.
   102  func (c *Counter) Delta1h() int64 {
   103  	c.mu.RLock()
   104  	defer c.mu.RUnlock()
   105  	c.advance()
   106  	return c.ts[hour].delta()
   107  }
   108  
   109  // Delta10m returns the delta for the last 10 minutes.
   110  func (c *Counter) Delta10m() int64 {
   111  	c.mu.RLock()
   112  	defer c.mu.RUnlock()
   113  	c.advance()
   114  	return c.ts[tenminutes].delta()
   115  }
   116  
   117  // Delta1m returns the delta for the last minute.
   118  func (c *Counter) Delta1m() int64 {
   119  	c.mu.RLock()
   120  	defer c.mu.RUnlock()
   121  	c.advance()
   122  	return c.ts[minute].delta()
   123  }
   124  
   125  // Rate1h returns the rate of change of the counter in the last hour.
   126  func (c *Counter) Rate1h() float64 {
   127  	c.mu.RLock()
   128  	defer c.mu.RUnlock()
   129  	c.advance()
   130  	return c.ts[hour].rate()
   131  }
   132  
   133  // Rate10m returns the rate of change of the counter in the last 10 minutes.
   134  func (c *Counter) Rate10m() float64 {
   135  	c.mu.RLock()
   136  	defer c.mu.RUnlock()
   137  	c.advance()
   138  	return c.ts[tenminutes].rate()
   139  }
   140  
   141  // Rate1m returns the rate of change of the counter in the last minute.
   142  func (c *Counter) Rate1m() float64 {
   143  	c.mu.RLock()
   144  	defer c.mu.RUnlock()
   145  	c.advance()
   146  	return c.ts[minute].rate()
   147  }
   148  
   149  // Reset resets the counter to an empty state.
   150  func (c *Counter) Reset() {
   151  	c.mu.Lock()
   152  	defer c.mu.Unlock()
   153  	now := TimeNow()
   154  	for _, ts := range c.ts {
   155  		ts.reset(now)
   156  	}
   157  }