-
Notifications
You must be signed in to change notification settings - Fork 152
/
escape.go
76 lines (69 loc) · 1.86 KB
/
escape.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package promql
import (
"github.com/influxdata/promql/v2"
"github.com/influxdata/promql/v2/pkg/labels"
)
func escapeLabelName(ln string) string {
switch {
case ln == "":
// This can occur in parameters to functions (e.g. label_replace() empty "src" parameter).
return ""
case ln == "__name__":
return "_field"
case ln[0] == '_' || ln[0] == '~':
return "~" + ln
default:
return ln
}
}
func UnescapeLabelName(ln string) string {
switch {
case ln == "_field":
return "__name__"
case ln[0] == '~':
return ln[1:]
default:
return ln
}
}
func escapeLabelNames(in []string) []string {
out := make([]string, len(in))
for i, ln := range in {
out[i] = escapeLabelName(ln)
}
return out
}
func escapeLabelMatchers(in []*labels.Matcher) []*labels.Matcher {
out := make([]*labels.Matcher, len(in))
var err error
for i, m := range in {
out[i], err = labels.NewMatcher(m.Type, escapeLabelName(m.Name), m.Value)
if err != nil {
panic("unable to create escaped label matcher")
}
}
return out
}
type labelNameEscaper struct{}
func (s labelNameEscaper) Visit(node promql.Node, path []promql.Node) (promql.Visitor, error) {
switch n := node.(type) {
case *promql.AggregateExpr:
n.Grouping = escapeLabelNames(n.Grouping)
case *promql.BinaryExpr:
if n.VectorMatching != nil {
n.VectorMatching.MatchingLabels = escapeLabelNames(n.VectorMatching.MatchingLabels)
n.VectorMatching.Include = escapeLabelNames(n.VectorMatching.Include)
}
case *promql.Call:
// Nothing to do here - there are only two functions that take label names
// as string parameters (label_replace() and label_join()), and those handle
// escaping by themselves.
case *promql.MatrixSelector:
n.Name = ""
n.LabelMatchers = escapeLabelMatchers(n.LabelMatchers)
case *promql.VectorSelector:
n.Name = ""
n.LabelMatchers = escapeLabelMatchers(n.LabelMatchers)
}
return s, nil
}