metrics: remove Counter interfaces

This commit is contained in:
Martin Holst Swende 2024-11-26 18:53:07 +01:00
parent 915248cd6b
commit d2a3d9a775
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
13 changed files with 40 additions and 94 deletions

View file

@ -4,109 +4,56 @@ import (
"sync/atomic" "sync/atomic"
) )
type CounterSnapshot interface {
Count() int64
}
// Counter hold an int64 value that can be incremented and decremented.
type Counter interface {
Clear()
Dec(int64)
Inc(int64)
Snapshot() CounterSnapshot
}
// GetOrRegisterCounter returns an existing Counter or constructs and registers // GetOrRegisterCounter returns an existing Counter or constructs and registers
// a new StandardCounter. // a new Counter.
func GetOrRegisterCounter(name string, r Registry) Counter { func GetOrRegisterCounter(name string, r Registry) *Counter {
if nil == r { if r == nil {
r = DefaultRegistry r = DefaultRegistry
} }
return r.GetOrRegister(name, NewCounter).(Counter) return r.GetOrRegister(name, NewCounter).(*Counter)
} }
// GetOrRegisterCounterForced returns an existing Counter or constructs and registers a // NewCounter constructs a new Counter.
// new Counter no matter the global switch is enabled or not. func NewCounter() *Counter {
// Be sure to unregister the counter from the registry once it is of no use to return new(Counter)
// allow for garbage collection.
func GetOrRegisterCounterForced(name string, r Registry) Counter {
if nil == r {
r = DefaultRegistry
}
return r.GetOrRegister(name, NewCounterForced).(Counter)
} }
// NewCounter constructs a new StandardCounter. // NewRegisteredCounter constructs and registers a new Counter.
func NewCounter() Counter { func NewRegisteredCounter(name string, r Registry) *Counter {
if !Enabled {
return NilCounter{}
}
return new(StandardCounter)
}
// NewCounterForced constructs a new StandardCounter and returns it no matter if
// the global switch is enabled or not.
func NewCounterForced() Counter {
return new(StandardCounter)
}
// NewRegisteredCounter constructs and registers a new StandardCounter.
func NewRegisteredCounter(name string, r Registry) Counter {
c := NewCounter() c := NewCounter()
if nil == r { if r == nil {
r = DefaultRegistry r = DefaultRegistry
} }
r.Register(name, c) r.Register(name, c)
return c return c
} }
// NewRegisteredCounterForced constructs and registers a new StandardCounter // CounterSnapshot is a read-only copy of a Counter.
// and launches a goroutine no matter the global switch is enabled or not. type CounterSnapshot int64
// Be sure to unregister the counter from the registry once it is of no use to
// allow for garbage collection.
func NewRegisteredCounterForced(name string, r Registry) Counter {
c := NewCounterForced()
if nil == r {
r = DefaultRegistry
}
r.Register(name, c)
return c
}
// counterSnapshot is a read-only copy of another Counter.
type counterSnapshot int64
// Count returns the count at the time the snapshot was taken. // Count returns the count at the time the snapshot was taken.
func (c counterSnapshot) Count() int64 { return int64(c) } func (c CounterSnapshot) Count() int64 { return int64(c) }
// NilCounter is a no-op Counter. // Counter is the standard implementation of a Counter and uses the
type NilCounter struct{}
func (NilCounter) Clear() {}
func (NilCounter) Dec(i int64) {}
func (NilCounter) Inc(i int64) {}
func (NilCounter) Snapshot() CounterSnapshot { return (*emptySnapshot)(nil) }
// StandardCounter is the standard implementation of a Counter and uses the
// sync/atomic package to manage a single int64 value. // sync/atomic package to manage a single int64 value.
type StandardCounter atomic.Int64 type Counter atomic.Int64
// Clear sets the counter to zero. // Clear sets the counter to zero.
func (c *StandardCounter) Clear() { func (c *Counter) Clear() {
(*atomic.Int64)(c).Store(0) (*atomic.Int64)(c).Store(0)
} }
// Dec decrements the counter by the given amount. // Dec decrements the counter by the given amount.
func (c *StandardCounter) Dec(i int64) { func (c *Counter) Dec(i int64) {
(*atomic.Int64)(c).Add(-i) (*atomic.Int64)(c).Add(-i)
} }
// Inc increments the counter by the given amount. // Inc increments the counter by the given amount.
func (c *StandardCounter) Inc(i int64) { func (c *Counter) Inc(i int64) {
(*atomic.Int64)(c).Add(i) (*atomic.Int64)(c).Add(i)
} }
// Snapshot returns a read-only copy of the counter. // Snapshot returns a read-only copy of the counter.
func (c *StandardCounter) Snapshot() CounterSnapshot { func (c *Counter) Snapshot() CounterSnapshot {
return counterSnapshot((*atomic.Int64)(c).Load()) return CounterSnapshot((*atomic.Int64)(c).Load())
} }

View file

