tsweb/varz: only export numeric expvar.Map values
Currently the expvar exporter attempts to write expvar.String, which breaks the Prometheus metric page. Updates tailscale/corp#36552 Signed-off-by: Anton Tolchanov <anton@tailscale.com>
This commit is contained in:
committed by
Anton Tolchanov
parent
de4a8dbcfc
commit
826fd544cc
+12
-2
@@ -245,11 +245,21 @@ func writePromExpVar(w io.Writer, prefix string, kv expvar.KeyValue) {
|
|||||||
if label != "" && typ != "" {
|
if label != "" && typ != "" {
|
||||||
fmt.Fprintf(w, "# TYPE %s %s\n", name, typ)
|
fmt.Fprintf(w, "# TYPE %s %s\n", name, typ)
|
||||||
v.Do(func(kv expvar.KeyValue) {
|
v.Do(func(kv expvar.KeyValue) {
|
||||||
fmt.Fprintf(w, "%s{%s=%q} %v\n", name, label, kv.Key, kv.Value)
|
switch kv.Value.(type) {
|
||||||
|
case *expvar.Int, *expvar.Float:
|
||||||
|
fmt.Fprintf(w, "%s{%s=%q} %v\n", name, label, kv.Key, kv.Value)
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(w, "# skipping %q expvar map key %q with unknown value type %T\n", name, kv.Key, kv.Value)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
v.Do(func(kv expvar.KeyValue) {
|
v.Do(func(kv expvar.KeyValue) {
|
||||||
fmt.Fprintf(w, "%s_%s %v\n", name, kv.Key, kv.Value)
|
switch kv.Value.(type) {
|
||||||
|
case *expvar.Int, *expvar.Float:
|
||||||
|
fmt.Fprintf(w, "%s_%s %v\n", name, kv.Key, kv.Value)
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(w, "# skipping %q expvar map key %q with unknown value type %T\n", name, kv.Key, kv.Value)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,6 +180,43 @@ func TestVarzHandler(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"# TYPE m counter\nm{label=\"bar\"} 2\nm{label=\"foo\"} 1\n",
|
"# TYPE m counter\nm{label=\"bar\"} 2\nm{label=\"foo\"} 1\n",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"metrics_label_map_float",
|
||||||
|
"float_map",
|
||||||
|
func() *expvar.Map {
|
||||||
|
m := new(expvar.Map)
|
||||||
|
m.Init()
|
||||||
|
f := new(expvar.Float)
|
||||||
|
f.Set(1.5)
|
||||||
|
m.Set("a", f)
|
||||||
|
return m
|
||||||
|
}(),
|
||||||
|
"float_map_a 1.5\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metrics_label_map_int",
|
||||||
|
"int_map",
|
||||||
|
func() *expvar.Map {
|
||||||
|
m := new(expvar.Map)
|
||||||
|
m.Init()
|
||||||
|
f := new(expvar.Int)
|
||||||
|
f.Set(55)
|
||||||
|
m.Set("a", f)
|
||||||
|
return m
|
||||||
|
}(),
|
||||||
|
"int_map_a 55\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metrics_label_map_string",
|
||||||
|
"string_map",
|
||||||
|
func() *expvar.Map {
|
||||||
|
m := new(expvar.Map)
|
||||||
|
m.Init()
|
||||||
|
m.Set("a", expvar.NewString("foo"))
|
||||||
|
return m
|
||||||
|
}(),
|
||||||
|
"# skipping \"string_map\" expvar map key \"a\" with unknown value type *expvar.String\n",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"metrics_label_map_untyped",
|
"metrics_label_map_untyped",
|
||||||
"control_save_config",
|
"control_save_config",
|
||||||
@@ -298,6 +335,12 @@ foo_foo_b 1
|
|||||||
api_status_code 42
|
api_status_code 42
|
||||||
`) + "\n",
|
`) + "\n",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"string_expvar_is_not_exported",
|
||||||
|
"foo_string",
|
||||||
|
new(expvar.String),
|
||||||
|
"# skipping expvar \"foo_string\" (Go type *expvar.String) with undeclared Prometheus type\n",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user