metrics: split gaugefloat64 interface

This commit is contained in:
Martin Holst Swende 2023-08-31 11:56:08 +02:00
parent b7f8d9b4ce
commit 36c31a691a
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
12 changed files with 41 additions and 100 deletions

View file

@ -123,7 +123,7 @@ func (exp *exp) publishGauge(name string, metric metrics.GaugeSnapshot) {
v := exp.getInt(name)
v.Set(metric.Value())
}
func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64) {
func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64Snapshot) {
exp.getFloat(name).Set(metric.Value())
}
@ -195,7 +195,7 @@ func (exp *exp) syncToExpvar() {
case metrics.Gauge:
exp.publishGauge(name, i.Snapshot())
case metrics.GaugeFloat64:
exp.publishGaugeFloat64(name, i)
exp.publishGaugeFloat64(name, i.Snapshot())
case metrics.GaugeInfo:
exp.publishGaugeInfo(name, i)
case metrics.Histogram:

View file

@ -5,13 +5,16 @@ import (
"sync/atomic"
)
// GaugeFloat64s hold a float64 value that can be set arbitrarily.
type GaugeFloat64 interface {
Snapshot() GaugeFloat64
Update(float64)
type GaugeFloat64Snapshot interface {
Value() float64
}
// GaugeFloat64 hold a float64 value that can be set arbitrarily.
type GaugeFloat64 interface {
Snapshot() GaugeFloat64Snapshot
Update(float64)
}
// GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a
// new StandardGaugeFloat64.
func GetOrRegisterGaugeFloat64(name string, r Registry) GaugeFloat64 {
@ -39,43 +42,17 @@ func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 {
return c
}
// NewFunctionalGauge constructs a new FunctionalGauge.
func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 {
if !Enabled {
return NilGaugeFloat64{}
}
return &FunctionalGaugeFloat64{value: f}
}
// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge.
func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 {
c := NewFunctionalGaugeFloat64(f)
if nil == r {
r = DefaultRegistry
}
r.Register(name, c)
return c
}
// GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64.
type GaugeFloat64Snapshot float64
// Snapshot returns the snapshot.
func (g GaugeFloat64Snapshot) Snapshot() GaugeFloat64 { return g }
// Update panics.
func (GaugeFloat64Snapshot) Update(float64) {
panic("Update called on a GaugeFloat64Snapshot")
}
// gaugeFloat64Snapshot is a read-only copy of another GaugeFloat64.
type gaugeFloat64Snapshot float64
// Value returns the value at the time the snapshot was taken.
func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) }
func (g gaugeFloat64Snapshot) Value() float64 { return float64(g) }
// NilGauge is a no-op Gauge.
type NilGaugeFloat64 struct{}
// Snapshot is a no-op.
func (NilGaugeFloat64) Snapshot() GaugeFloat64 { return NilGaugeFloat64{} }
func (NilGaugeFloat64) Snapshot() GaugeFloat64Snapshot { return NilGaugeFloat64{} }
// Update is a no-op.
func (NilGaugeFloat64) Update(v float64) {}
@ -90,34 +67,12 @@ type StandardGaugeFloat64 struct {
}
// Snapshot returns a read-only copy of the gauge.
func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 {
return GaugeFloat64Snapshot(g.Value())
func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64Snapshot {
v := math.Float64frombits(g.floatBits.Load())
return gaugeFloat64Snapshot(v)
}
// Update updates the gauge's value.
func (g *StandardGaugeFloat64) Update(v float64) {
g.floatBits.Store(math.Float64bits(v))
}
// Value returns the gauge's current value.
func (g *StandardGaugeFloat64) Value() float64 {
return math.Float64frombits(g.floatBits.Load())
}
// FunctionalGaugeFloat64 returns value from given function
type FunctionalGaugeFloat64 struct {
value func() float64
}
// Value returns the gauge's current value.
func (g FunctionalGaugeFloat64) Value() float64 {
return g.value()
}
// Snapshot returns the snapshot.
func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) }
// Update panics.
func (FunctionalGaugeFloat64) Update(float64) {
panic("Update called on a FunctionalGaugeFloat64")
}

View file

