diff --git a/go.mod b/go.mod index 8e9da55..16b8425 100644 --- a/go.mod +++ b/go.mod @@ -11,4 +11,5 @@ require ( github.com/prometheus/procfs v0.0.0-20190519111021-9935e8e0588d // indirect github.com/yuin/gopher-lua v0.0.0-20181214045814-db9ae37725ec // indirect golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // indirect + golang.org/x/text v0.3.0 ) diff --git a/metric.go b/metric.go index 23eab0e..7bc5d17 100644 --- a/metric.go +++ b/metric.go @@ -5,6 +5,7 @@ import ( "log" "strconv" "strings" + "unicode/utf8" "github.com/prometheus/client_golang/prometheus" ) @@ -45,6 +46,10 @@ func infoCollect( ) []prometheus.Metric { var res []prometheus.Metric stats := parseInfo(info) + validLabelValues := make([]string, len(labelValues)) + for pos, lv := range labelValues { + validLabelValues[pos] = sanitizeLabelValue(lv) + } for key, m := range metrics { v, ok := stats[key] if !ok { @@ -58,12 +63,26 @@ func infoCollect( } res = append( res, - prometheus.MustNewConstMetric(m.desc, m.typ, f, labelValues...), + prometheus.MustNewConstMetric(m.desc, m.typ, f, validLabelValues...), ) } return res } +func sanitizeLabelValue(lv string) string { + if utf8.ValidString(lv) { + return lv + } + fixUtf := func(r rune) rune { + if r == utf8.RuneError { + return 65533 + } + return r + } + + return strings.Map(fixUtf, lv) +} + func parseInfo(s string) map[string]string { r := map[string]string{} for _, l := range strings.Split(s, ";") { diff --git a/metric_test.go b/metric_test.go index c1c1f2d..4706edd 100644 --- a/metric_test.go +++ b/metric_test.go @@ -44,6 +44,7 @@ func TestInfoCollect(t *testing.T) { payload string field string metric cmetric + labels []string want string } for n, c := range []cas{ @@ -103,9 +104,41 @@ func TestInfoCollect(t *testing.T) { }, want: `gauge: `, }, + { + payload: "counter-1=3.14:gauge-1=6.12:flag=true:counter-2=6.66", + field: "flag", + metric: cmetric{ + typ: prometheus.GaugeValue, + desc: prometheus.NewDesc( + "c1", + "My second flag", + []string{"namespace", "set"}, + nil, + ), + }, + //labels: []string{"ns", ""}, + labels: []string{"ns", "\xC0"}, + want: `label: label: gauge: `, + }, + { + payload: "counter-1=3.14:gauge-1=6.12:flag=true:counter-2=6.66", + field: "flag", + metric: cmetric{ + typ: prometheus.GaugeValue, + desc: prometheus.NewDesc( + "c1", + "My second flag", + []string{"namespace", "set"}, + nil, + ), + }, + //labels: []string{"ns", ""}, + labels: []string{"ns", "ӕ"}, + want: `label: label: gauge: `, + }, } { metrics := cmetrics{c.field: c.metric} - ms := infoCollect(metrics, c.payload) + ms := infoCollect(metrics, c.payload, c.labels...) if have, want := len(ms), 1; have != want { t.Fatalf("have %d, want %d", have, want) @@ -117,4 +150,4 @@ func TestInfoCollect(t *testing.T) { t.Errorf("case %d: have %q, want %q", n, have, want) } } -} +} \ No newline at end of file