Files
metric/namespace_test.go
zooqueen 3e4215905c name a metric with no subsystem without a second separator
AppendNamespace returned namespace+"_" when the name was empty, and every
New*Vec calls it as AppendNamespace(opts.Namespace, opts.Subsystem) to build a
prefix that the caller then joins with another "_". A metric with a namespace
and no subsystem — coredns_build_info is one — therefore registered as
coredns__build_info, and nothing scraping for the name the caller asked for
could find it. Metrics WITH a subsystem were unaffected, which is why this hid:
coredns_cache_hits_total was there the whole time.

Tests pin both halves: the helper for each combination of empty sides, and the
name a CounterOpts actually resolves to. Both fail against the old behaviour
with exactly the doubled separator.
2026-08-10 21:21:04 -07:00

39 lines
1.2 KiB
Go

package metric
import "testing"
func TestAppendNamespace(t *testing.T) {
for _, tc := range []struct {
namespace, name, want string
}{
{"coredns", "cache", "coredns_cache"},
{"coredns", "", "coredns"}, // a namespace with no subsystem
{"", "cache", "cache"},
{"", "", ""},
} {
if got := AppendNamespace(tc.namespace, tc.name); got != tc.want {
t.Errorf("AppendNamespace(%q, %q) = %q, want %q", tc.namespace, tc.name, got, tc.want)
}
}
}
// TestVecNameWithoutSubsystem pins the name a metric is registered under when
// it declares a namespace and no subsystem. It used to gain a second separator
// from the empty subsystem — coredns__build_info — so a scrape for the name the
// caller asked for found nothing.
func TestVecNameWithoutSubsystem(t *testing.T) {
for _, tc := range []struct {
opts CounterOpts
want string
}{
{CounterOpts{Namespace: "coredns", Subsystem: "cache", Name: "hits_total"}, "coredns_cache_hits_total"},
{CounterOpts{Namespace: "coredns", Name: "build_info"}, "coredns_build_info"},
{CounterOpts{Name: "bare"}, "bare"},
} {
got := prefixedName(AppendNamespace(tc.opts.Namespace, tc.opts.Subsystem), tc.opts.Name)
if got != tc.want {
t.Errorf("name for %+v = %q, want %q", tc.opts, got, tc.want)
}
}
}