File: //proc/thread-self/root/opt/go/pkg/mod/github.com/armon/
[email protected]/inmem_test.go
package metrics
import (
"math"
"net/url"
"strings"
"testing"
"time"
)
func TestInmemSink(t *testing.T) {
inm := NewInmemSink(10*time.Millisecond, 50*time.Millisecond)
data := inm.Data()
if len(data) != 1 {
t.Fatalf("bad: %v", data)
}
// Add data points
inm.SetGauge([]string{"foo", "bar"}, 42)
inm.SetGaugeWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}})
inm.EmitKey([]string{"foo", "bar"}, 42)
inm.IncrCounter([]string{"foo", "bar"}, 20)
inm.IncrCounter([]string{"foo", "bar"}, 22)
inm.IncrCounterWithLabels([]string{"foo", "bar"}, 20, []Label{{"a", "b"}})
inm.IncrCounterWithLabels([]string{"foo", "bar"}, 22, []Label{{"a", "b"}})
inm.AddSample([]string{"foo", "bar"}, 20)
inm.AddSample([]string{"foo", "bar"}, 22)
inm.AddSampleWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}})
data = inm.Data()
if len(data) != 1 {
t.Fatalf("bad: %v", data)
}
intvM := data[0]
intvM.RLock()
if time.Now().Sub(intvM.Interval) > 10*time.Millisecond {
t.Fatalf("interval too old")
}
if intvM.Gauges["foo.bar"].Value != 42 {
t.Fatalf("bad val: %v", intvM.Gauges)
}
if intvM.Gauges["foo.bar;a=b"].Value != 23 {
t.Fatalf("bad val: %v", intvM.Gauges)
}
if intvM.Points["foo.bar"][0] != 42 {
t.Fatalf("bad val: %v", intvM.Points)
}
for _, agg := range []SampledValue{intvM.Counters["foo.bar"], intvM.Counters["foo.bar;a=b"]} {
if agg.Count != 2 {
t.Fatalf("bad val: %v", agg)
}
if agg.Rate != 4200 {
t.Fatalf("bad val: %v", agg.Rate)
}
if agg.Sum != 42 {
t.Fatalf("bad val: %v", agg)
}
if agg.SumSq != 884 {
t.Fatalf("bad val: %v", agg)
}
if agg.Min != 20 {
t.Fatalf("bad val: %v", agg)
}
if agg.Max != 22 {
t.Fatalf("bad val: %v", agg)
}
if agg.AggregateSample.Mean() != 21 {
t.Fatalf("bad val: %v", agg)
}
if agg.AggregateSample.Stddev() != math.Sqrt(2) {
t.Fatalf("bad val: %v", agg)
}
if agg.LastUpdated.IsZero() {
t.Fatalf("agg.LastUpdated is not set: %v", agg)
}
diff := time.Now().Sub(agg.LastUpdated).Seconds()
if diff > 1 {
t.Fatalf("time diff too great: %f", diff)
}
}
if _, ok := intvM.Samples["foo.bar"]; !ok {
t.Fatalf("missing sample")
}
if _, ok := intvM.Samples["foo.bar;a=b"]; !ok {
t.Fatalf("missing sample")
}
intvM.RUnlock()
for i := 1; i < 10; i++ {
time.Sleep(10 * time.Millisecond)
inm.SetGauge([]string{"foo", "bar"}, 42)
data = inm.Data()
if len(data) != min(i+1, 5) {
t.Fatalf("bad: %v", data)
}
}
// Should not exceed 5 intervals!
time.Sleep(10 * time.Millisecond)
inm.SetGauge([]string{"foo", "bar"}, 42)
data = inm.Data()
if len(data) != 5 {
t.Fatalf("bad: %v", data)
}
}
func TestNewInmemSinkFromURL(t *testing.T) {
for _, tc := range []struct {
desc string
input string
expectErr string
expectInterval time.Duration
expectRetain time.Duration
}{
{
desc: "interval and duration are set via query params",
input: "inmem://?interval=11s&retain=22s",
expectInterval: duration(t, "11s"),
expectRetain: duration(t, "22s"),
},
{
desc: "interval is required",
input: "inmem://?retain=22s",
expectErr: "Bad 'interval' param",
},
{
desc: "interval must be a duration",
input: "inmem://?retain=30s&interval=HIYA",
expectErr: "Bad 'interval' param",
},
{
desc: "retain is required",
input: "inmem://?interval=30s",
expectErr: "Bad 'retain' param",
},
{
desc: "retain must be a valid duration",
input: "inmem://?interval=30s&retain=HELLO",
expectErr: "Bad 'retain' param",
},
} {
t.Run(tc.desc, func(t *testing.T) {
u, err := url.Parse(tc.input)
if err != nil {
t.Fatalf("error parsing URL: %s", err)
}
ms, err := NewInmemSinkFromURL(u)
if tc.expectErr != "" {
if !strings.Contains(err.Error(), tc.expectErr) {
t.Fatalf("expected err: %q, to contain: %q", err, tc.expectErr)
}
} else {
if err != nil {
t.Fatalf("unexpected err: %s", err)
}
is := ms.(*InmemSink)
if is.interval != tc.expectInterval {
t.Fatalf("expected interval %s, got: %s", tc.expectInterval, is.interval)
}
if is.retain != tc.expectRetain {
t.Fatalf("expected retain %s, got: %s", tc.expectRetain, is.retain)
}
}
})
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func duration(t *testing.T, s string) time.Duration {
dur, err := time.ParseDuration(s)
if err != nil {
t.Fatalf("error parsing duration: %s", err)
}
return dur
}