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 }