From 12b499b7f414638484dc9686b23486c5f9c871b7 Mon Sep 17 00:00:00 2001 From: Robert Tillery Date: Mon, 17 Jun 2019 14:49:06 -0400 Subject: [PATCH] Add Set and Histogram --- circonus/circonus.go | 5 +++++ circonus/circonus_test.go | 6 ++++++ datadog/dogstatsd.go | 20 ++++++++++++++++++++ datadog/dogstatsd_test.go | 9 +++++++++ inmem.go | 5 +++++ inmem_test.go | 4 ++++ prometheus/prometheus.go | 5 +++++ prometheus/prometheus_test.go | 11 +++++++++++ sink.go | 12 ++++++++++++ sink_test.go | 4 ++++ statsd.go | 5 +++++ statsd_test.go | 4 ++++ statsite.go | 5 +++++ statsite_test.go | 4 ++++ 14 files changed, 99 insertions(+) create mode 100644 prometheus/prometheus_test.go diff --git a/circonus/circonus.go b/circonus/circonus.go index eb41b99..5786ddd 100644 --- a/circonus/circonus.go +++ b/circonus/circonus.go @@ -97,6 +97,11 @@ func (s *CirconusSink) AddSampleWithLabels(key []string, val float32, labels []m s.metrics.RecordValue(flatKey, float64(val)) } +func (*CirconusSink) Histogram(key []string, val float32) {} +func (*CirconusSink) HistogramWithLabels(key []string, val float32, labels []metrics.Label) {} +func (*CirconusSink) Set(key []string, val string) {} +func (*CirconusSink) SetWithLabels(key []string, val string, labels []metrics.Label) {} + // Flattens key to Circonus metric name func (s *CirconusSink) flattenKey(parts []string) string { joined := strings.Join(parts, "`") diff --git a/circonus/circonus_test.go b/circonus/circonus_test.go index 2644d57..da97357 100644 --- a/circonus/circonus_test.go +++ b/circonus/circonus_test.go @@ -8,8 +8,14 @@ import ( "net/http/httptest" "strings" "testing" + + "github.com/armon/go-metrics" ) +func TestImplementsMetricSink(t *testing.T) { + var _ metrics.MetricSink = &CirconusSink{} +} + func TestNewCirconusSink(t *testing.T) { // test with invalid config (nil) diff --git a/datadog/dogstatsd.go b/datadog/dogstatsd.go index fe021d0..4dea7aa 100644 --- a/datadog/dogstatsd.go +++ b/datadog/dogstatsd.go @@ -100,6 +100,14 @@ func (s *DogStatsdSink) AddSample(key []string, val float32) { s.AddSampleWithLabels(key, val, nil) } +func (s *DogStatsdSink) Histogram(key []string, val float32) { + s.HistogramWithLabels(key, val, nil) +} + +func (s *DogStatsdSink) Set(key []string, val string) { + s.SetWithLabels(key, val, nil) +} + // The following ...WithLabels methods correspond to Datadog's Tag extension to Statsd. // http://docs.datadoghq.com/guides/dogstatsd/#tags func (s *DogStatsdSink) SetGaugeWithLabels(key []string, val float32, labels []metrics.Label) { @@ -120,6 +128,18 @@ func (s *DogStatsdSink) AddSampleWithLabels(key []string, val float32, labels [] s.client.TimeInMilliseconds(flatKey, float64(val), tags, rate) } +func (s *DogStatsdSink) HistogramWithLabels(key []string, val float32, labels []metrics.Label) { + flatKey, tags := s.getFlatkeyAndCombinedLabels(key, labels) + rate := 1.0 + s.client.Histogram(flatKey, float64(val), tags, rate) +} + +func (s *DogStatsdSink) SetWithLabels(key []string, val string, labels []metrics.Label) { + flatKey, tags := s.getFlatkeyAndCombinedLabels(key, labels) + rate := 1.0 + s.client.Set(flatKey, val, tags, rate) +} + func (s *DogStatsdSink) getFlatkeyAndCombinedLabels(key []string, labels []metrics.Label) (string, []string) { key, parsedLabels := s.parseKey(key) flatKey := s.flattenKey(key) diff --git a/datadog/dogstatsd_test.go b/datadog/dogstatsd_test.go index 43b81ac..f8f3980 100644 --- a/datadog/dogstatsd_test.go +++ b/datadog/dogstatsd_test.go @@ -17,6 +17,10 @@ const ( TestHostname = "test_hostname" ) +func TestImplementsMetricSink(t *testing.T) { + var _ metrics.MetricSink = &DogStatsdSink{} +} + func MockGetHostname() string { return TestHostname } @@ -58,6 +62,11 @@ var MetricSinkTests = []struct { {"SetGauge", []string{"foo", "baz"}, float32(42), []metrics.Label{{"my tag", "my_value"}}, HostnameDisabled, "foo.baz:42.000000|g|#my_tag:my_value"}, {"SetGauge", []string{"foo", "bar"}, float32(42), []metrics.Label{{"my_tag", "my_value"}, {"other_tag", "other_value"}}, HostnameDisabled, "foo.bar:42.000000|g|#my_tag:my_value,other_tag:other_value"}, {"SetGauge", []string{"foo", "bar"}, float32(42), []metrics.Label{{"my_tag", "my_value"}, {"other_tag", "other_value"}}, HostnameEnabled, "foo.bar:42.000000|g|#my_tag:my_value,other_tag:other_value,host:test_hostname"}, + + {"Histogram", []string{"foo", "bar"}, float32(42), EmptyTags, HostnameDisabled, "foo.bar:42.000000|h"}, + {"Histogram", []string{"foo", "bar"}, float32(42), []metrics.Label{{"my_tag", "my_value"}}, HostnameDisabled, "foo.bar:42.000000|h|#my_tag:my_value"}, + {"Set", []string{"foo", "bar"}, "baz", EmptyTags, HostnameDisabled, "foo.bar:baz|s"}, + {"Set", []string{"foo", "bar"}, "baz", []metrics.Label{{"my_tag", "my_value"}}, HostnameDisabled, "foo.bar:baz|s|#my_tag:my_value"}, } func mockNewDogStatsdSink(addr string, labels []metrics.Label, tagWithHostname bool) *DogStatsdSink { diff --git a/inmem.go b/inmem.go index 93b0e0a..ff6d085 100644 --- a/inmem.go +++ b/inmem.go @@ -223,6 +223,11 @@ func (i *InmemSink) AddSampleWithLabels(key []string, val float32, labels []Labe agg.Ingest(float64(val), i.rateDenom) } +func (*InmemSink) Histogram(key []string, val float32) {} +func (*InmemSink) HistogramWithLabels(key []string, val float32, labels []Label) {} +func (*InmemSink) Set(key []string, val string) {} +func (*InmemSink) SetWithLabels(key []string, val string, labels []Label) {} + // Data is used to retrieve all the aggregated metrics // Intervals may be in use, and a read lock should be acquired func (i *InmemSink) Data() []*IntervalMetrics { diff --git a/inmem_test.go b/inmem_test.go index 3b037c7..57fe92a 100644 --- a/inmem_test.go +++ b/inmem_test.go @@ -8,6 +8,10 @@ import ( "time" ) +func TestInmemImplementsMetricSink(t *testing.T) { + var _ MetricSink = &InmemSink{} +} + func TestInmemSink(t *testing.T) { inm := NewInmemSink(10*time.Millisecond, 50*time.Millisecond) diff --git a/prometheus/prometheus.go b/prometheus/prometheus.go index 9b339be..c7c08c7 100644 --- a/prometheus/prometheus.go +++ b/prometheus/prometheus.go @@ -192,3 +192,8 @@ func (p *PrometheusSink) IncrCounterWithLabels(parts []string, val float32, labe g.Add(float64(val)) p.updates[hash] = time.Now() } + +func (*PrometheusSink) Histogram(key []string, val float32) {} +func (*PrometheusSink) HistogramWithLabels(key []string, val float32, labels []metrics.Label) {} +func (*PrometheusSink) Set(key []string, val string) {} +func (*PrometheusSink) SetWithLabels(key []string, val string, labels []metrics.Label) {} diff --git a/prometheus/prometheus_test.go b/prometheus/prometheus_test.go new file mode 100644 index 0000000..81b63af --- /dev/null +++ b/prometheus/prometheus_test.go @@ -0,0 +1,11 @@ +package prometheus + +import ( + "testing" + + "github.com/armon/go-metrics" +) + +func TestImplementsMetricSink(t *testing.T) { + var _ metrics.MetricSink = &PrometheusSink{} +} diff --git a/sink.go b/sink.go index 0b7d6e4..22b96b3 100644 --- a/sink.go +++ b/sink.go @@ -22,6 +22,14 @@ type MetricSink interface { // Samples are for timing information, where quantiles are used AddSample(key []string, val float32) AddSampleWithLabels(key []string, val float32, labels []Label) + + // Histogram tracks the statistical distribution of a set of values + Histogram(key []string, val float32) + HistogramWithLabels(key []string, val float32, labels []Label) + + // Set counts the number of unique elements in a group. + Set(key []string, val string) + SetWithLabels(key []string, val string, labels []Label) } // BlackholeSink is used to just blackhole messages @@ -34,6 +42,10 @@ func (*BlackholeSink) IncrCounter(key []string, val float32) func (*BlackholeSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {} func (*BlackholeSink) AddSample(key []string, val float32) {} func (*BlackholeSink) AddSampleWithLabels(key []string, val float32, labels []Label) {} +func (*BlackholeSink) Histogram(key []string, val float32) {} +func (*BlackholeSink) HistogramWithLabels(key []string, val float32, labels []Label) {} +func (*BlackholeSink) Set(key []string, val string) {} +func (*BlackholeSink) SetWithLabels(key []string, val string, labels []Label) {} // FanoutSink is used to sink to fanout values to multiple sinks type FanoutSink []MetricSink diff --git a/sink_test.go b/sink_test.go index 36da370..5d3004a 100644 --- a/sink_test.go +++ b/sink_test.go @@ -63,6 +63,10 @@ func (m *MockSink) AddSampleWithLabels(key []string, val float32, labels []Label m.vals = append(m.vals, val) m.labels = append(m.labels, labels) } +func (*MockSink) Histogram(key []string, val float32) {} +func (*MockSink) HistogramWithLabels(key []string, val float32, labels []Label) {} +func (*MockSink) Set(key []string, val string) {} +func (*MockSink) SetWithLabels(key []string, val string, labels []Label) {} func TestFanoutSink_Gauge(t *testing.T) { m1 := &MockSink{} diff --git a/statsd.go b/statsd.go index 1bfffce..5dc2030 100644 --- a/statsd.go +++ b/statsd.go @@ -80,6 +80,11 @@ func (s *StatsdSink) AddSampleWithLabels(key []string, val float32, labels []Lab s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val)) } +func (*StatsdSink) Histogram(key []string, val float32) {} +func (*StatsdSink) HistogramWithLabels(key []string, val float32, labels []Label) {} +func (*StatsdSink) Set(key []string, val string) {} +func (*StatsdSink) SetWithLabels(key []string, val string, labels []Label) {} + // Flattens the key for formatting, removes spaces func (s *StatsdSink) flattenKey(parts []string) string { joined := strings.Join(parts, ".") diff --git a/statsd_test.go b/statsd_test.go index bdf36cc..bbc9c08 100644 --- a/statsd_test.go +++ b/statsd_test.go @@ -10,6 +10,10 @@ import ( "time" ) +func TestStatsdImplementsMetricSink(t *testing.T) { + var _ MetricSink = &StatsdSink{} +} + func TestStatsd_Flatten(t *testing.T) { s := &StatsdSink{} flat := s.flattenKey([]string{"a", "b", "c", "d"}) diff --git a/statsite.go b/statsite.go index 6c0d284..b7e3821 100644 --- a/statsite.go +++ b/statsite.go @@ -80,6 +80,11 @@ func (s *StatsiteSink) AddSampleWithLabels(key []string, val float32, labels []L s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val)) } +func (*StatsiteSink) Histogram(key []string, val float32) {} +func (*StatsiteSink) HistogramWithLabels(key []string, val float32, labels []Label) {} +func (*StatsiteSink) Set(key []string, val string) {} +func (*StatsiteSink) SetWithLabels(key []string, val string, labels []Label) {} + // Flattens the key for formatting, removes spaces func (s *StatsiteSink) flattenKey(parts []string) string { joined := strings.Join(parts, ".") diff --git a/statsite_test.go b/statsite_test.go index 5b9ee0b..97e6753 100644 --- a/statsite_test.go +++ b/statsite_test.go @@ -9,6 +9,10 @@ import ( "time" ) +func TestStatsiteImplementsMetricSink(t *testing.T) { + var _ MetricSink = &StatsiteSink{} +} + func TestStatsite_Flatten(t *testing.T) { s := &StatsiteSink{} flat := s.flattenKey([]string{"a", "b", "c", "d"})