| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package metricsutil |
| |
| import ( |
| "testing" |
| "time" |
| |
| "github.com/armon/go-metrics" |
| ) |
| |
| func isLabelPresent(toFind Label, ls []Label) bool { |
| for _, l := range ls { |
| if l == toFind { |
| return true |
| } |
| } |
| return false |
| } |
| |
| // We can use a sink directly, or wrap the top-level |
| // go-metrics implementation for testing purposes. |
| func defaultMetrics(sink metrics.MetricSink) *metrics.Metrics { |
| // No service name |
| config := metrics.DefaultConfig("") |
| |
| // No host name |
| config.EnableHostname = false |
| m, _ := metrics.New(config, sink) |
| return m |
| } |
| |
| func TestClusterLabelPresent(t *testing.T) { |
| testClusterName := "test-cluster" |
| |
| // Use a ridiculously long time to minimize the chance |
| // that we have to deal with more than one interval. |
| // InMemSink rounds down to an interval boundary rather than |
| // starting one at the time of initialization. |
| inmemSink := metrics.NewInmemSink( |
| 1000000*time.Hour, |
| 2000000*time.Hour) |
| clusterSink := NewClusterMetricSink(testClusterName, defaultMetrics(inmemSink)) |
| |
| key1 := []string{"aaa", "bbb"} |
| key2 := []string{"ccc", "ddd"} |
| key3 := []string{"eee", "fff"} |
| labels1 := []Label{{"dim1", "val1"}} |
| labels2 := []Label{{"dim2", "val2"}} |
| labels3 := []Label{{"dim3", "val3"}} |
| clusterLabel := Label{"cluster", testClusterName} |
| expectedKey1 := "aaa.bbb;dim1=val1;cluster=" + testClusterName |
| expectedKey2 := "ccc.ddd;dim2=val2;cluster=" + testClusterName |
| expectedKey3 := "eee.fff;dim3=val3;cluster=" + testClusterName |
| |
| clusterSink.SetGaugeWithLabels(key1, 1.0, labels1) |
| clusterSink.IncrCounterWithLabels(key2, 2.0, labels2) |
| clusterSink.AddSampleWithLabels(key3, 3.0, labels3) |
| |
| intervals := inmemSink.Data() |
| // If we start very close to the end of an interval, then our metrics might be |
| // split across two different buckets. We won't write the code to try to handle that. |
| // 100000-hours = at most once every 4167 days |
| if len(intervals) > 1 { |
| t.Skip("Detected interval crossing.") |
| } |
| |
| // Check Gauge |
| g, ok := intervals[0].Gauges[expectedKey1] |
| if !ok { |
| t.Fatal("Key", expectedKey1, "not found in map", intervals[0].Gauges) |
| } |
| if g.Value != 1.0 { |
| t.Error("Gauge value", g.Value, "does not match", 1.0) |
| } |
| if !isLabelPresent(labels1[0], g.Labels) { |
| t.Error("Gauge label", g.Labels, "does not include", labels1) |
| } |
| if !isLabelPresent(clusterLabel, g.Labels) { |
| t.Error("Gauge label", g.Labels, "does not include", clusterLabel) |
| } |
| |
| // Check Counter |
| c, ok := intervals[0].Counters[expectedKey2] |
| if !ok { |
| t.Fatal("Key", expectedKey2, "not found in map", intervals[0].Counters) |
| } |
| if c.Sum != 2.0 { |
| t.Error("Counter value", c.Sum, "does not match", 2.0) |
| } |
| if !isLabelPresent(labels2[0], c.Labels) { |
| t.Error("Counter label", c.Labels, "does not include", labels2) |
| } |
| if !isLabelPresent(clusterLabel, c.Labels) { |
| t.Error("Counter label", c.Labels, "does not include", clusterLabel) |
| } |
| |
| // Check Sample |
| s, ok := intervals[0].Samples[expectedKey3] |
| if !ok { |
| t.Fatal("Key", expectedKey3, "not found in map", intervals[0].Samples) |
| } |
| if s.Sum != 3.0 { |
| t.Error("Sample value", s.Sum, "does not match", 3.0) |
| } |
| if !isLabelPresent(labels3[0], s.Labels) { |
| t.Error("Sample label", s.Labels, "does not include", labels3) |
| } |
| if !isLabelPresent(clusterLabel, s.Labels) { |
| t.Error("Sample label", s.Labels, "does not include", clusterLabel) |
| } |
| } |