// Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause package metrics import ( "bytes" "fmt" "io" "testing" ) type L2 struct { Foo string `prom:"foo"` Bar string `prom:"bar"` } func TestMultilabelMap(t *testing.T) { m := new(MultiLabelMap[L2]) m.Add(L2{"a", "b"}, 2) m.Add(L2{"b", "c"}, 4) m.Add(L2{"b", "b"}, 3) m.Add(L2{"a", "a"}, 1) cur := func() string { var buf bytes.Buffer m.Do(func(kv KeyValue[L2]) { if buf.Len() > 0 { buf.WriteString(",") } fmt.Fprintf(&buf, "%s/%s=%v", kv.Key.Foo, kv.Key.Bar, kv.Value) }) return buf.String() } if g, w := cur(), "a/a=1,a/b=2,b/b=3,b/c=4"; g != w { t.Errorf("got %q; want %q", g, w) } var buf bytes.Buffer m.WritePrometheus(&buf, "metricname") const want = `metricname{foo="a",bar="a"} 1 metricname{foo="a",bar="b"} 2 metricname{foo="b",bar="b"} 3 metricname{foo="b",bar="c"} 4 ` if got := buf.String(); got != want { t.Errorf("promtheus output = %q; want %q", got, want) } m.Delete(L2{"b", "b"}) if g, w := cur(), "a/a=1,a/b=2,b/c=4"; g != w { t.Errorf("got %q; want %q", g, w) } allocs := testing.AllocsPerRun(1000, func() { m.Add(L2{"a", "a"}, 1) }) if allocs > 0 { t.Errorf("allocs = %v; want 0", allocs) } m.Init() if g, w := cur(), ""; g != w { t.Errorf("got %q; want %q", g, w) } writeAllocs := testing.AllocsPerRun(1000, func() { m.WritePrometheus(io.Discard, "test") }) if writeAllocs > 0 { t.Errorf("writeAllocs = %v; want 0", writeAllocs) } } func TestMultiLabelMapTypes(t *testing.T) { type LabelTypes struct { S string B bool I int U uint } m := new(MultiLabelMap[LabelTypes]) m.Type = "counter" m.Help = "some good stuff" m.Add(LabelTypes{"a", true, -1, 2}, 3) var buf bytes.Buffer m.WritePrometheus(&buf, "metricname") const want = `# TYPE metricname counter # HELP metricname some good stuff metricname{s="a",b="true",i="-1",u="2"} 3 ` if got := buf.String(); got != want { t.Errorf("got %q; want %q", got, want) } writeAllocs := testing.AllocsPerRun(1000, func() { m.WritePrometheus(io.Discard, "test") }) if writeAllocs > 0 { t.Errorf("writeAllocs = %v; want 0", writeAllocs) } } func BenchmarkMultiLabelWriteAllocs(b *testing.B) { b.ReportAllocs() m := new(MultiLabelMap[L2]) m.Add(L2{"a", "b"}, 2) m.Add(L2{"b", "c"}, 4) m.Add(L2{"b", "b"}, 3) m.Add(L2{"a", "a"}, 1) var w io.Writer = io.Discard b.ResetTimer() for range b.N { m.WritePrometheus(w, "test") } }