diff --git a/prometheus/registry.go b/prometheus/registry.go index 34aa3b3..1e84531 100644 --- a/prometheus/registry.go +++ b/prometheus/registry.go @@ -23,6 +23,8 @@ import ( "github.com/golang/protobuf/proto" + "unicode/utf8" + dto "github.com/prometheus/client_model/go" ) @@ -679,6 +681,12 @@ func checkMetricConsistency( ) } + for _, labelPair := range dtoMetric.GetLabel() { + if !utf8.ValidString(*labelPair.Value) { + return fmt.Errorf("collected metric's label %s is not utf8: %#v", *labelPair.Name, *labelPair.Value) + } + } + // Is the metric unique (i.e. no other metric with the same name and the same label values)? h := hashNew() h = hashAdd(h, metricFamily.GetName()) diff --git a/prometheus/registry_test.go b/prometheus/registry_test.go index d016a15..d136bba 100644 --- a/prometheus/registry_test.go +++ b/prometheus/registry_test.go @@ -209,6 +209,34 @@ metric: < expectedMetricFamilyMergedWithExternalAsProtoCompactText := []byte(`name:"name" help:"docstring" type:COUNTER metric: label: counter: > metric: label: counter: > metric: label: counter: > `) + externalMetricFamilyWithInvalidLabelValue := &dto.MetricFamily{ + Name: proto.String("name"), + Help: proto.String("docstring"), + Type: dto.MetricType_COUNTER.Enum(), + Metric: []*dto.Metric{ + { + Label: []*dto.LabelPair{ + { + Name: proto.String("constname"), + Value: proto.String("\xFF"), + }, + { + Name: proto.String("labelname"), + Value: proto.String("different_val"), + }, + }, + Counter: &dto.Counter{ + Value: proto.Float64(42), + }, + }, + }, + } + + expectedMetricFamilyInvalidLabelValueAsText := []byte(`An error has occurred during metrics gathering: + +collected metric's label constname is not utf8: "\xff" +`) + type output struct { headers map[string]string body []byte @@ -452,6 +480,22 @@ metric: < externalMetricFamilyWithSameName, }, }, + { // 16 + headers: map[string]string{ + "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=compact-text", + }, + out: output{ + headers: map[string]string{ + "Content-Type": `text/plain; charset=utf-8`, + }, + body: expectedMetricFamilyInvalidLabelValueAsText, + }, + collector: metricVec, + externalMF: []*dto.MetricFamily{ + externalMetricFamily, + externalMetricFamilyWithInvalidLabelValue, + }, + }, } for i, scenario := range scenarios { registry := prometheus.NewPedanticRegistry()