Skip to content

Commit d362766

Browse files
committed
Add matchers filtering field to rules api
Signed-off-by: Eunice Kim <[email protected]>
1 parent 505cdc2 commit d362766

File tree

5 files changed

+312
-50
lines changed

5 files changed

+312
-50
lines changed

pkg/ruler/api.go

+8
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,21 @@ func (a *API) PrometheusRules(w http.ResponseWriter, req *http.Request) {
147147
return
148148
}
149149

150+
_, err = parseMatchersParam(req.Form["match[]"])
151+
if err != nil {
152+
level.Error(logger).Log("msg", "error parsing match query params", "err", err)
153+
util_api.RespondError(logger, w, v1.ErrBadData, fmt.Sprintf("error parsing match params %s", err), http.StatusBadRequest)
154+
return
155+
}
156+
150157
rulesRequest := RulesRequest{
151158
RuleNames: req.Form["rule_name[]"],
152159
RuleGroupNames: req.Form["rule_group[]"],
153160
Files: req.Form["file[]"],
154161
Type: typ,
155162
State: state,
156163
Health: health,
164+
Matches: req.Form["match[]"],
157165
}
158166

159167
w.Header().Set("Content-Type", "application/json")

pkg/ruler/ruler.go

+50
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,10 @@ func (r *Ruler) getLocalRules(userID string, rulesRequest RulesRequest, includeB
884884
ruleType := rulesRequest.Type
885885
alertState := rulesRequest.State
886886
health := rulesRequest.Health
887+
matcherSets, err := parseMatchersParam(rulesRequest.Matches)
888+
if err != nil {
889+
return nil, errors.Wrap(err, "error parsing matcher values")
890+
}
887891

888892
returnAlerts := ruleType == "" || ruleType == alertingRuleFilter
889893
returnRecording := (ruleType == "" || ruleType == recordingRuleFilter) && alertState == ""
@@ -928,6 +932,9 @@ func (r *Ruler) getLocalRules(userID string, rulesRequest RulesRequest, includeB
928932
if !returnByHealth(health, string(r.Health())) {
929933
continue
930934
}
935+
if !matches(matcherSets, r.Labels()) {
936+
continue
937+
}
931938
lastError := ""
932939
if r.LastError() != nil {
933940
lastError = r.LastError().Error()
@@ -1009,6 +1016,7 @@ func (r *Ruler) getLocalRules(userID string, rulesRequest RulesRequest, includeB
10091016
fileSet,
10101017
returnAlerts,
10111018
returnRecording,
1019+
matcherSets,
10121020
})
10131021
if err != nil {
10141022
return nil, err
@@ -1023,6 +1031,7 @@ type groupListFilter struct {
10231031
fileSet map[string]struct{}
10241032
returnAlerts bool
10251033
returnRecording bool
1034+
matcherSets [][]*labels.Matcher
10261035
}
10271036

10281037
// ruleGroupListToGroupStateDesc converts rulespb.RuleGroupList to []*GroupStateDesc while accepting filters to control what goes to the
@@ -1068,6 +1077,9 @@ func (r *Ruler) ruleGroupListToGroupStateDesc(userID string, backupGroups rulesp
10681077
continue
10691078
}
10701079
}
1080+
if !matches(filters.matcherSets, cortexpb.FromLabelAdaptersToLabels(r.Labels)) {
1081+
continue
1082+
}
10711083

10721084
var ruleDesc *RuleStateDesc
10731085
query, err := parser.ParseExpr(r.GetExpr())
@@ -1162,6 +1174,7 @@ func (r *Ruler) getShardedRules(ctx context.Context, userID string, rulesRequest
11621174
RuleGroupNames: rulesRequest.GetRuleGroupNames(),
11631175
Files: rulesRequest.GetFiles(),
11641176
Type: rulesRequest.GetType(),
1177+
Matches: rulesRequest.GetMatches(),
11651178
})
11661179

11671180
if err != nil {
@@ -1320,3 +1333,40 @@ func returnByState(requestState string, alertState string) bool {
13201333
func returnByHealth(requestHealth string, ruleHealth string) bool {
13211334
return requestHealth == "" || requestHealth == ruleHealth
13221335
}
1336+
1337+
func parseMatchersParam(matchers []string) ([][]*labels.Matcher, error) {
1338+
var matcherSets [][]*labels.Matcher
1339+
for _, s := range matchers {
1340+
matchers, err := parser.ParseMetricSelector(s)
1341+
if err != nil {
1342+
return nil, err
1343+
}
1344+
matcherSets = append(matcherSets, matchers)
1345+
}
1346+
1347+
OUTER:
1348+
for _, ms := range matcherSets {
1349+
for _, lm := range ms {
1350+
if lm != nil && !lm.Matches("") {
1351+
continue OUTER
1352+
}
1353+
}
1354+
return nil, errors.New("match[] must contain at least one non-empty matcher")
1355+
}
1356+
return matcherSets, nil
1357+
}
1358+
1359+
func matches(matcherSets [][]*labels.Matcher, l labels.Labels) bool {
1360+
if len(matcherSets) == 0 {
1361+
return true
1362+
}
1363+
1364+
for _, matchers := range matcherSets {
1365+
for _, m := range matchers {
1366+
if v := l.Get(m.Name); m.Matches(v) {
1367+
return true
1368+
}
1369+
}
1370+
}
1371+
return false
1372+
}

pkg/ruler/ruler.pb.go

+116-50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/ruler/ruler.proto

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ message RulesRequest {
2626
string type = 4;
2727
string state = 5;
2828
string health = 6;
29+
repeated string matches = 7;
2930
}
3031

3132
message RulesResponse {

0 commit comments

Comments
 (0)