From f2f9c4da72ef8be9bc1b3c4f92519fd54184c012 Mon Sep 17 00:00:00 2001 From: Lukasz Cwik <126621805+lcwik@users.noreply.github.com> Date: Wed, 13 Sep 2023 10:28:51 -0700 Subject: [PATCH] [DEC-2088] Add metrics specific tests (#250) * [DEC-2088] Add metrics specific tests * Revert back to method that exists in go 1.19 * Move package, fix exact type for require.Equals --- protocol/lib/metrics/util_test.go | 206 +++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 6 deletions(-) diff --git a/protocol/lib/metrics/util_test.go b/protocol/lib/metrics/util_test.go index cd0829e06c..9f1e404aa9 100644 --- a/protocol/lib/metrics/util_test.go +++ b/protocol/lib/metrics/util_test.go @@ -1,16 +1,58 @@ -package metrics +package metrics_test import ( + gometrics "github.com/armon/go-metrics" + "github.com/dydxprotocol/v4-chain/protocol/lib/metrics" "math" "math/big" "testing" + "time" "github.com/stretchr/testify/require" ) +func TestIncrCountMetricWithLabels(t *testing.T) { + defer gometrics.Shutdown() + + conf := gometrics.DefaultConfig("testService") + sink := gometrics.NewInmemSink(time.Hour, time.Hour) + _, err := gometrics.NewGlobal(conf, sink) + require.NoError(t, err) + + for i := 0; i < 3; i++ { + metrics.IncrCountMetricWithLabels( + "testModule", + "testMetric", + gometrics.Label{ + Name: "testLabel", + Value: "testLabelValue", + }, + ) + } + + found := false + for _, metrics := range sink.Data() { + metrics.RLock() + defer metrics.RUnlock() + + if metric, ok := metrics.Counters["testService.testModule.testMetric.count;testLabel=testLabelValue"]; ok { + require.Equal(t, + []gometrics.Label{{ + Name: "testLabel", + Value: "testLabelValue", + }}, + metric.Labels) + require.Equal(t, 3, metric.Count) + require.Equal(t, float64(3), metric.Sum) + found = true + } + } + require.True(t, found) +} + func TestIncrCountMetricWithLabelsDoesntPanic(t *testing.T) { require.NotPanics(t, func() { - IncrCountMetricWithLabels("module", "metric", NewBinaryStringLabel("label", true)) + metrics.IncrCountMetricWithLabels("module", "metric", metrics.NewBinaryStringLabel("label", true)) }) } @@ -23,17 +65,115 @@ func TestNewBinaryStringLabel(t *testing.T) { "positive condition": { name: "labelname", condition: true, - expectedLabelValue: Yes, + expectedLabelValue: metrics.Yes, }, "negative condition": { name: "labelname", condition: false, - expectedLabelValue: No, + expectedLabelValue: metrics.No, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + label := metrics.NewBinaryStringLabel(tc.name, tc.condition) + require.Equal(t, tc.name, label.Name) + require.Equal(t, tc.expectedLabelValue, label.Value) + }) + } +} + +func TestGetLabelForBoolValue(t *testing.T) { + tests := map[string]struct { + name string + condition bool + expectedLabelValue string + }{ + "true": { + name: "labelname", + condition: true, + expectedLabelValue: "true", + }, + "false": { + name: "labelname", + condition: false, + expectedLabelValue: "false", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + label := metrics.GetLabelForBoolValue(tc.name, tc.condition) + require.Equal(t, tc.name, label.Name) + require.Equal(t, tc.expectedLabelValue, label.Value) + }) + } +} + +func TestGetLabelForIntValue(t *testing.T) { + tests := map[string]struct { + name string + value int + expectedLabelValue string + }{ + "min": { + name: "labelname", + value: math.MinInt, + expectedLabelValue: "-9223372036854775808", + }, + "negative": { + name: "labelname", + value: -1, + expectedLabelValue: "-1", + }, + "zero": { + name: "labelname", + value: 0, + expectedLabelValue: "0", + }, + "positive": { + name: "labelname", + value: 1, + expectedLabelValue: "1", + }, + "max": { + name: "labelname", + value: math.MaxInt, + expectedLabelValue: "9223372036854775807", }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { - label := NewBinaryStringLabel(tc.name, tc.condition) + label := metrics.GetLabelForIntValue(tc.name, tc.value) + require.Equal(t, tc.name, label.Name) + require.Equal(t, tc.expectedLabelValue, label.Value) + }) + } +} + +func TestGetLabelForStringValue(t *testing.T) { + tests := map[string]struct { + name string + value string + expectedLabelValue string + }{ + "empty": { + name: "labelname", + value: "", + expectedLabelValue: "", + }, + "short string": { + name: "labelname", + value: "abc", + expectedLabelValue: "abc", + }, + "long string": { + name: "labelname", + value: "abc def 2389209 lsdf ;'sdf';s#2", + expectedLabelValue: "abc def 2389209 lsdf ;'sdf';s#2", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + label := metrics.GetLabelForStringValue(tc.name, tc.value) require.Equal(t, tc.name, label.Name) require.Equal(t, tc.expectedLabelValue, label.Value) }) @@ -57,6 +197,10 @@ func TestGetMetricValueFromBigInt(t *testing.T) { input: big.NewInt(-1234), expected: float32(-1234), }, + "underflow": { + input: big.NewInt(math.MinInt), + expected: float32(-9.223372e+18), + }, "overflow": { input: new(big.Int).SetUint64(math.MaxUint64), expected: float32(1.8446744e+19), @@ -64,7 +208,57 @@ func TestGetMetricValueFromBigInt(t *testing.T) { } for name, tc := range tests { t.Run(name, func(t *testing.T) { - require.Equal(t, tc.expected, GetMetricValueFromBigInt(tc.input)) + require.Equal(t, tc.expected, metrics.GetMetricValueFromBigInt(tc.input)) }) } } + +func TestModuleMeasureSinceWithLabels(t *testing.T) { + defer gometrics.Shutdown() + + conf := gometrics.DefaultConfig("testService") + sink := gometrics.NewInmemSink(time.Hour, time.Hour) + _, err := gometrics.NewGlobal(conf, sink) + require.NoError(t, err) + + for i := 0; i < 3; i++ { + metrics.ModuleMeasureSinceWithLabels( + "testModule", + []string{"testKey1", "testKey2"}, + time.Now(), + []gometrics.Label{{ + Name: "testLabel", + Value: "testLabelValue", + }}, + ) + } + + found := false + for _, metrics := range sink.Data() { + metrics.RLock() + defer metrics.RUnlock() + + if metric, ok := metrics.Samples["testService.testKey1.testKey2;module=testModule;testLabel=testLabelValue"]; ok { + require.Equal(t, + []gometrics.Label{ + { + Name: "module", + Value: "testModule", + }, + { + Name: "testLabel", + Value: "testLabelValue", + }, + }, + metric.Labels) + require.Equal(t, 3, metric.Count) + // Since we can't inject time into gometrics we can't calculate the exact expected timing sample + // so we bound the value between 0 and 3 seconds assuming that hardware isn't so overloaded that + // executing this test takes longer than 3 seconds. + require.Less(t, 0.0, metric.Sum) + require.Greater(t, 3.0, metric.Sum) + found = true + } + } + require.True(t, found) +}