@ -26,19 +26,11 @@ func BenchmarkGaugeFloat64Parallel(b *testing.B) {
}()
}
wg.Wait()
if have, want := c.Value(), float64(b.N-1); have != want {
if have, want := c.Snapshot().Value(), float64(b.N-1); have != want {
b.Fatalf("have %f want %f", have, want)
}
}
func TestGaugeFloat64(t *testing.T) {
g := NewGaugeFloat64()
g.Update(47.0)
if v := g.Value(); 47.0 != v {
t.Errorf("g.Value(): 47.0 != %v\n", v)
}
}
func TestGaugeFloat64Snapshot(t *testing.T) {
g := NewGaugeFloat64()
g.Update(47.0)
@ -53,28 +45,7 @@ func TestGetOrRegisterGaugeFloat64(t *testing.T) {
r := NewRegistry()
NewRegisteredGaugeFloat64("foo", r).Update(47.0)
t.Logf("registry: %v", r)
if g := GetOrRegisterGaugeFloat64("foo", r); 47.0 != g.Value() {
t.Fatal(g)
}
}
func TestFunctionalGaugeFloat64(t *testing.T) {
var counter float64
fg := NewFunctionalGaugeFloat64(func() float64 {
counter++
return counter
})
fg.Value()
fg.Value()
if counter != 2 {
t.Error("counter != 2")
}
}
func TestGetOrRegisterFunctionalGaugeFloat64(t *testing.T) {
r := NewRegistry()
NewRegisteredFunctionalGaugeFloat64("foo", r, func() float64 { return 47 })
if g := GetOrRegisterGaugeFloat64("foo", r); g.Value() != 47 {
if g := GetOrRegisterGaugeFloat64("foo", r).Snapshot(); 47.0 != g.Value() {
t.Fatal(g)
}
}

View file

@ -72,7 +72,7 @@ func graphite(c *GraphiteConfig) error {
case Gauge:
fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Snapshot().Value(), now)
case GaugeFloat64:
fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now)
fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Snapshot().Value(), now)
case GaugeInfo:
fmt.Fprintf(w, "%s.%s.value %s %d\n", c.Prefix, name, metric.Value().String(), now)
case Histogram:

View file

@ -32,7 +32,7 @@ func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {
l.Printf(" value: %9d\n", metric.Snapshot().Value())
case GaugeFloat64:
l.Printf("gauge %s\n", name)
l.Printf(" value: %f\n", metric.Value())
l.Printf(" value: %f\n", metric.Snapshot().Value())
case GaugeInfo:
l.Printf("gauge %s\n", name)
l.Printf(" value: %s\n", metric.Value())

View file

@ -71,7 +71,7 @@ func (c *OpenTSDBConfig) writeRegistry(w io.Writer, now int64, shortHostname str
case Gauge:
fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Snapshot().Value(), shortHostname)
case GaugeFloat64:
fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Snapshot().Value(), shortHostname)
case GaugeInfo:
fmt.Fprintf(w, "put %s.%s.value %d %s host=%s\n", c.Prefix, name, now, metric.Value().String(), shortHostname)
case Histogram:

View file

@ -1,6 +1,7 @@
package metrics
import (
"fmt"
"net"
"os"
"strings"
@ -47,5 +48,19 @@ func TestExampleOpenTSB(t *testing.T) {
}
if have, want := w.String(), string(wantB); have != want {
t.Errorf("\nhave:\n%v\nwant:\n%v\n", have, want)
t.Logf("have vs want:\n%v", findFirstDiffPos(have, want))
}
}
func findFirstDiffPos(a, b string) string {
yy := strings.Split(b, "\n")
for i, x := range strings.Split(a, "\n") {
if i >= len(yy) {
return fmt.Sprintf("have:%d: %s\nwant:%d: <EOF>", i, x, i)
}
if y := yy[i]; x != y {
return fmt.Sprintf("have:%d: %s\nwant:%d: %s", i, x, i, y)
}
}
return ""
}

View file

@ -87,7 +87,7 @@ func (c *collector) addGauge(name string, m metrics.GaugeSnapshot) {
c.writeGaugeCounter(name, m.Value())
}
func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64) {
func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64Snapshot) {
c.writeGaugeCounter(name, m.Value())
}

View file

@ -156,7 +156,7 @@ func (r *StandardRegistry) GetAll() map[string]map[string]interface{} {
case Gauge:
values["value"] = metric.Snapshot().Value()
case GaugeFloat64:
values["value"] = metric.Value()
values["value"] = metric.Snapshot().Value()
case Healthcheck:
values["error"] = nil
metric.Check()

View file

@ -22,7 +22,7 @@ func Syslog(r Registry, d time.Duration, w *syslog.Writer) {
case Gauge:
w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Snapshot().Value()))
case GaugeFloat64:
w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value()))
w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Snapshot().Value()))
case GaugeInfo:
w.Info(fmt.Sprintf("gauge %s: value: %s", name, metric.Value()))
case Healthcheck:

View file

@ -1,4 +1,4 @@
put pre.elite.count 978307200 0 host=hal9000
put pre.elite.count 978307200 1337 host=hal9000
put pre.elite.one-minute 978307200 0.00 host=hal9000
put pre.elite.five-minute 978307200 0.00 host=hal9000
put pre.elite.fifteen-minute 978307200 0.00 host=hal9000

View file

@ -38,7 +38,7 @@ func WriteOnce(r Registry, w io.Writer) {
fmt.Fprintf(w, " value: %9d\n", metric.Snapshot().Value())
case GaugeFloat64:
fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
fmt.Fprintf(w, " value: %f\n", metric.Value())
fmt.Fprintf(w, " value: %f\n", metric.Snapshot().Value())
case GaugeInfo:
fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
fmt.Fprintf(w, " value: %s\n", metric.Value().String())