gauge.go: add Inc, Dec and Add methods to Gauge
This commit is contained in:
parent
fdfd428a62
commit
da211e52b9
34
gauge.go
34
gauge.go
@ -17,7 +17,7 @@ import (
|
|||||||
// - foo{bar="baz",aaa="b"}
|
// - foo{bar="baz",aaa="b"}
|
||||||
//
|
//
|
||||||
// f must be safe for concurrent calls.
|
// f must be safe for concurrent calls.
|
||||||
// if f is nil, then it is expected that the gauge value is changed via Gauge.Set() call.
|
// if f is nil, then it is expected that the gauge value is changed via Set(), Inc(), Dec() and Add() calls.
|
||||||
//
|
//
|
||||||
// The returned gauge is safe to use from concurrent goroutines.
|
// The returned gauge is safe to use from concurrent goroutines.
|
||||||
//
|
//
|
||||||
@ -55,6 +55,38 @@ func (g *Gauge) Set(v float64) {
|
|||||||
atomic.StoreUint64(&g.valueBits, n)
|
atomic.StoreUint64(&g.valueBits, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inc increments g by 1.
|
||||||
|
//
|
||||||
|
// The g must be created with nil callback in order to be able to call this function.
|
||||||
|
func (g *Gauge) Inc() {
|
||||||
|
g.Add(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dec decrements g by 1.
|
||||||
|
//
|
||||||
|
// The g must be created with nil callback in order to be able to call this function.
|
||||||
|
func (g *Gauge) Dec() {
|
||||||
|
g.Add(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds fAdd to g. fAdd may be positive and negative.
|
||||||
|
//
|
||||||
|
// The g must be created with nil callback in order to be able to call this function.
|
||||||
|
func (g *Gauge) Add(fAdd float64) {
|
||||||
|
if g.f != nil {
|
||||||
|
panic(fmt.Errorf("cannot call Set on gauge created with non-nil callback"))
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
n := atomic.LoadUint64(&g.valueBits)
|
||||||
|
f := math.Float64frombits(n)
|
||||||
|
fNew := f + fAdd
|
||||||
|
nNew := math.Float64bits(fNew)
|
||||||
|
if atomic.CompareAndSwapUint64(&g.valueBits, n, nNew) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Gauge) marshalTo(prefix string, w io.Writer) {
|
func (g *Gauge) marshalTo(prefix string, w io.Writer) {
|
||||||
v := g.Get()
|
v := g.Get()
|
||||||
if float64(int64(v)) == v {
|
if float64(int64(v)) == v {
|
||||||
|
@ -15,6 +15,18 @@ func TestGaugeError(t *testing.T) {
|
|||||||
g := GetOrCreateGauge("GetOrCreateGauge_nil_callback", func() float64 { return 123 })
|
g := GetOrCreateGauge("GetOrCreateGauge_nil_callback", func() float64 { return 123 })
|
||||||
g.Set(42)
|
g.Set(42)
|
||||||
})
|
})
|
||||||
|
expectPanic(t, "GetOrCreateGauge_Add_non-nil-callback", func() {
|
||||||
|
g := GetOrCreateGauge("GetOrCreateGauge_nil_callback", func() float64 { return 123 })
|
||||||
|
g.Add(42)
|
||||||
|
})
|
||||||
|
expectPanic(t, "GetOrCreateGauge_Inc_non-nil-callback", func() {
|
||||||
|
g := GetOrCreateGauge("GetOrCreateGauge_nil_callback", func() float64 { return 123 })
|
||||||
|
g.Inc()
|
||||||
|
})
|
||||||
|
expectPanic(t, "GetOrCreateGauge_Dec_non-nil-callback", func() {
|
||||||
|
g := GetOrCreateGauge("GetOrCreateGauge_nil_callback", func() float64 { return 123 })
|
||||||
|
g.Dec()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGaugeSet(t *testing.T) {
|
func TestGaugeSet(t *testing.T) {
|
||||||
@ -29,6 +41,49 @@ func TestGaugeSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGaugeIncDec(t *testing.T) {
|
||||||
|
s := NewSet()
|
||||||
|
g := s.NewGauge("foo", nil)
|
||||||
|
if n := g.Get(); n != 0 {
|
||||||
|
t.Fatalf("unexpected gauge value: %g; expecting 0", n)
|
||||||
|
}
|
||||||
|
for i := 1; i <= 100; i++ {
|
||||||
|
g.Inc()
|
||||||
|
if n := g.Get(); n != float64(i) {
|
||||||
|
t.Fatalf("unexpected gauge value %g; expecting %d", n, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 99; i >= 0; i-- {
|
||||||
|
g.Dec()
|
||||||
|
if n := g.Get(); n != float64(i) {
|
||||||
|
t.Fatalf("unexpected gauge value %g; expecting %d", n, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGaugeIncDecConcurrenc(t *testing.T) {
|
||||||
|
s := NewSet()
|
||||||
|
g := s.NewGauge("foo", nil)
|
||||||
|
|
||||||
|
workers := 5
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < workers; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
g.Inc()
|
||||||
|
g.Dec()
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if n := g.Get(); n != 0 {
|
||||||
|
t.Fatalf("unexpected gauge value %g; want 0", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGaugeSerial(t *testing.T) {
|
func TestGaugeSerial(t *testing.T) {
|
||||||
name := "GaugeSerial"
|
name := "GaugeSerial"
|
||||||
n := 1.23
|
n := 1.23
|
||||||
|
Loading…
Reference in New Issue
Block a user