-
Notifications
You must be signed in to change notification settings - Fork 1
/
labels_matcher.go
130 lines (118 loc) · 2.61 KB
/
labels_matcher.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package promtable
import (
"regexp"
"sort"
"github.com/uschen/promtable/prompb"
)
// QueryMatchersToLabelsMatcher - qm must be sorted
func QueryMatchersToLabelsMatcher(qm []*prompb.LabelMatcher) (lsm LabelsMatcher, err error) {
if len(qm) == 0 {
return
}
for i := range qm {
lm, err := queryMatcherToLabelMatcher(qm[i])
if err != nil {
return nil, err
}
lsm = append(lsm, lm)
}
sort.Sort(lsm)
return
}
func queryMatcherToLabelMatcher(m *prompb.LabelMatcher) (*labelMatcher, error) {
var (
not bool
lv = m.Value
)
lm := &labelMatcher{
Name: m.Name,
Type: m.Type,
}
switch m.Type {
case prompb.LabelMatcher_NEQ:
lm.matchFunc = func(v string) bool {
return v != lv
}
case prompb.LabelMatcher_EQ:
lm.matchFunc = func(v string) bool {
return v == lv
}
case prompb.LabelMatcher_NRE:
not = true
fallthrough
case prompb.LabelMatcher_RE:
regexMatch, err := regexp.Compile(lv)
if err != nil {
return nil, err
}
if !not {
lm.matchFunc = func(v string) bool {
return regexMatch.MatchString(v)
}
} else {
lm.matchFunc = func(v string) bool {
return !regexMatch.MatchString(v)
}
}
}
return lm, nil
}
type valueMatchFunc func(value string) bool
// labelMatcher -
type labelMatcher struct {
Name string
Type prompb.LabelMatcher_Type
matchFunc valueMatchFunc
}
// LabelsMatcher - labelTester is sorted by name
type LabelsMatcher []*labelMatcher
func (m LabelsMatcher) Len() int { return len(m) }
func (m LabelsMatcher) Less(i, j int) bool { return m[i].Name < m[j].Name }
func (m LabelsMatcher) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
// Match - labels must be sorted
func (m LabelsMatcher) Match(labels []prompb.Label) (ok bool) {
if len(m) == 0 {
// nothing to match with
return true
}
if len(labels) == 0 {
// has matcher but no labels
// if all Not Type Matcher, we can return true
for i := range m {
if m[i].Type != prompb.LabelMatcher_NEQ && m[i].Type != prompb.LabelMatcher_NRE {
return false
}
}
return true
}
// every sinlge one of matchers has to be satisfied
// matchers: e e g h
// labels: c d e f g h i j k
var (
i, k int
)
for i < len(m) {
if m[i].Name < labels[k].Name {
return false
}
if m[i].Name == labels[k].Name {
if !m[i].matchFunc(labels[k].Value) {
// not match...
return false
}
// matched,
// the next matcher might have the same name, don't move k yet
k++
i++
continue
}
// >
if k == len(labels)-1 { // this ends main loop
// k is the last one already...
return false
}
// m.Name > label.Name, needs to bump k
k++
}
return true
}