diff --git a/tsweb/tsweb.go b/tsweb/tsweb.go index ab2cfe924..9e33806c1 100644 --- a/tsweb/tsweb.go +++ b/tsweb/tsweb.go @@ -364,18 +364,25 @@ func VarzHandler(w http.ResponseWriter, r *http.Request) { var dump func(prefix string, kv expvar.KeyValue) dump = func(prefix string, kv expvar.KeyValue) { - name := prefix + kv.Key - + key := kv.Key var typ string + var label string switch { case strings.HasPrefix(kv.Key, "gauge_"): typ = "gauge" - name = prefix + strings.TrimPrefix(kv.Key, "gauge_") + key = strings.TrimPrefix(kv.Key, "gauge_") case strings.HasPrefix(kv.Key, "counter_"): typ = "counter" - name = prefix + strings.TrimPrefix(kv.Key, "counter_") + key = strings.TrimPrefix(kv.Key, "counter_") + } + if strings.HasPrefix(key, "labelmap_") { + key = strings.TrimPrefix(key, "labelmap_") + if i := strings.Index(key, "_"); i != -1 { + label, key = key[:i], key[i+1:] + } } + name := prefix + key switch v := kv.Value.(type) { case *expvar.Int: @@ -422,6 +429,15 @@ func VarzHandler(w http.ResponseWriter, r *http.Request) { v.Do(func(kv expvar.KeyValue) { fmt.Fprintf(w, "%s{%s=%q} %v\n", name, v.Label, kv.Key, kv.Value) }) + case *expvar.Map: + if label != "" && typ != "" { + fmt.Fprintf(w, "# TYPE %s %s\n", name, typ) + v.Do(func(kv expvar.KeyValue) { + fmt.Fprintf(w, "%s{%s=%q} %v\n", name, label, kv.Key, kv.Value) + }) + } else { + fmt.Fprintf(w, "# skipping expvar.Map %q with incomplete metadata: label %q, Prometheus type %q\n", name, label, typ) + } } } expvarDo(func(kv expvar.KeyValue) { diff --git a/tsweb/tsweb_test.go b/tsweb/tsweb_test.go index f9bda99cc..584fdaf04 100644 --- a/tsweb/tsweb_test.go +++ b/tsweb/tsweb_test.go @@ -343,7 +343,7 @@ func TestVarzHandler(t *testing.T) { "# TYPE s_bar counter\ns_bar 2\n# TYPE s_foo counter\ns_foo 1\n", }, { - "metrics_set_TODO_guage_type", + "metrics_set_TODO_gauge_type", "gauge_s", // TODO(bradfitz): arguably a bug; should pass down type &metrics.Set{ Map: *(func() *expvar.Map { @@ -375,7 +375,7 @@ func TestVarzHandler(t *testing.T) { "# skipping expvar \"x\" (Go type expvar.Func returning float64) with undeclared Prometheus type\n", }, { - "label_map", + "metrics_label_map", "counter_m", &metrics.LabelMap{ Label: "label", @@ -389,6 +389,28 @@ func TestVarzHandler(t *testing.T) { }, "# TYPE m counter\nm{label=\"bar\"} 2\nm{label=\"foo\"} 1\n", }, + { + "expvar_label_map", + "counter_labelmap_keyname_m", + func() *expvar.Map { + m := new(expvar.Map) + m.Init() + m.Add("foo", 1) + m.Add("bar", 2) + return m + }(), + "# TYPE m counter\nm{keyname=\"bar\"} 2\nm{keyname=\"foo\"} 1\n", + }, + { + "expvar_label_map_malformed", + "counter_labelmap_lackslabel", + func() *expvar.Map { + m := new(expvar.Map) + m.Init() + return m + }(), + "# skipping expvar.Map \"lackslabel\" with incomplete metadata: label \"\", Prometheus type \"counter\"\n", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {