Merge pull request #3 from kesselborn/feature/extract-counter-from-gauge

Split Gauge into Gauge and Counter
This commit is contained in:
Matt T. Proud 2012-12-19 02:54:51 -08:00
commit 474d1d53d1
7 changed files with 192 additions and 69 deletions

View File

@ -31,19 +31,19 @@ func main() {
BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50), BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50),
ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99}, 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{ bar_rpc_latency := metrics.CreateHistogram(&metrics.HistogramSpecification{
Starts: metrics.EquallySizedBucketsFor(0, 200, 4), Starts: metrics.EquallySizedBucketsFor(0, 200, 4),
BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50), BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50),
ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99}, 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{ zed_rpc_latency := metrics.CreateHistogram(&metrics.HistogramSpecification{
Starts: metrics.EquallySizedBucketsFor(0, 200, 4), Starts: metrics.EquallySizedBucketsFor(0, 200, 4),
BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50), BucketMaker: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50),
ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99}, 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 := registry.NewRegistry()
metrics.Register("rpc_latency_foo_microseconds", foo_rpc_latency) metrics.Register("rpc_latency_foo_microseconds", foo_rpc_latency)

View File

@ -14,6 +14,7 @@ package metrics
const ( const (
valueKey = "value" valueKey = "value"
gaugeTypeValue = "gauge" gaugeTypeValue = "gauge"
counterTypeValue = "counter"
typeKey = "type" typeKey = "type"
histogramTypeValue = "histogram" histogramTypeValue = "histogram"
floatFormat = 'f' floatFormat = 'f'

86
metrics/counter.go Normal file
View File

@ -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
}

98
metrics/counter_test.go Normal file
View File

@ -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))
}

View File

@ -42,32 +42,6 @@ func (metric *GaugeMetric) Set(value float64) float64 {
return metric.value 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 { func (metric *GaugeMetric) Get() float64 {
metric.mutex.RLock() metric.mutex.RLock()
defer metric.mutex.RUnlock() defer metric.mutex.RUnlock()

View File

@ -12,19 +12,19 @@ import (
. "launchpad.net/gocheck" . "launchpad.net/gocheck"
) )
func (s *S) TestCreate(c *C) { func (s *S) TestGaugeCreate(c *C) {
m := GaugeMetric{value: 1.0} m := GaugeMetric{value: 1.0}
c.Assert(m, Not(IsNil)) c.Assert(m, Not(IsNil))
c.Check(m.Get(), Equals, 1.0) c.Check(m.Get(), Equals, 1.0)
} }
func (s *S) TestString(c *C) { func (s *S) TestGaugeString(c *C) {
m := GaugeMetric{value: 2.0} m := GaugeMetric{value: 2.0}
c.Check(m.String(), Equals, "[GaugeMetric; value=2.000000]") 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 := GaugeMetric{value: -1.0}
m.Set(-99.0) m.Set(-99.0)
@ -32,42 +32,6 @@ func (s *S) TestSet(c *C) {
c.Check(m.Get(), Equals, -99.0) 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) { func (s *S) TestGaugeMetricMarshallable(c *C) {
m := GaugeMetric{value: 1.0} m := GaugeMetric{value: 1.0}

View File

@ -31,7 +31,7 @@ exposed if the DefaultRegistry's exporter is hooked into the HTTP request
handler. handler.
*/ */
var requestCount *metrics.GaugeMetric = &metrics.GaugeMetric{} var requestCount *metrics.CounterMetric = &metrics.CounterMetric{}
var requestLatencyLogarithmicBuckets []float64 = metrics.LogarithmicSizedBucketsFor(0, 1000) var requestLatencyLogarithmicBuckets []float64 = metrics.LogarithmicSizedBucketsFor(0, 1000)
var requestLatencyEqualBuckets []float64 = metrics.EquallySizedBucketsFor(0, 1000, 10) var requestLatencyEqualBuckets []float64 = metrics.EquallySizedBucketsFor(0, 1000, 10)
var requestLatencyLogarithmicAccumulating *metrics.Histogram = metrics.CreateHistogram(&metrics.HistogramSpecification{ var requestLatencyLogarithmicAccumulating *metrics.Histogram = metrics.CreateHistogram(&metrics.HistogramSpecification{