metrics: fix float64 gauge

This commit is contained in:
Martin Holst Swende 2024-11-26 20:59:11 +01:00
parent afaca63832
commit f27df5c6a5
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
10 changed files with 31 additions and 54 deletions

View file

@ -194,7 +194,7 @@ func (exp *exp) syncToExpvar() {
exp.publishCounterFloat64(name, i.Snapshot()) exp.publishCounterFloat64(name, i.Snapshot())
case *metrics.Gauge: case *metrics.Gauge:
exp.publishGauge(name, i.Snapshot()) exp.publishGauge(name, i.Snapshot())
case metrics.GaugeFloat64: case *metrics.GaugeFloat64:
exp.publishGaugeFloat64(name, i.Snapshot()) exp.publishGaugeFloat64(name, i.Snapshot())
case metrics.GaugeInfo: case metrics.GaugeInfo:
exp.publishGaugeInfo(name, i.Snapshot()) exp.publishGaugeInfo(name, i.Snapshot())

View file

@ -5,35 +5,28 @@ import (
"sync/atomic" "sync/atomic"
) )
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 // GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a
// new StandardGaugeFloat64. // new GaugeFloat64.
func GetOrRegisterGaugeFloat64(name string, r Registry) GaugeFloat64 { func GetOrRegisterGaugeFloat64(name string, r Registry) *GaugeFloat64 {
if nil == r { if nil == r {
r = DefaultRegistry r = DefaultRegistry
} }
return r.GetOrRegister(name, NewGaugeFloat64()).(GaugeFloat64) return r.GetOrRegister(name, NewGaugeFloat64()).(*GaugeFloat64)
} }
// NewGaugeFloat64 constructs a new StandardGaugeFloat64. // GaugeFloat64Snapshot is a read-only copy of a GaugeFloat64.
func NewGaugeFloat64() GaugeFloat64 { type GaugeFloat64Snapshot float64
if !Enabled {
return NilGaugeFloat64{} // Value returns the value at the time the snapshot was taken.
} func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) }
return &StandardGaugeFloat64{}
// NewGaugeFloat64 constructs a new GaugeFloat64.
func NewGaugeFloat64() *GaugeFloat64 {
return new(GaugeFloat64)
} }
// NewRegisteredGaugeFloat64 constructs and registers a new StandardGaugeFloat64. // NewRegisteredGaugeFloat64 constructs and registers a new GaugeFloat64.
func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 { func NewRegisteredGaugeFloat64(name string, r Registry) *GaugeFloat64 {
c := NewGaugeFloat64() c := NewGaugeFloat64()
if nil == r { if nil == r {
r = DefaultRegistry r = DefaultRegistry
@ -42,32 +35,16 @@ func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 {
return c return c
} }
// gaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. // GaugeFloat64 and uses atomic to manage a single float64 value.
type gaugeFloat64Snapshot float64 type GaugeFloat64 atomic.Uint64
// Value returns the value at the time the snapshot was taken.
func (g gaugeFloat64Snapshot) Value() float64 { return float64(g) }
// NilGaugeFloat64 is a no-op Gauge.
type NilGaugeFloat64 struct{}
func (NilGaugeFloat64) Snapshot() GaugeFloat64Snapshot { return NilGaugeFloat64{} }
func (NilGaugeFloat64) Update(v float64) {}
func (NilGaugeFloat64) Value() float64 { return 0.0 }
// StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses
// atomic to manage a single float64 value.
type StandardGaugeFloat64 struct {
floatBits atomic.Uint64
}
// Snapshot returns a read-only copy of the gauge. // Snapshot returns a read-only copy of the gauge.
func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64Snapshot { func (g *GaugeFloat64) Snapshot() GaugeFloat64Snapshot {
v := math.Float64frombits(g.floatBits.Load()) v := math.Float64frombits((*atomic.Uint64)(g).Load())
return gaugeFloat64Snapshot(v) return GaugeFloat64Snapshot(v)
} }
// Update updates the gauge's value. // Update updates the gauge's value.
func (g *StandardGaugeFloat64) Update(v float64) { func (g *GaugeFloat64) Update(v float64) {
g.floatBits.Store(math.Float64bits(v)) (*atomic.Uint64)(g).Store(math.Float64bits(v))
} }

View file

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

View file

@ -26,7 +26,7 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf
"value": metric.Snapshot().Value(), "value": metric.Snapshot().Value(),
} }
return measurement, fields return measurement, fields
case metrics.GaugeFloat64: case *metrics.GaugeFloat64:
measurement := fmt.Sprintf("%s%s.gauge", namespace, name) measurement := fmt.Sprintf("%s%s.gauge", namespace, name)
fields := map[string]interface{}{ fields := map[string]interface{}{
"value": metric.Snapshot().Value(), "value": metric.Snapshot().Value(),

View file

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

View file

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

View file

@ -57,7 +57,7 @@ func (c *collector) Add(name string, i any) error {
c.addCounterFloat64(name, m.Snapshot()) c.addCounterFloat64(name, m.Snapshot())
case *metrics.Gauge: case *metrics.Gauge:
c.addGauge(name, m.Snapshot()) c.addGauge(name, m.Snapshot())
case metrics.GaugeFloat64: case *metrics.GaugeFloat64:
c.addGaugeFloat64(name, m.Snapshot()) c.addGaugeFloat64(name, m.Snapshot())
case metrics.GaugeInfo: case metrics.GaugeInfo:
c.addGaugeInfo(name, m.Snapshot()) c.addGaugeInfo(name, m.Snapshot())

View file

@ -155,7 +155,7 @@ func (r *StandardRegistry) GetAll() map[string]map[string]interface{} {
values["count"] = metric.Snapshot().Count() values["count"] = metric.Snapshot().Count()
case *Gauge: case *Gauge:
values["value"] = metric.Snapshot().Value() values["value"] = metric.Snapshot().Value()
case GaugeFloat64: case *GaugeFloat64:
values["value"] = metric.Snapshot().Value() values["value"] = metric.Snapshot().Value()
case Healthcheck: case Healthcheck:
values["error"] = nil values["error"] = nil
@ -214,7 +214,7 @@ func (r *StandardRegistry) Unregister(name string) {
func (r *StandardRegistry) loadOrRegister(name string, i interface{}) (interface{}, bool, bool) { func (r *StandardRegistry) loadOrRegister(name string, i interface{}) (interface{}, bool, bool) {
switch i.(type) { switch i.(type) {
case *Counter, *CounterFloat64, *Gauge, GaugeFloat64, GaugeInfo, Healthcheck, Histogram, Meter, Timer, ResettingTimer: case *Counter, *CounterFloat64, *Gauge, *GaugeFloat64, GaugeInfo, Healthcheck, Histogram, Meter, Timer, ResettingTimer:
default: default:
return nil, false, false return nil, false, false
} }

View file

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

View file

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