@ -188,7 +188,7 @@ func (exp *exp) publishResettingTimer(name string, metric metrics.ResettingTimer
func (exp *exp) syncToExpvar() { func (exp *exp) syncToExpvar() {
exp.registry.Each(func(name string, i interface{}) { exp.registry.Each(func(name string, i interface{}) {
switch i := i.(type) { switch i := i.(type) {
case metrics.Counter: case *metrics.Counter:
exp.publishCounter(name, i.Snapshot()) exp.publishCounter(name, i.Snapshot())
case metrics.CounterFloat64: case metrics.CounterFloat64:
exp.publishCounterFloat64(name, i.Snapshot()) exp.publishCounterFloat64(name, i.Snapshot())

View file

@ -65,7 +65,7 @@ func graphite(c *GraphiteConfig) error {
w := bufio.NewWriter(conn) w := bufio.NewWriter(conn)
c.Registry.Each(func(name string, i interface{}) { c.Registry.Each(func(name string, i interface{}) {
switch metric := i.(type) { switch metric := i.(type) {
case Counter: case *Counter:
fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Snapshot().Count(), now) fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Snapshot().Count(), now)
case CounterFloat64: case CounterFloat64:
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)

View file

@ -20,7 +20,6 @@ package metrics
var ( var (
_ SampleSnapshot = (*emptySnapshot)(nil) _ SampleSnapshot = (*emptySnapshot)(nil)
_ HistogramSnapshot = (*emptySnapshot)(nil) _ HistogramSnapshot = (*emptySnapshot)(nil)
_ CounterSnapshot = (*emptySnapshot)(nil)
_ GaugeSnapshot = (*emptySnapshot)(nil) _ GaugeSnapshot = (*emptySnapshot)(nil)
_ MeterSnapshot = (*emptySnapshot)(nil) _ MeterSnapshot = (*emptySnapshot)(nil)
_ EWMASnapshot = (*emptySnapshot)(nil) _ EWMASnapshot = (*emptySnapshot)(nil)

View file

@ -8,7 +8,7 @@ import (
func readMeter(namespace, name string, i interface{}) (string, map[string]interface{}) { func readMeter(namespace, name string, i interface{}) (string, map[string]interface{}) {
switch metric := i.(type) { switch metric := i.(type) {
case metrics.Counter: case *metrics.Counter:
measurement := fmt.Sprintf("%s%s.count", namespace, name) measurement := fmt.Sprintf("%s%s.count", namespace, name)
fields := map[string]interface{}{ fields := map[string]interface{}{
"value": metric.Snapshot().Count(), "value": metric.Snapshot().Count(),

View file

@ -21,7 +21,7 @@ func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {
for range time.Tick(freq) { for range time.Tick(freq) {
r.Each(func(name string, i interface{}) { r.Each(func(name string, i interface{}) {
switch metric := i.(type) { switch metric := i.(type) {
case Counter: case *Counter:
l.Printf("counter %s\n", name) l.Printf("counter %s\n", name)
l.Printf(" count: %9d\n", metric.Snapshot().Count()) l.Printf(" count: %9d\n", metric.Snapshot().Count())
case CounterFloat64: case CounterFloat64:

View file

@ -64,7 +64,7 @@ func (c *OpenTSDBConfig) writeRegistry(w io.Writer, now int64, shortHostname str
c.Registry.Each(func(name string, i interface{}) { c.Registry.Each(func(name string, i interface{}) {
switch metric := i.(type) { switch metric := i.(type) {
case Counter: case *Counter:
fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Snapshot().Count(), shortHostname) fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Snapshot().Count(), shortHostname)
case CounterFloat64: case CounterFloat64:
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)

View file

@ -51,7 +51,7 @@ func newCollector() *collector {
// metric type is not supported/known. // metric type is not supported/known.
func (c *collector) Add(name string, i any) error { func (c *collector) Add(name string, i any) error {
switch m := i.(type) { switch m := i.(type) {
case metrics.Counter: case *metrics.Counter:
c.addCounter(name, m.Snapshot()) c.addCounter(name, m.Snapshot())
case metrics.CounterFloat64: case metrics.CounterFloat64:
c.addCounterFloat64(name, m.Snapshot()) c.addCounterFloat64(name, m.Snapshot())

View file

@ -149,7 +149,7 @@ func (r *StandardRegistry) GetAll() map[string]map[string]interface{} {
r.Each(func(name string, i interface{}) { r.Each(func(name string, i interface{}) {
values := make(map[string]interface{}) values := make(map[string]interface{})
switch metric := i.(type) { switch metric := i.(type) {
case Counter: case *Counter:
values["count"] = metric.Snapshot().Count() values["count"] = metric.Snapshot().Count()
case CounterFloat64: case CounterFloat64:
values["count"] = metric.Snapshot().Count() values["count"] = metric.Snapshot().Count()
@ -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

@ -47,7 +47,7 @@ func TestRegistry(t *testing.T) {
if name != "foo" { if name != "foo" {
t.Fatal(name) t.Fatal(name)
} }
if _, ok := iface.(Counter); !ok { if _, ok := iface.(*Counter); !ok {
t.Fatal(iface) t.Fatal(iface)
} }
}) })
@ -73,7 +73,7 @@ func TestRegistryDuplicate(t *testing.T) {
i := 0 i := 0
r.Each(func(name string, iface interface{}) { r.Each(func(name string, iface interface{}) {
i++ i++
if _, ok := iface.(Counter); !ok { if _, ok := iface.(*Counter); !ok {
t.Fatal(iface) t.Fatal(iface)
} }
}) })
@ -85,11 +85,11 @@ func TestRegistryDuplicate(t *testing.T) {
func TestRegistryGet(t *testing.T) { func TestRegistryGet(t *testing.T) {
r := NewRegistry() r := NewRegistry()
r.Register("foo", NewCounter()) r.Register("foo", NewCounter())
if count := r.Get("foo").(Counter).Snapshot().Count(); count != 0 { if count := r.Get("foo").(*Counter).Snapshot().Count(); count != 0 {
t.Fatal(count) t.Fatal(count)
} }
r.Get("foo").(Counter).Inc(1) r.Get("foo").(*Counter).Inc(1)
if count := r.Get("foo").(Counter).Snapshot().Count(); count != 1 { if count := r.Get("foo").(*Counter).Snapshot().Count(); count != 1 {
t.Fatal(count) t.Fatal(count)
} }
} }
@ -100,7 +100,7 @@ func TestRegistryGetOrRegister(t *testing.T) {
// First metric wins with GetOrRegister // First metric wins with GetOrRegister
_ = r.GetOrRegister("foo", NewCounter()) _ = r.GetOrRegister("foo", NewCounter())
m := r.GetOrRegister("foo", NewGauge()) m := r.GetOrRegister("foo", NewGauge())
if _, ok := m.(Counter); !ok { if _, ok := m.(*Counter); !ok {
t.Fatal(m) t.Fatal(m)
} }
@ -110,7 +110,7 @@ func TestRegistryGetOrRegister(t *testing.T) {
if name != "foo" { if name != "foo" {
t.Fatal(name) t.Fatal(name)
} }
if _, ok := iface.(Counter); !ok { if _, ok := iface.(*Counter); !ok {
t.Fatal(iface) t.Fatal(iface)
} }
}) })
@ -125,7 +125,7 @@ func TestRegistryGetOrRegisterWithLazyInstantiation(t *testing.T) {
// First metric wins with GetOrRegister // First metric wins with GetOrRegister
_ = r.GetOrRegister("foo", NewCounter) _ = r.GetOrRegister("foo", NewCounter)
m := r.GetOrRegister("foo", NewGauge) m := r.GetOrRegister("foo", NewGauge)
if _, ok := m.(Counter); !ok { if _, ok := m.(*Counter); !ok {
t.Fatal(m) t.Fatal(m)
} }
@ -135,7 +135,7 @@ func TestRegistryGetOrRegisterWithLazyInstantiation(t *testing.T) {
if name != "foo" { if name != "foo" {
t.Fatal(name) t.Fatal(name)
} }
if _, ok := iface.(Counter); !ok { if _, ok := iface.(*Counter); !ok {
t.Fatal(iface) t.Fatal(iface)
} }
}) })

View file

@ -15,7 +15,7 @@ func Syslog(r Registry, d time.Duration, w *syslog.Writer) {
for range time.Tick(d) { for range time.Tick(d) {
r.Each(func(name string, i interface{}) { r.Each(func(name string, i interface{}) {
switch metric := i.(type) { switch metric := i.(type) {
case Counter: case *Counter:
w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Snapshot().Count())) w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Snapshot().Count()))
case CounterFloat64: case CounterFloat64:
w.Info(fmt.Sprintf("counter %s: count: %f", name, metric.Snapshot().Count())) w.Info(fmt.Sprintf("counter %s: count: %f", name, metric.Snapshot().Count()))

View file

@ -26,7 +26,7 @@ func WriteOnce(r Registry, w io.Writer) {
slices.SortFunc(namedMetrics, namedMetric.cmp) slices.SortFunc(namedMetrics, namedMetric.cmp)
for _, namedMetric := range namedMetrics { for _, namedMetric := range namedMetrics {
switch metric := namedMetric.m.(type) { switch metric := namedMetric.m.(type) {
case Counter: case *Counter:
fmt.Fprintf(w, "counter %s\n", namedMetric.name) fmt.Fprintf(w, "counter %s\n", namedMetric.name)
fmt.Fprintf(w, " count: %9d\n", metric.Snapshot().Count()) fmt.Fprintf(w, " count: %9d\n", metric.Snapshot().Count())
case CounterFloat64: case CounterFloat64:

View file

@ -34,7 +34,7 @@ const (
) )
var ( var (
bucketsCounter []metrics.Counter bucketsCounter []*metrics.Counter
ingressTrafficMeter = metrics.NewRegisteredMeter(ingressMeterName, nil) ingressTrafficMeter = metrics.NewRegisteredMeter(ingressMeterName, nil)
egressTrafficMeter = metrics.NewRegisteredMeter(egressMeterName, nil) egressTrafficMeter = metrics.NewRegisteredMeter(egressMeterName, nil)
) )