github.com/rudderlabs/rudder-go-kit@v0.30.0/stats/metric/gauge.go (about)

     1  package metric
     2  
     3  import (
     4  	"math"
     5  	"sync/atomic"
     6  	"time"
     7  )
     8  
     9  // Gauge keeps track of increasing/decreasing or generally arbitrary values.
    10  // You can even use a gauge to keep track of time, e.g. when was the last time
    11  // an event happened!
    12  type Gauge interface {
    13  	// Set sets the given value to the gauge.
    14  	Set(float64)
    15  	// Inc increments the gauge by 1. Use Add to increment it by arbitrary
    16  	// values.
    17  	Inc()
    18  	// Dec decrements the gauge by 1. Use Sub to decrement it by arbitrary
    19  	// values.
    20  	Dec()
    21  	// Add adds the given value to the counter.
    22  	Add(val float64)
    23  	// Sub subtracts the given value from the counter.
    24  	Sub(float64)
    25  	// SetToCurrentTime sets the current UNIX time as the gauge's value
    26  	SetToCurrentTime()
    27  	// Value gets the current value of the counter.
    28  	Value() float64
    29  	// IntValue gets the current value of the counter as an int.
    30  	IntValue() int
    31  	// ValueAsTime gets the current value of the counter as time.
    32  	ValueAsTime() time.Time
    33  }
    34  
    35  func NewGauge() Gauge {
    36  	result := &gauge{now: time.Now}
    37  	return result
    38  }
    39  
    40  type gauge struct {
    41  	valBits uint64
    42  
    43  	now func() time.Time // To mock out time.Now() for testing.
    44  }
    45  
    46  func (g *gauge) Set(val float64) {
    47  	atomic.StoreUint64(&g.valBits, math.Float64bits(val))
    48  }
    49  
    50  func (g *gauge) SetToCurrentTime() {
    51  	g.Set(float64(g.now().UnixNano()) / 1e9)
    52  }
    53  
    54  func (g *gauge) Inc() {
    55  	g.Add(1)
    56  }
    57  
    58  func (g *gauge) Dec() {
    59  	g.Add(-1)
    60  }
    61  
    62  func (g *gauge) Add(val float64) {
    63  	for {
    64  		oldBits := atomic.LoadUint64(&g.valBits)
    65  		newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
    66  		if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) {
    67  			return
    68  		}
    69  	}
    70  }
    71  
    72  func (g *gauge) Sub(val float64) {
    73  	g.Add(val * -1)
    74  }
    75  
    76  func (g *gauge) Value() float64 {
    77  	return math.Float64frombits(atomic.LoadUint64(&g.valBits))
    78  }
    79  
    80  func (g *gauge) IntValue() int {
    81  	return int(g.Value())
    82  }
    83  
    84  func (g *gauge) ValueAsTime() time.Time {
    85  	return time.Unix(0, int64(g.Value()*1e9))
    86  }