diff --git a/alert/dispatch/dispatch.go b/alert/dispatch/dispatch.go index c90e6496..2d4a4f1d 100644 --- a/alert/dispatch/dispatch.go +++ b/alert/dispatch/dispatch.go @@ -234,9 +234,15 @@ func NotifyRuleApplicable(notifyConfig *models.NotifyConfig, event *models.Alert tagMatch := true if len(notifyConfig.LabelKeys) > 0 { + for i := range notifyConfig.LabelKeys { + if notifyConfig.LabelKeys[i].Func == "" { + notifyConfig.LabelKeys[i].Func = notifyConfig.LabelKeys[i].Op + } + } + tagFilters, err := models.ParseTagFilter(notifyConfig.LabelKeys) if err != nil { - logger.Errorf("failed to parse tag filter: %v", err) + logger.Errorf("notify send failed to parse tag filter: %v event:%+v notify_config:%+v", err, event, notifyConfig) return false } tagMatch = common.MatchTags(event.TagsMap, tagFilters) @@ -246,13 +252,13 @@ func NotifyRuleApplicable(notifyConfig *models.NotifyConfig, event *models.Alert if len(notifyConfig.Attributes) > 0 { tagFilters, err := models.ParseTagFilter(notifyConfig.Attributes) if err != nil { - logger.Errorf("failed to parse tag filter: %v", err) + logger.Errorf("notify send failed to parse tag filter: %v event:%+v notify_config:%+v err:%v", tagFilters, event, notifyConfig, err) return false } attributesMatch = common.MatchTags(event.JsonTagsAndValue(), tagFilters) } - + logger.Infof("notify send timeMatch:%v severityMatch:%v tagMatch:%v attributesMatch:%v event:%+v notify_config:%+v", timeMatch, severityMatch, tagMatch, attributesMatch, event, notifyConfig) return timeMatch && severityMatch && tagMatch && attributesMatch } diff --git a/alert/eval/eval.go b/alert/eval/eval.go index 1cfda9d5..c76541cf 100644 --- a/alert/eval/eval.go +++ b/alert/eval/eval.go @@ -301,7 +301,7 @@ func (arw *AlertRuleWorker) GetPromAnomalyPoint(ruleConfig string) ([]models.Ano arw.Processor.Stats.CounterRuleEvalErrorTotal.WithLabelValues(fmt.Sprintf("%v", arw.Processor.DatasourceId()), QUERY_DATA, arw.Processor.BusiGroupCache.GetNameByBusiGroupId(arw.Rule.GroupId), fmt.Sprintf("%v", arw.Rule.Id)).Inc() } - logger.Debugf("rule_eval:%s query:%+v, value:%v", arw.Key(), query, value) + logger.Infof("rule_eval:%s query:%+v, value:%v", arw.Key(), query, value) points := models.ConvertAnomalyPoints(value) for i := 0; i < len(points); i++ { points[i].Severity = query.Severity diff --git a/center/router/router_notify_rule.go b/center/router/router_notify_rule.go index 90254bc7..3e6512c3 100644 --- a/center/router/router_notify_rule.go +++ b/center/router/router_notify_rule.go @@ -146,13 +146,17 @@ func (rt *Router) notifyTest(c *gin.Context) { } ginx.Dangerous(err) - events := make([]*models.AlertCurEvent, len(hisEvents)) - for i, he := range hisEvents { - events[i] = he.ToCur() + events := []*models.AlertCurEvent{} + for _, he := range hisEvents { + event := he.ToCur() + event.SetTagsMap() + if dispatch.NotifyRuleApplicable(&f.NotifyConfig, event) { + events = append(events, event) + } } - if !dispatch.NotifyRuleApplicable(&f.NotifyConfig, events[0]) { - ginx.Bomb(http.StatusBadRequest, "event not applicable") + if len(events) == 0 { + ginx.Bomb(http.StatusBadRequest, "not events applicable") } notifyChannels, err := models.NotifyChannelGets(rt.Ctx, f.NotifyConfig.ChannelID, "", "", -1) diff --git a/models/alert_cur_event.go b/models/alert_cur_event.go index e5490eff..2b139bf3 100644 --- a/models/alert_cur_event.go +++ b/models/alert_cur_event.go @@ -77,6 +77,23 @@ type AlertCurEvent struct { NotifyRuleIDs []int64 `json:"notify_rule_ids" gorm:"-"` } +func (e *AlertCurEvent) SetTagsMap() { + e.TagsMap = make(map[string]string) + for i := 0; i < len(e.TagsJSON); i++ { + pair := strings.TrimSpace(e.TagsJSON[i]) + if pair == "" { + continue + } + + arr := strings.SplitN(pair, "=", 2) + if len(arr) != 2 { + continue + } + + e.TagsMap[arr[0]] = arr[1] + } +} + func (e *AlertCurEvent) JsonTagsAndValue() map[string]string { v := reflect.ValueOf(e).Elem() t := v.Type() diff --git a/models/alert_his_event.go b/models/alert_his_event.go index 0aa32b8d..bdce3f17 100644 --- a/models/alert_his_event.go +++ b/models/alert_his_event.go @@ -391,6 +391,7 @@ func (e *AlertHisEvent) ToCur() *AlertCurEvent { TriggerTime: e.TriggerTime, TriggerValue: e.TriggerValue, Tags: e.Tags, + TagsJSON: e.TagsJSON, OriginalTags: e.OriginalTags, LastEvalTime: e.LastEvalTime, NotifyCurNumber: e.NotifyCurNumber, diff --git a/models/alert_mute.go b/models/alert_mute.go index 2dcc0c5e..f7eacfa6 100644 --- a/models/alert_mute.go +++ b/models/alert_mute.go @@ -18,6 +18,7 @@ import ( type TagFilter struct { Key string `json:"key"` // tag key Func string `json:"func"` // `==` | `=~` | `in` | `!=` | `!~` | `not in` + Op string `json:"op"` // `==` | `=~` | `in` | `!=` | `!~` | `not in` Value string `json:"value"` // tag value Regexp *regexp.Regexp // parse value to regexp if func = '=~' or '!~' Vset map[string]struct{} // parse value to regexp if func = 'in' or 'not in' @@ -28,6 +29,10 @@ func (t *TagFilter) Verify() error { return errors.New("tag key cannot be empty") } + if t.Func == "" { + t.Func = t.Op + } + if t.Func != "==" && t.Func != "!=" && t.Func != "in" && t.Func != "not in" && t.Func != "=~" && t.Func != "!~" { return errors.New("invalid operation")