Support UTF-8 label matchers: Update Stringer for non-Prometheus compliant label names (#3580)
* Update Stringer for non-Prometheus compliant label names This commit updates the String method to print non-Prometheus compliant label names in a format that can be parsed in the UTF-8 parser. Such inputs are never valid in the classic parser. If the label name is Prometheus compliant, it is still printed unquoted. Signed-off-by: George Robinson <george.robinson@grafana.co --------- Signed-off-by: George Robinson <george.robinson@grafana.com>
This commit is contained in:
parent
716830a56f
commit
9dbc8b6b91
|
@ -18,7 +18,9 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
@ -74,6 +76,9 @@ func NewMatcher(t MatchType, n, v string) (*Matcher, error) {
|
|||
}
|
||||
|
||||
func (m *Matcher) String() string {
|
||||
if strings.ContainsFunc(m.Name, isReserved) {
|
||||
return fmt.Sprintf(`%s%s%s`, strconv.Quote(m.Name), m.Type, strconv.Quote(m.Value))
|
||||
}
|
||||
return fmt.Sprintf(`%s%s"%s"`, m.Name, m.Type, openMetricsEscape(m.Value))
|
||||
}
|
||||
|
||||
|
@ -199,3 +204,13 @@ func (ms Matchers) String() string {
|
|||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// This is copied from matchers/parse/lexer.go. It will be removed when
|
||||
// the transition window from classic matchers to UTF-8 matchers is complete,
|
||||
// as then we can use double quotes when printing the label name for all
|
||||
// matchers. Until then, the classic parser does not understand double quotes
|
||||
// around the label name, so we use this function as a heuristic to tell if
|
||||
// the matcher was parsed with the UTF-8 parser or the classic parser.
|
||||
func isReserved(r rune) bool {
|
||||
return unicode.IsSpace(r) || strings.ContainsRune("{}!=~,\\\"'`", r)
|
||||
}
|
||||
|
|
|
@ -182,6 +182,30 @@ line`,
|
|||
value: `tab stop`,
|
||||
want: `foo="tab stop"`,
|
||||
},
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchEqual,
|
||||
value: `🙂`,
|
||||
want: `foo="🙂"`,
|
||||
},
|
||||
{
|
||||
name: `foo!`,
|
||||
op: MatchNotEqual,
|
||||
value: `bar`,
|
||||
want: `"foo!"!="bar"`,
|
||||
},
|
||||
{
|
||||
name: `foo🙂`,
|
||||
op: MatchEqual,
|
||||
value: `bar`,
|
||||
want: `foo🙂="bar"`,
|
||||
},
|
||||
{
|
||||
name: `foo bar`,
|
||||
op: MatchEqual,
|
||||
value: `baz`,
|
||||
want: `"foo bar"="baz"`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
Loading…
Reference in New Issue