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"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
)
|
)
|
||||||
|
@ -74,6 +76,9 @@ func NewMatcher(t MatchType, n, v string) (*Matcher, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Matcher) String() string {
|
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))
|
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()
|
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`,
|
value: `tab stop`,
|
||||||
want: `foo="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 {
|
for _, test := range tests {
|
||||||
|
|
Loading…
Reference in New Issue