diff --git a/examples/random/main.go b/examples/random/main.go index 1738408..144c58a 100644 --- a/examples/random/main.go +++ b/examples/random/main.go @@ -31,19 +31,19 @@ func main() { BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50), ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99}, }) - foo_rpc_calls := &metrics.GaugeMetric{} + foo_rpc_calls := &metrics.CounterMetric{} bar_rpc_latency := metrics.CreateHistogram(&metrics.HistogramSpecification{ Starts: metrics.EquallySizedBucketsFor(0, 200, 4), BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50), ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99}, }) - bar_rpc_calls := &metrics.GaugeMetric{} + bar_rpc_calls := &metrics.CounterMetric{} zed_rpc_latency := metrics.CreateHistogram(&metrics.HistogramSpecification{ Starts: metrics.EquallySizedBucketsFor(0, 200, 4), BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50), ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99}, }) - zed_rpc_calls := &metrics.GaugeMetric{} + zed_rpc_calls := &metrics.CounterMetric{} metrics := registry.NewRegistry() metrics.Register("rpc_latency_foo_microseconds", foo_rpc_latency) diff --git a/metrics/constants.go b/metrics/constants.go index 61f24bc..0514ae7 100644 --- a/metrics/constants.go +++ b/metrics/constants.go @@ -14,6 +14,7 @@ package metrics const ( valueKey = "value" gaugeTypeValue = "gauge" + counterTypeValue = "counter" typeKey = "type" histogramTypeValue = "histogram" floatFormat = 'f' diff --git a/metrics/counter.go b/metrics/counter.go new file mode 100644 index 0000000..01549a6 --- /dev/null +++ b/metrics/counter.go @@ -0,0 +1,86 @@ +/* +Copyright (c) 2012, Matt T. Proud +All rights reserved. + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file. +*/ + +package metrics + +import ( + "fmt" + "sync" +) + +type CounterMetric struct { + value float64 + mutex sync.RWMutex +} + +func (metric *CounterMetric) Set(value float64) float64 { + metric.mutex.Lock() + defer metric.mutex.Unlock() + + metric.value = value + + return metric.value +} + +func (metric *CounterMetric) Reset() { + metric.Set(0) +} + +func (metric *CounterMetric) String() string { + formatString := "[CounterMetric; value=%f]" + + metric.mutex.RLock() + defer metric.mutex.RUnlock() + + return fmt.Sprintf(formatString, metric.value) +} + +func (metric *CounterMetric) IncrementBy(value float64) float64 { + metric.mutex.Lock() + defer metric.mutex.Unlock() + + metric.value += value + + return metric.value +} + +func (metric *CounterMetric) Increment() float64 { + return metric.IncrementBy(1) +} + +func (metric *CounterMetric) DecrementBy(value float64) float64 { + metric.mutex.Lock() + defer metric.mutex.Unlock() + + metric.value -= value + + return metric.value +} + +func (metric *CounterMetric) Decrement() float64 { + return metric.DecrementBy(1) +} + +func (metric *CounterMetric) Get() float64 { + metric.mutex.RLock() + defer metric.mutex.RUnlock() + + return metric.value +} + +func (metric *CounterMetric) Marshallable() map[string]interface{} { + metric.mutex.RLock() + defer metric.mutex.RUnlock() + + v := make(map[string]interface{}, 2) + + v[valueKey] = metric.value + v[typeKey] = counterTypeValue + + return v +} diff --git a/metrics/counter_test.go b/metrics/counter_test.go new file mode 100644 index 0000000..94bde05 --- /dev/null +++ b/metrics/counter_test.go @@ -0,0 +1,98 @@ +/* +Copyright (c) 2012, Matt T. Proud +All rights reserved. + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file. +*/ + +package metrics + +import ( + . "launchpad.net/gocheck" +) + +func (s *S) TestCounterCreate(c *C) { + m := CounterMetric{value: 1.0} + + c.Assert(m, Not(IsNil)) +} + +func (s *S) TestCounterGet(c *C) { + m := CounterMetric{value: 42.23} + + c.Check(m.Get(), Equals, 42.23) +} + +func (s *S) TestCounterSet(c *C) { + m := CounterMetric{value: 42.23} + m.Set(40.4) + + c.Check(m.Get(), Equals, 40.4) +} + +func (s *S) TestCounterReset(c *C) { + m := CounterMetric{value: 42.23} + m.Reset() + + c.Check(m.Get(), Equals, 0.0) +} + +func (s *S) TestCounterIncrementBy(c *C) { + m := CounterMetric{value: 1.0} + + m.IncrementBy(1.5) + + c.Check(m.Get(), Equals, 2.5) + c.Check(m.String(), Equals, "[CounterMetric; value=2.500000]") +} + +func (s *S) TestCounterIncrement(c *C) { + m := CounterMetric{value: 1.0} + + m.Increment() + + c.Check(m.Get(), Equals, 2.0) + c.Check(m.String(), Equals, "[CounterMetric; value=2.000000]") +} + +func (s *S) TestCounterDecrementBy(c *C) { + m := CounterMetric{value: 1.0} + + m.DecrementBy(1.0) + + c.Check(m.Get(), Equals, 0.0) + c.Check(m.String(), Equals, "[CounterMetric; value=0.000000]") +} + +func (s *S) TestCounterDecrement(c *C) { + m := CounterMetric{value: 1.0} + + m.Decrement() + + c.Check(m.Get(), Equals, 0.0) + c.Check(m.String(), Equals, "[CounterMetric; value=0.000000]") +} + +func (s *S) TestCounterString(c *C) { + m := CounterMetric{value: 2.0} + c.Check(m.String(), Equals, "[CounterMetric; value=2.000000]") +} + +func (s *S) TestCounterMetricMarshallable(c *C) { + m := CounterMetric{value: 1.0} + + returned := m.Marshallable() + + c.Assert(returned, Not(IsNil)) + + c.Check(returned, HasLen, 2) + c.Check(returned["value"], Equals, 1.0) + c.Check(returned["type"], Equals, "counter") +} + +func (s *S) TestCounterAsMetric(c *C) { + var metric Metric = &CounterMetric{value: 1.0} + + c.Assert(metric, Not(IsNil)) +} diff --git a/metrics/gauge.go b/metrics/gauge.go index ed8f448..4197336 100644 --- a/metrics/gauge.go +++ b/metrics/gauge.go @@ -42,32 +42,6 @@ func (metric *GaugeMetric) Set(value float64) float64 { return metric.value } -func (metric *GaugeMetric) IncrementBy(value float64) float64 { - metric.mutex.Lock() - defer metric.mutex.Unlock() - - metric.value += value - - return metric.value -} - -func (metric *GaugeMetric) Increment() float64 { - return metric.IncrementBy(1) -} - -func (metric *GaugeMetric) DecrementBy(value float64) float64 { - metric.mutex.Lock() - defer metric.mutex.Unlock() - - metric.value -= value - - return metric.value -} - -func (metric *GaugeMetric) Decrement() float64 { - return metric.DecrementBy(1) -} - func (metric *GaugeMetric) Get() float64 { metric.mutex.RLock() defer metric.mutex.RUnlock() diff --git a/metrics/gauge_test.go b/metrics/gauge_test.go index ed479b4..6930c40 100644 --- a/metrics/gauge_test.go +++ b/metrics/gauge_test.go @@ -12,19 +12,19 @@ import ( . "launchpad.net/gocheck" ) -func (s *S) TestCreate(c *C) { +func (s *S) TestGaugeCreate(c *C) { m := GaugeMetric{value: 1.0} c.Assert(m, Not(IsNil)) c.Check(m.Get(), Equals, 1.0) } -func (s *S) TestString(c *C) { +func (s *S) TestGaugeString(c *C) { m := GaugeMetric{value: 2.0} c.Check(m.String(), Equals, "[GaugeMetric; value=2.000000]") } -func (s *S) TestSet(c *C) { +func (s *S) TestGaugeSet(c *C) { m := GaugeMetric{value: -1.0} m.Set(-99.0) @@ -32,42 +32,6 @@ func (s *S) TestSet(c *C) { c.Check(m.Get(), Equals, -99.0) } -func (s *S) TestIncrementBy(c *C) { - m := GaugeMetric{value: 1.0} - - m.IncrementBy(1.5) - - c.Check(m.Get(), Equals, 2.5) - c.Check(m.String(), Equals, "[GaugeMetric; value=2.500000]") -} - -func (s *S) TestIncrement(c *C) { - m := GaugeMetric{value: 1.0} - - m.Increment() - - c.Check(m.Get(), Equals, 2.0) - c.Check(m.String(), Equals, "[GaugeMetric; value=2.000000]") -} - -func (s *S) TestDecrementBy(c *C) { - m := GaugeMetric{value: 1.0} - - m.DecrementBy(1.0) - - c.Check(m.Get(), Equals, 0.0) - c.Check(m.String(), Equals, "[GaugeMetric; value=0.000000]") -} - -func (s *S) TestDecrement(c *C) { - m := GaugeMetric{value: 1.0} - - m.Decrement() - - c.Check(m.Get(), Equals, 0.0) - c.Check(m.String(), Equals, "[GaugeMetric; value=0.000000]") -} - func (s *S) TestGaugeMetricMarshallable(c *C) { m := GaugeMetric{value: 1.0} diff --git a/registry.go b/registry.go index 66b406f..5af343a 100644 --- a/registry.go +++ b/registry.go @@ -31,7 +31,7 @@ exposed if the DefaultRegistry's exporter is hooked into the HTTP request handler. */ -var requestCount *metrics.GaugeMetric = &metrics.GaugeMetric{} +var requestCount *metrics.CounterMetric = &metrics.CounterMetric{} var requestLatencyLogarithmicBuckets []float64 = metrics.LogarithmicSizedBucketsFor(0, 1000) var requestLatencyEqualBuckets []float64 = metrics.EquallySizedBucketsFor(0, 1000, 10) var requestLatencyLogarithmicAccumulating *metrics.Histogram = metrics.CreateHistogram(&metrics.HistogramSpecification{