diff --git a/pkg/textparse/parse.go b/pkg/textparse/parse.go index b9f7ed6a2..4783bc580 100644 --- a/pkg/textparse/parse.go +++ b/pkg/textparse/parse.go @@ -21,6 +21,7 @@ import ( "errors" "io" "sort" + "strings" "unsafe" "github.com/prometheus/prometheus/pkg/labels" @@ -123,6 +124,12 @@ func (p *Parser) Metric(l *labels.Labels) string { c := p.l.offsets[i+2] - p.l.mstart d := p.l.offsets[i+3] - p.l.mstart + // Replacer causes allocations. Replace only when necessary. + if strings.IndexByte(s[c:d], byte('\\')) >= 0 { + *l = append(*l, labels.Label{Name: s[a:b], Value: replacer.Replace(s[c:d])}) + continue + } + *l = append(*l, labels.Label{Name: s[a:b], Value: s[c:d]}) } @@ -131,6 +138,14 @@ func (p *Parser) Metric(l *labels.Labels) string { return s } +var replacer = strings.NewReplacer( + `\"`, `"`, + `\\`, `\`, + `\n`, ` +`, + `\t`, ` `, +) + func yoloString(b []byte) string { return *((*string)(unsafe.Pointer(&b))) } diff --git a/pkg/textparse/parse_test.go b/pkg/textparse/parse_test.go index 25e11ef1f..9018a086d 100644 --- a/pkg/textparse/parse_test.go +++ b/pkg/textparse/parse_test.go @@ -45,7 +45,8 @@ some:aggregate:rate5m{a_b="c"} 1 # TYPE go_goroutines gauge go_goroutines 33 123123 _metric_starting_with_underscore 1 -testmetric{_label_starting_with_underscore="foo"} 1` +testmetric{_label_starting_with_underscore="foo"} 1 +testmetric{label="\"bar\""} 1` input += "\nnull_byte_metric{a=\"abc\x00\"} 1" int64p := func(x int64) *int64 { return &x } @@ -113,6 +114,10 @@ testmetric{_label_starting_with_underscore="foo"} 1` m: "testmetric{_label_starting_with_underscore=\"foo\"}", v: 1, lset: labels.FromStrings("__name__", "testmetric", "_label_starting_with_underscore", "foo"), + }, { + m: "testmetric{label=\"\\\"bar\\\"\"}", + v: 1, + lset: labels.FromStrings("__name__", "testmetric", "label", `"bar"`), }, { m: "null_byte_metric{a=\"abc\x00\"}", v: 1,