Skip to content

Commit

Permalink
metrics: split gaugeinfo into read/write
Browse files Browse the repository at this point in the history
  • Loading branch information
holiman committed Aug 31, 2023
1 parent 0abadec commit f4d0f94
Show file tree
Hide file tree
Showing 9 changed files with 28 additions and 126 deletions.
4 changes: 2 additions & 2 deletions metrics/exp/exp.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64Snap
exp.getFloat(name).Set(metric.Value())
}

func (exp *exp) publishGaugeInfo(name string, metric metrics.GaugeInfo) {
func (exp *exp) publishGaugeInfo(name string, metric metrics.GaugeInfoSnapshot) {
exp.getInfo(name).Set(metric.Value().String())
}

Expand Down Expand Up @@ -197,7 +197,7 @@ func (exp *exp) syncToExpvar() {
case metrics.GaugeFloat64:
exp.publishGaugeFloat64(name, i.Snapshot())
case metrics.GaugeInfo:
exp.publishGaugeInfo(name, i)
exp.publishGaugeInfo(name, i.Snapshot())
case metrics.Histogram:
exp.publishHistogram(name, i)
case metrics.Meter:
Expand Down
88 changes: 14 additions & 74 deletions metrics/gauge_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import (
"sync"
)

type GaugeInfoSnapshot interface {
Value() GaugeInfoValue
}

// GaugeInfos hold a GaugeInfoValue value that can be set arbitrarily.
type GaugeInfo interface {
Snapshot() GaugeInfo
Update(GaugeInfoValue)
Value() GaugeInfoValue
Snapshot() GaugeInfoSnapshot
}

// GaugeInfoValue is a mappng of (string) keys to (string) values
// GaugeInfoValue is a mapping of keys to values
type GaugeInfoValue map[string]string

func (val GaugeInfoValue) String() string {
Expand Down Expand Up @@ -49,49 +52,17 @@ func NewRegisteredGaugeInfo(name string, r Registry) GaugeInfo {
return c
}

// NewFunctionalGauge constructs a new FunctionalGauge.
func NewFunctionalGaugeInfo(f func() GaugeInfoValue) GaugeInfo {
if !Enabled {
return NilGaugeInfo{}
}
return &FunctionalGaugeInfo{value: f}
}

// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge.
func NewRegisteredFunctionalGaugeInfo(name string, r Registry, f func() GaugeInfoValue) GaugeInfo {
c := NewFunctionalGaugeInfo(f)
if nil == r {
r = DefaultRegistry
}
r.Register(name, c)
return c
}

// GaugeInfoSnapshot is a read-only copy of another GaugeInfo.
type GaugeInfoSnapshot GaugeInfoValue

// Snapshot returns the snapshot.
func (g GaugeInfoSnapshot) Snapshot() GaugeInfo { return g }

// Update panics.
func (GaugeInfoSnapshot) Update(GaugeInfoValue) {
panic("Update called on a GaugeInfoSnapshot")
}
// gaugeInfoSnapshot is a read-only copy of another GaugeInfo.
type gaugeInfoSnapshot GaugeInfoValue

// Value returns the value at the time the snapshot was taken.
func (g GaugeInfoSnapshot) Value() GaugeInfoValue { return GaugeInfoValue(g) }
func (g gaugeInfoSnapshot) Value() GaugeInfoValue { return GaugeInfoValue(g) }

// NilGauge is a no-op Gauge.
type NilGaugeInfo struct{}

// Snapshot is a no-op.
func (NilGaugeInfo) Snapshot() GaugeInfo { return NilGaugeInfo{} }

// Update is a no-op.
func (NilGaugeInfo) Update(v GaugeInfoValue) {}

// Value is a no-op.
func (NilGaugeInfo) Value() GaugeInfoValue { return GaugeInfoValue{} }
func (NilGaugeInfo) Snapshot() GaugeInfoSnapshot { return NilGaugeInfo{} }
func (NilGaugeInfo) Update(v GaugeInfoValue) {}
func (NilGaugeInfo) Value() GaugeInfoValue { return GaugeInfoValue{} }

// StandardGaugeInfo is the standard implementation of a GaugeInfo and uses
// sync.Mutex to manage a single string value.
Expand All @@ -101,8 +72,8 @@ type StandardGaugeInfo struct {
}

// Snapshot returns a read-only copy of the gauge.
func (g *StandardGaugeInfo) Snapshot() GaugeInfo {
return GaugeInfoSnapshot(g.Value())
func (g *StandardGaugeInfo) Snapshot() GaugeInfoSnapshot {
return gaugeInfoSnapshot(g.value)
}

// Update updates the gauge's value.
Expand All @@ -111,34 +82,3 @@ func (g *StandardGaugeInfo) Update(v GaugeInfoValue) {
defer g.mutex.Unlock()
g.value = v
}

// Value returns the gauge's current value.
func (g *StandardGaugeInfo) Value() GaugeInfoValue {
g.mutex.Lock()
defer g.mutex.Unlock()
return g.value
}

// FunctionalGaugeInfo returns value from given function
type FunctionalGaugeInfo struct {
value func() GaugeInfoValue
}

// Value returns the gauge's current value.
func (g FunctionalGaugeInfo) Value() GaugeInfoValue {
return g.value()
}

// Value returns the gauge's current value in JSON string format
func (g FunctionalGaugeInfo) ValueJsonString() string {
data, _ := json.Marshal(g.value())
return string(data)
}

// Snapshot returns the snapshot.
func (g FunctionalGaugeInfo) Snapshot() GaugeInfo { return GaugeInfoSnapshot(g.Value()) }

// Update panics.
func (FunctionalGaugeInfo) Update(GaugeInfoValue) {
panic("Update called on a FunctionalGaugeInfo")
}
50 changes: 6 additions & 44 deletions metrics/gauge_info_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package metrics

import (
"strconv"
"testing"
)

Expand All @@ -14,62 +13,25 @@ func TestGaugeInfoJsonString(t *testing.T) {
},
)
want := `{"anotherKey":"any_string_value","chain_id":"5","third_key":"anything"}`
if have := g.Value().String(); have != want {
t.Errorf("\nhave: %v\nwant: %v\n", have, want)
}
}

func TestGaugeInfoSnapshot(t *testing.T) {
g := NewGaugeInfo()
g.Update(GaugeInfoValue{"value": "original"})
snapshot := g.Snapshot() // Snapshot @chainid 5
original := g.Snapshot()
g.Update(GaugeInfoValue{"value": "updated"})
// The 'g' should be updated
if have, want := g.Value().String(), `{"value":"updated"}`; have != want {

if have := original.Value().String(); have != want {
t.Errorf("\nhave: %v\nwant: %v\n", have, want)
}
// Snapshot should be unupdated
if have, want := snapshot.Value().String(), `{"value":"original"}`; have != want {
if have, want := g.Snapshot().Value().String(), `{"value":"updated"}`; have != want {
t.Errorf("\nhave: %v\nwant: %v\n", have, want)
}

}

func TestGetOrRegisterGaugeInfo(t *testing.T) {
r := NewRegistry()
NewRegisteredGaugeInfo("foo", r).Update(
GaugeInfoValue{"chain_id": "5"})
g := GetOrRegisterGaugeInfo("foo", r)
g := GetOrRegisterGaugeInfo("foo", r).Snapshot()
if have, want := g.Value().String(), `{"chain_id":"5"}`; have != want {
t.Errorf("have\n%v\nwant\n%v\n", have, want)
}
}

func TestFunctionalGaugeInfo(t *testing.T) {
info := GaugeInfoValue{"chain_id": "0"}
counter := 1
// A "functional" gauge invokes the method to obtain the value
fg := NewFunctionalGaugeInfo(func() GaugeInfoValue {
info["chain_id"] = strconv.Itoa(counter)
counter++
return info
})
fg.Value()
fg.Value()
if have, want := info["chain_id"], "2"; have != want {
t.Errorf("have %v want %v", have, want)
}
}

func TestGetOrRegisterFunctionalGaugeInfo(t *testing.T) {
r := NewRegistry()
NewRegisteredFunctionalGaugeInfo("foo", r, func() GaugeInfoValue {
return GaugeInfoValue{
"chain_id": "5",
}
})
want := `{"chain_id":"5"}`
have := GetOrRegisterGaugeInfo("foo", r).Value().String()
if have != want {
t.Errorf("have\n%v\nwant\n%v\n", have, want)
}
}
2 changes: 1 addition & 1 deletion metrics/graphite.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func graphite(c *GraphiteConfig) error {
case GaugeFloat64:
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)
fmt.Fprintf(w, "%s.%s.value %s %d\n", c.Prefix, name, metric.Snapshot().Value().String(), now)
case Histogram:
h := metric.Snapshot()
ps := h.Percentiles(c.Percentiles)
Expand Down
2 changes: 1 addition & 1 deletion metrics/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {
l.Printf(" value: %f\n", metric.Snapshot().Value())
case GaugeInfo:
l.Printf("gauge %s\n", name)
l.Printf(" value: %s\n", metric.Value())
l.Printf(" value: %s\n", metric.Snapshot().Value())
case Healthcheck:
metric.Check()
l.Printf("healthcheck %s\n", name)
Expand Down
2 changes: 1 addition & 1 deletion metrics/opentsdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (c *OpenTSDBConfig) writeRegistry(w io.Writer, now int64, shortHostname str
case GaugeFloat64:
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)
fmt.Fprintf(w, "put %s.%s.value %d %s host=%s\n", c.Prefix, name, now, metric.Snapshot().Value().String(), shortHostname)
case Histogram:
h := metric.Snapshot()
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
Expand Down
2 changes: 1 addition & 1 deletion metrics/prometheus/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64Snapshot)
c.writeGaugeCounter(name, m.Value())
}

func (c *collector) addGaugeInfo(name string, m metrics.GaugeInfo) {
func (c *collector) addGaugeInfo(name string, m metrics.GaugeInfoSnapshot) {
c.writeGaugeInfo(name, m.Value())
}

Expand Down
2 changes: 1 addition & 1 deletion metrics/syslog.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func Syslog(r Registry, d time.Duration, w *syslog.Writer) {
case GaugeFloat64:
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()))
w.Info(fmt.Sprintf("gauge %s: value: %s", name, metric.Snapshot().Value()))
case Healthcheck:
metric.Check()
w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error()))
Expand Down
2 changes: 1 addition & 1 deletion metrics/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func WriteOnce(r Registry, w io.Writer) {
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())
fmt.Fprintf(w, " value: %s\n", metric.Snapshot().Value().String())
case Healthcheck:
metric.Check()
fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name)
Expand Down

0 comments on commit f4d0f94

Please sign in to comment.