Skip to content

Commit

Permalink
initial implementation of GaugeFloat64
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-garcia committed Mar 22, 2014
1 parent ea09f7d commit 68b1307
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 1 deletion.
1 change: 1 addition & 0 deletions cmd/metrics-bench/metrics-bench.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ func main() {
for i := 0; i < 10000; i++ {
r.Register(fmt.Sprintf("counter-%d", i), metrics.NewCounter())
r.Register(fmt.Sprintf("gauge-%d", i), metrics.NewGauge())
r.Register(fmt.Sprintf("gaugefloat64-%d", i), metrics.NewGaugeFloat64())
r.Register(fmt.Sprintf("histogram-uniform-%d", i), metrics.NewHistogram(metrics.NewUniformSample(1028)))
r.Register(fmt.Sprintf("histogram-exp-%d", i), metrics.NewHistogram(metrics.NewExpDecaySample(1028, 0.015)))
r.Register(fmt.Sprintf("meter-%d", i), metrics.NewMeter())
Expand Down
17 changes: 17 additions & 0 deletions cmd/metrics-example/metrics-example.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ func main() {
}()
}

gf := metrics.NewGaugeFloat64()
r.Register("barfloat64", gf)
for i := 0; i < fanout; i++ {
go func() {
for {
g.Update(19.0)
time.Sleep(300e6)
}
}()
go func() {
for {
g.Update(47.0)
time.Sleep(400e6)
}
}()
}

hc := metrics.NewHealthcheck(func(h metrics.Healthcheck) {
if 0 < rand.Intn(2) {
h.Healthy()
Expand Down
91 changes: 91 additions & 0 deletions gauge_float64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package metrics

import "sync"

// GaugeFloat64s hold a float64 value that can be set arbitrarily.
type GaugeFloat64 interface {
Snapshot() GaugeFloat64
Update(float64)
Value() float64
}

// GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a
// new StandardGaugeFloat64.
func GetOrRegisterGaugeFloat64(name string, r Registry) GaugeFloat64 {
if nil == r {
r = DefaultRegistry
}
return r.GetOrRegister(name, NewGaugeFloat64()).(GaugeFloat64)
}

// NewGaugeFloat64 constructs a new StandardGaugeFloat64.
func NewGaugeFloat64() GaugeFloat64 {
if UseNilMetrics {
return NilGaugeFloat64{}
}
return &StandardGaugeFloat64{
value: 0.0,
}
}

// NewRegisteredGaugeFloat64 constructs and registers a new StandardGaugeFloat64.
func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 {
c := NewGaugeFloat64()
if nil == r {
r = DefaultRegistry
}
r.Register(name, c)
return c
}

// GaugeSnapshotFloat64 is a read-only copy of another GaugeFloat64.
type GaugeSnapshotFloat64 float64

// Snapshot returns the snapshot.
func (g GaugeSnapshotFloat64) Snapshot() GaugeFloat64 { return g }

// Update panics.
func (GaugeSnapshotFloat64) Update(float64) {
panic("Update called on a GaugeSnapshotFloat64")
}

// Value returns the value at the time the snapshot was taken.
func (g GaugeSnapshotFloat64) 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{} }

// Update is a no-op.
func (NilGaugeFloat64) Update(v float64) {}

// Value is a no-op.
func (NilGaugeFloat64) Value() float64 { return 0.0 }

// StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses
// sync.Mutex to manage a single float64 value.
type StandardGaugeFloat64 struct {
value float64
sync.Mutex
}

// Snapshot returns a read-only copy of the gauge.
func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 {
return GaugeSnapshotFloat64(g.Value())
}

// Update updates the gauge's value.
func (g *StandardGaugeFloat64) Update(v float64) {
g.Lock()
defer g.Unlock()
g.value = v
}

// Value returns the gauge's current value.
func (g *StandardGaugeFloat64) Value() float64 {
g.Lock()
defer g.Unlock()
return g.value
}
39 changes: 39 additions & 0 deletions gauge_float64_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package metrics

import "testing"


func BenchmarkGuageFloat64(b *testing.B) {
g := NewGaugeFloat64()
b.ResetTimer()
for i := 0; i < b.N; i++ {
g.Update(float64(i))
}
}

func TestGaugeFloat64(t *testing.T) {
g := NewGaugeFloat64()
g.Update(float64(47.0))
if v := g.Value(); float64(47.0) != v {
t.Errorf("g.Value(): 47.0 != %v\n", v)
}
}

func TestGaugeFloat64Snapshot(t *testing.T) {
g := NewGaugeFloat64()
g.Update(float64(47.0))
snapshot := g.Snapshot()
g.Update(float64(0))
if v := snapshot.Value(); float64(47.0) != v {
t.Errorf("g.Value(): 47.0 != %v\n", v)
}
}

func TestGetOrRegisterGaugeFloat64(t *testing.T) {
r := NewRegistry()
NewRegisteredGaugeFloat64("foo", r).Update(float64(47.0))
t.Logf("registry: %v", r)
if g := GetOrRegisterGaugeFloat64("foo", r); float64(47.0) != g.Value() {
t.Fatal(g)
}
}
2 changes: 2 additions & 0 deletions graphite.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ func graphite(c *GraphiteConfig) error {
fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now)
case Gauge:
fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now)
case GaugeFloat64:
fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now)
case Histogram:
h := metric.Snapshot()
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
Expand Down
8 changes: 8 additions & 0 deletions influxdb/influxdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ func send(r metrics.Registry, client *influxClient.Client) error {
{now, metric.Value()},
},
})
case metrics.GaugeFloat64:
series = append(series, &influxClient.Series{
Name: fmt.Sprintf("%s.value", name),
Columns: []string{"time", "value"},
Points: [][]interface{}{
{now, metric.Value()},
},
})
case metrics.Histogram:
h := metric.Snapshot()
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
Expand Down
2 changes: 2 additions & 0 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ func (r StandardRegistry) MarshalJSON() ([]byte, error) {
values["count"] = metric.Count()
case Gauge:
values["value"] = metric.Value()
case GaugeFloat64:
values["value"] = metric.Value()
case Healthcheck:
metric.Check()
values["error"] = metric.Error().Error()
Expand Down
4 changes: 4 additions & 0 deletions librato/librato.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot
measurement[Name] = name
measurement[Value] = float64(m.Value())
snapshot.Gauges = append(snapshot.Gauges, measurement)
case metrics.GaugeFloat64:
measurement[Name] = name
measurement[Value] = float64(m.Value())
snapshot.Gauges = append(snapshot.Gauges, measurement)
case metrics.Histogram:
if m.Count() > 0 {
gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
Expand Down
3 changes: 3 additions & 0 deletions log.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ func Log(r Registry, d time.Duration, l *log.Logger) {
case Gauge:
l.Printf("gauge %s\n", name)
l.Printf(" value: %9d\n", metric.Value())
case GaugeFloat64:
l.Printf("gauge %s\n", name)
l.Printf(" value: %f\n", metric.Value())
case Healthcheck:
metric.Check()
l.Printf("healthcheck %s\n", name)
Expand Down
2 changes: 2 additions & 0 deletions metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func BenchmarkMetrics(b *testing.B) {
r := NewRegistry()
c := NewRegisteredCounter("counter", r)
g := NewRegisteredGauge("gauge", r)
gf := NewRegisteredGaugeFloat64("gaugefloat64", r)
h := NewRegisteredHistogram("histogram", r, NewUniformSample(100))
m := NewRegisteredMeter("meter", r)
t := NewRegisteredTimer("timer", r)
Expand Down Expand Up @@ -90,6 +91,7 @@ func BenchmarkMetrics(b *testing.B) {
for i := 0; i < b.N; i++ {
c.Inc(1)
g.Update(int64(i))
gf.Update(float64(i))
h.Update(int64(i))
m.Mark(1)
t.Update(1)
Expand Down
2 changes: 1 addition & 1 deletion registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (r *StandardRegistry) Unregister(name string) {

func (r *StandardRegistry) register(name string, i interface{}) {
switch i.(type) {
case Counter, Gauge, Healthcheck, Histogram, Meter, Timer:
case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer:
r.metrics[name] = i
}
}
Expand Down
2 changes: 2 additions & 0 deletions stathat/stathat.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func sh(r metrics.Registry, userkey string) error {
stathat.PostEZCount(name, userkey, int(metric.Count()))
case metrics.Gauge:
stathat.PostEZValue(name, userkey, float64(metric.Value()))
case metrics.GaugeFloat64:
stathat.PostEZValue(name, userkey, float64(metric.Value()))
case metrics.Histogram:
h := metric.Snapshot()
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
Expand Down
2 changes: 2 additions & 0 deletions syslog.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ func Syslog(r Registry, d time.Duration, w *syslog.Writer) {
w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Count()))
case Gauge:
w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value()))
case GaugeFloat64:
w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value()))
case Healthcheck:
metric.Check()
w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error()))
Expand Down
3 changes: 3 additions & 0 deletions writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func WriteOnce(r Registry, w io.Writer) {
case Gauge:
fmt.Fprintf(w, "gauge %s\n", name)
fmt.Fprintf(w, " value: %9d\n", metric.Value())
case GaugeFloat64:
fmt.Fprintf(w, "gauge %s\n", name)
fmt.Fprintf(w, " value: %f\n", metric.Value())
case Healthcheck:
metric.Check()
fmt.Fprintf(w, "healthcheck %s\n", name)
Expand Down

0 comments on commit 68b1307

Please sign in to comment.