From 78dcd3b7b2e04218ec409ad703aec4aa9884c648 Mon Sep 17 00:00:00 2001 From: Pedro Tanaka Date: Thu, 21 Apr 2022 08:27:16 +0200 Subject: [PATCH 1/5] Adding new simple test to relay package Signed-off-by: Pedro Tanaka --- go.mod | 1 + go.sum | 2 ++ pkg/relay/relay.go | 3 +- pkg/relay/relay_test.go | 61 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 pkg/relay/relay_test.go diff --git a/go.mod b/go.mod index 1812e33..065a33e 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_model v0.2.0 github.com/prometheus/common v0.30.0 + github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807 gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 6765984..e69f2f3 100644 --- a/go.sum +++ b/go.sum @@ -190,6 +190,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807 h1:LUsDduamlucuNnWcaTbXQ6aLILFcLXADpOzeEH3U+OI= +github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/pkg/relay/relay.go b/pkg/relay/relay.go index e1b280c..900d86a 100644 --- a/pkg/relay/relay.go +++ b/pkg/relay/relay.go @@ -16,6 +16,7 @@ package relay import ( "bytes" "fmt" + "github.com/prometheus/statsd_exporter/pkg/clock" "net" "strings" "time" @@ -91,7 +92,7 @@ func (r *Relay) relayOutput() { var buffer bytes.Buffer var err error - relayInterval := time.NewTicker(1 * time.Second) + relayInterval := clock.NewTicker(1 * time.Second) defer relayInterval.Stop() for { diff --git a/pkg/relay/relay_test.go b/pkg/relay/relay_test.go new file mode 100644 index 0000000..967b670 --- /dev/null +++ b/pkg/relay/relay_test.go @@ -0,0 +1,61 @@ +package relay + +import ( + "github.com/go-kit/log" + "github.com/prometheus/statsd_exporter/pkg/clock" + "github.com/stvp/go-udp-testing" + "testing" + "time" +) + +func TestRelay_RelayLine(t *testing.T) { + type args struct { + lines []string + expected string + } + + tests := []struct { + name string + args args + }{ + { + name: "single line", + args: args{ + lines: []string{"foo5:100|c|#tag1:bar,#tag2:baz"}, + expected: "foo5:100|c|#tag1:bar,#tag2:baz\n", + }, + }, + } + + for _, tt := range tests { + udp.SetAddr(":1160") + t.Run(tt.name, func(t *testing.T) { + + tickerCh := make(chan time.Time) + clock.ClockInstance = &clock.Clock{ + TickerCh: tickerCh, + } + clock.ClockInstance.Instant = time.Unix(0, 0) + + logger := log.NewNopLogger() + r, err := NewRelay( + logger, + "localhost:1160", + 200, + ) + + if err != nil { + t.Errorf("Did not expect error while creating relay.") + } + + udp.ShouldReceive(t, tt.args.expected, func() { + for _, line := range tt.args.lines { + r.RelayLine(line) + // Tick time forward to trigger a flush + } + clock.ClockInstance.Instant = time.Unix(20000, 0) + clock.ClockInstance.TickerCh <- time.Unix(20000, 0) + }) + }) + } +} From 60742e1bd683a508b6e7cfdfb4d0a3fee7469ee7 Mon Sep 17 00:00:00 2001 From: Pedro Tanaka Date: Thu, 21 Apr 2022 11:43:33 +0200 Subject: [PATCH 2/5] Adding metric testing on relay Signed-off-by: Pedro Tanaka --- pkg/relay/relay_test.go | 91 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/pkg/relay/relay_test.go b/pkg/relay/relay_test.go index 967b670..ea07d43 100644 --- a/pkg/relay/relay_test.go +++ b/pkg/relay/relay_test.go @@ -1,7 +1,10 @@ package relay import ( + "fmt" "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" "github.com/prometheus/statsd_exporter/pkg/clock" "github.com/stvp/go-udp-testing" "testing" @@ -51,11 +54,97 @@ func TestRelay_RelayLine(t *testing.T) { udp.ShouldReceive(t, tt.args.expected, func() { for _, line := range tt.args.lines { r.RelayLine(line) - // Tick time forward to trigger a flush } + // Tick time forward to trigger a packet send. clock.ClockInstance.Instant = time.Unix(20000, 0) clock.ClockInstance.TickerCh <- time.Unix(20000, 0) }) + + metrics, err := prometheus.DefaultGatherer.Gather() + if err != nil { + t.Fatalf("Cannot gather from DefaultGatherer: %v", err) + } + + metricNames := map[string]float64{ + "statsd_exporter_relay_long_lines_total": 0, + } + for metricName, expectedValue := range metricNames { + firstMetric := getFloat64(metrics, metricName, prometheus.Labels{"target": "localhost:1160"}) + + if firstMetric == nil { + t.Fatalf("Could not find time series with first label set for metric: %s", metricName) + } + if *firstMetric != expectedValue { + t.Errorf("Expected metric %s to be %f, got %f", metricName, expectedValue, *firstMetric) + } + } }) } } + +// getFloat64 search for metric by name in array of MetricFamily and then search a value by labels. +// Method returns a value or nil if metric is not found. +func getFloat64(metrics []*dto.MetricFamily, name string, labels prometheus.Labels) *float64 { + var metricFamily *dto.MetricFamily + for _, m := range metrics { + if *m.Name == name { + metricFamily = m + break + } + } + if metricFamily == nil { + return nil + } + + var metric *dto.Metric + labelStr := fmt.Sprintf("%v", labels) + for _, m := range metricFamily.Metric { + l := labelPairsAsLabels(m.GetLabel()) + ls := fmt.Sprintf("%v", l) + if labelStr == ls { + metric = m + break + } + } + if metric == nil { + return nil + } + + var value float64 + if metric.Gauge != nil { + value = metric.Gauge.GetValue() + return &value + } + if metric.Counter != nil { + value = metric.Counter.GetValue() + return &value + } + if metric.Histogram != nil { + value = metric.Histogram.GetSampleSum() + return &value + } + if metric.Summary != nil { + value = metric.Summary.GetSampleSum() + return &value + } + if metric.Untyped != nil { + value = metric.Untyped.GetValue() + return &value + } + panic(fmt.Errorf("collected a non-gauge/counter/histogram/summary/untyped metric: %s", metric)) +} + +func labelPairsAsLabels(pairs []*dto.LabelPair) (labels prometheus.Labels) { + labels = prometheus.Labels{} + for _, pair := range pairs { + if pair.Name == nil { + continue + } + value := "" + if pair.Value != nil { + value = *pair.Value + } + labels[*pair.Name] = value + } + return +} From 2d339b08533f1491c44b9a5376e2a4cc27f9aca2 Mon Sep 17 00:00:00 2001 From: Pedro Tanaka Date: Thu, 21 Apr 2022 11:47:19 +0200 Subject: [PATCH 3/5] Adding new metric to relay Signed-off-by: Pedro Tanaka --- pkg/relay/relay.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pkg/relay/relay.go b/pkg/relay/relay.go index 900d86a..bdae527 100644 --- a/pkg/relay/relay.go +++ b/pkg/relay/relay.go @@ -35,8 +35,9 @@ type Relay struct { logger log.Logger packetLength uint - packetsTotal prometheus.Counter - longLinesTotal prometheus.Counter + packetsTotal prometheus.Counter + longLinesTotal prometheus.Counter + relayedLinesTotal prometheus.Counter } var ( @@ -54,6 +55,13 @@ var ( }, []string{"target"}, ) + relayLinesRelayedTotal = promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "statsd_exporter_relay_lines_relayed_total", + Help: "The number of lines that were buffered to be relayed.", + }, + []string{"target"}, + ) ) // NewRelay creates a statsd UDP relay. It can be used to send copies of statsd raw @@ -77,8 +85,9 @@ func NewRelay(l log.Logger, target string, packetLength uint) (*Relay, error) { logger: l, packetLength: packetLength, - packetsTotal: relayPacketsTotal.WithLabelValues(target), - longLinesTotal: relayLongLinesTotal.WithLabelValues(target), + packetsTotal: relayPacketsTotal.WithLabelValues(target), + longLinesTotal: relayLongLinesTotal.WithLabelValues(target), + relayedLinesTotal: relayLinesRelayedTotal.WithLabelValues(target), } // Startup the UDP sender. @@ -152,5 +161,6 @@ func (r *Relay) RelayLine(l string) { if !strings.HasSuffix(l, "\n") { l = l + "\n" } + r.relayedLinesTotal.Inc() r.bufferChannel <- []byte(l) } From d015cda3655857bc1dab880d91783c7e8234847d Mon Sep 17 00:00:00 2001 From: Pedro Tanaka Date: Fri, 22 Apr 2022 14:58:21 +0200 Subject: [PATCH 4/5] Adding new test section to check on metrics Signed-off-by: Pedro Tanaka --- pkg/relay/relay_test.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pkg/relay/relay_test.go b/pkg/relay/relay_test.go index ea07d43..5bdfbca 100644 --- a/pkg/relay/relay_test.go +++ b/pkg/relay/relay_test.go @@ -22,9 +22,9 @@ func TestRelay_RelayLine(t *testing.T) { args args }{ { - name: "single line", + name: "multiple lines", args: args{ - lines: []string{"foo5:100|c|#tag1:bar,#tag2:baz"}, + lines: []string{"foo5:100|c|#tag1:bar,#tag2:baz", "foo2:200|c|#tag1:bar,#tag2:baz"}, expected: "foo5:100|c|#tag1:bar,#tag2:baz\n", }, }, @@ -66,18 +66,22 @@ func TestRelay_RelayLine(t *testing.T) { } metricNames := map[string]float64{ - "statsd_exporter_relay_long_lines_total": 0, + "statsd_exporter_relay_long_lines_total": 0, + "statsd_exporter_relay_lines_relayed_total": float64(len(tt.args.lines)), } for metricName, expectedValue := range metricNames { - firstMetric := getFloat64(metrics, metricName, prometheus.Labels{"target": "localhost:1160"}) + metric := getFloat64(metrics, metricName, prometheus.Labels{"target": "localhost:1160"}) - if firstMetric == nil { + if metric == nil { t.Fatalf("Could not find time series with first label set for metric: %s", metricName) } - if *firstMetric != expectedValue { - t.Errorf("Expected metric %s to be %f, got %f", metricName, expectedValue, *firstMetric) + if *metric != expectedValue { + t.Errorf("Expected metric %s to be %f, got %f", metricName, expectedValue, *metric) } } + + prometheus.Unregister(relayLongLinesTotal) + prometheus.Unregister(relayLinesRelayedTotal) }) } } From fbf78373879d4a582cf4be1239e40035b02436c3 Mon Sep 17 00:00:00 2001 From: Pedro Tanaka Date: Tue, 26 Apr 2022 21:07:02 +0200 Subject: [PATCH 5/5] Fixing linting problems on new code Signed-off-by: Pedro Tanaka --- pkg/relay/relay.go | 3 ++- pkg/relay/relay_test.go | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/relay/relay.go b/pkg/relay/relay.go index bdae527..6e8e752 100644 --- a/pkg/relay/relay.go +++ b/pkg/relay/relay.go @@ -16,11 +16,12 @@ package relay import ( "bytes" "fmt" - "github.com/prometheus/statsd_exporter/pkg/clock" "net" "strings" "time" + "github.com/prometheus/statsd_exporter/pkg/clock" + "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" diff --git a/pkg/relay/relay_test.go b/pkg/relay/relay_test.go index 5bdfbca..3974c9d 100644 --- a/pkg/relay/relay_test.go +++ b/pkg/relay/relay_test.go @@ -2,13 +2,14 @@ package relay import ( "fmt" + "testing" + "time" + "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/prometheus/statsd_exporter/pkg/clock" "github.com/stvp/go-udp-testing" - "testing" - "time" ) func TestRelay_RelayLine(t *testing.T) { @@ -33,7 +34,6 @@ func TestRelay_RelayLine(t *testing.T) { for _, tt := range tests { udp.SetAddr(":1160") t.Run(tt.name, func(t *testing.T) { - tickerCh := make(chan time.Time) clock.ClockInstance = &clock.Clock{ TickerCh: tickerCh, @@ -56,8 +56,8 @@ func TestRelay_RelayLine(t *testing.T) { r.RelayLine(line) } // Tick time forward to trigger a packet send. - clock.ClockInstance.Instant = time.Unix(20000, 0) - clock.ClockInstance.TickerCh <- time.Unix(20000, 0) + clock.ClockInstance.Instant = time.Unix(1, 10) + clock.ClockInstance.TickerCh <- time.Unix(0, 0) }) metrics, err := prometheus.DefaultGatherer.Gather()