add label_matcher param to filter alerts (#5353)

Signed-off-by: junot <junotxiang@kubesphere.io>

Signed-off-by: junot <junotxiang@kubesphere.io>
This commit is contained in:
junot
2022-11-08 11:15:26 +08:00
committed by GitHub
parent ea694684a0
commit 2b37422645
3 changed files with 40 additions and 6 deletions

View File

@@ -35,6 +35,7 @@ const (
// for alert
FieldAlertLabelFilters = "label_filters"
FieldAlertActiveAt = "activeAt"
FieldAlertLabelMatcher = "label_matcher"
)
var SortableFields = []string{

View File

@@ -66,6 +66,7 @@ func AddToContainer(container *restful.Container, informers informers.InformerFa
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, one of `activeAt`. e.g. orderBy=activeAt")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldState, "state, one of `firing`, `pending`")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldAlertLabelFilters, "label filters, concatenating multiple filters with commas, equal symbol for exact query, wave symbol for fuzzy query e.g. name~a").DataFormat("key=%s,key~%s")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldAlertLabelMatcher, "label matcher to match alert labels, follow prometheus matcher format. e.g. `{label_name1=\"valueA\",label_name2=~\"valueB|valueC\"}`")).
Returns(http.StatusOK, kapi.StatusOK, kapi.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AlertingTag}))
@@ -96,6 +97,7 @@ func AddToContainer(container *restful.Container, informers informers.InformerFa
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, one of `activeAt`. e.g. orderBy=activeAt")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldState, "state, one of `firing`, `pending`")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldAlertLabelFilters, "label filters, concatenating multiple filters with commas, equal symbol for exact query, wave symbol for fuzzy query e.g. name~a").DataFormat("key=%s,key~%s")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldAlertLabelMatcher, "label matcher to match alert labels, follow prometheus matcher format. e.g. `{label_name1=\"valueA\",label_name2=~\"valueB|valueC\"}`")).
Returns(http.StatusOK, kapi.StatusOK, kapi.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AlertingTag}))
@@ -120,13 +122,14 @@ func AddToContainer(container *restful.Container, informers informers.InformerFa
ws.Route(ws.GET("/globalalerts").
To(handler.handleListGlobalAlerts).
Doc("list the alerts of globalrulegroups in the cluster").
Doc("list the alerts of globalrulegroups").
Param(ws.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d").DefaultValue("page=1")).
Param(ws.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(ws.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("ascending=false")).
Param(ws.QueryParameter(query.ParameterOrderBy, "sort parameters, one of `activeAt`. e.g. orderBy=activeAt")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldState, "state, one of `firing`, `pending`")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldAlertLabelFilters, "label filters, concatenating multiple filters with commas, equal symbol for exact query, wave symbol for fuzzy query e.g. name~a").DataFormat("key=%s,key~%s")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldAlertLabelMatcher, "label matcher to match alert labels, follow prometheus matcher format. e.g. `{label_name1=\"valueA\",label_name2=~\"valueB|valueC\"}`")).
Param(ws.QueryParameter(kapialertingv2beta1.FieldBuiltin, "filter alerts, `true` for alerts from built-in rule groups and `false` for alerts from custom rule groups")).
Returns(http.StatusOK, kapi.StatusOK, kapi.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AlertingTag}))

View File

@@ -16,9 +16,11 @@ package alerting
import (
"context"
"fmt"
"time"
promlabels "github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/promql/parser"
promrules "github.com/prometheus/prometheus/rules"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
@@ -243,7 +245,10 @@ func (o *ruleGroupOperator) ListAlerts(ctx context.Context, namespace string,
}
}
filterAlert := o.createFilterAlertFunc(queryParam)
filterAlert, err := o.createFilterAlertFunc(queryParam)
if err != nil {
return nil, err
}
listResult := resources.DefaultList(alerts, queryParam, func(left, right runtime.Object, field query.Field) bool {
return o.compareAlert(&left.(*wrapAlert).Alert, &right.(*wrapAlert).Alert, field)
}, func(obj runtime.Object, filter query.Filter) bool {
@@ -269,12 +274,20 @@ func (d *ruleGroupOperator) compareAlert(left, right *kapialertingv2beta1.Alert,
return false
}
func (d *ruleGroupOperator) createFilterAlertFunc(queryParam *query.Query) func(alert *kapialertingv2beta1.Alert, filter query.Filter) bool {
func (d *ruleGroupOperator) createFilterAlertFunc(queryParam *query.Query) (func(alert *kapialertingv2beta1.Alert, filter query.Filter) bool, error) {
var labelFilters kapialertingv2beta1.LabelFilters
var labelMatchers []*promlabels.Matcher
var err error
if len(queryParam.Filters) > 0 {
if filters, ok := queryParam.Filters[kapialertingv2beta1.FieldAlertLabelFilters]; ok {
labelFilters = kapialertingv2beta1.ParseLabelFilters(string(filters))
}
if matcherStr, ok := queryParam.Filters[kapialertingv2beta1.FieldAlertLabelMatcher]; ok {
labelMatchers, err = parser.ParseMetricSelector(string(matcherStr))
if err != nil {
return nil, fmt.Errorf("invalid %s param: %v", kapialertingv2beta1.FieldAlertLabelMatcher, err)
}
}
}
return func(alert *kapialertingv2beta1.Alert, filter query.Filter) bool {
switch filter.Field {
@@ -283,11 +296,22 @@ func (d *ruleGroupOperator) createFilterAlertFunc(queryParam *query.Query) func(
return true
}
return labelFilters.Matches(alert.Labels)
case kapialertingv2beta1.FieldAlertLabelMatcher:
for _, m := range labelMatchers {
var v string
if len(alert.Labels) > 0 {
v = alert.Labels[m.Name]
}
if !m.Matches(v) {
return false
}
}
return true
case kapialertingv2beta1.FieldState:
return alert.State == string(filter.Value)
}
return false
}
}, nil
}
func (o *ruleGroupOperator) GetRuleGroup(ctx context.Context, namespace, name string) (*kapialertingv2beta1.RuleGroup, error) {
@@ -474,7 +498,10 @@ func (o *ruleGroupOperator) ListClusterAlerts(ctx context.Context,
}
}
filterAlert := o.createFilterAlertFunc(queryParam)
filterAlert, err := o.createFilterAlertFunc(queryParam)
if err != nil {
return nil, err
}
listResult := resources.DefaultList(alerts, queryParam, func(left, right runtime.Object, field query.Field) bool {
return o.compareAlert(&left.(*wrapAlert).Alert, &right.(*wrapAlert).Alert, field)
}, func(obj runtime.Object, filter query.Filter) bool {
@@ -717,7 +744,10 @@ func (o *ruleGroupOperator) ListGlobalAlerts(ctx context.Context,
}
}
filterAlert := o.createFilterAlertFunc(queryParam)
filterAlert, err := o.createFilterAlertFunc(queryParam)
if err != nil {
return nil, err
}
listResult := resources.DefaultList(alerts, queryParam, func(left, right runtime.Object, field query.Field) bool {
return o.compareAlert(&left.(*wrapAlert).Alert, &right.(*wrapAlert).Alert, field)
}, func(obj runtime.Object, filter query.Filter) bool {