diff --git a/model/alerting/condition.go b/model/alerting/condition.go index 097f3c6f..f242ac15 100644 --- a/model/alerting/condition.go +++ b/model/alerting/condition.go @@ -18,6 +18,7 @@ type ConditionItem struct { Values []string `json:"values"` Severity string `json:"severity"` } + func (cond *ConditionItem) GenerateConditionExpression()(conditionExpression string, err error){ valueLength := len(cond.Values) if valueLength == 0 { diff --git a/plugin/api/alerting/api.go b/plugin/api/alerting/api.go index 41bdb9f5..d2f2a0df 100644 --- a/plugin/api/alerting/api.go +++ b/plugin/api/alerting/api.go @@ -40,6 +40,7 @@ func (alert *AlertAPI) Init() { api.HandleAPIMethod(api.GET, "/alerting/message/_search", alert.searchAlertMessage) api.HandleAPIMethod(api.POST, "/alerting/message/_ignore", alert.ignoreAlertMessage) api.HandleAPIMethod(api.GET, "/alerting/message/_stats", alert.getAlertMessageStats) + api.HandleAPIMethod(api.GET, "/alerting/message/:message_id", alert.getAlertMessage) //just for test diff --git a/plugin/api/alerting/message.go b/plugin/api/alerting/message.go index 50537e55..a09a3c78 100644 --- a/plugin/api/alerting/message.go +++ b/plugin/api/alerting/message.go @@ -166,4 +166,52 @@ func (h *AlertAPI) searchAlertMessage(w http.ResponseWriter, req *http.Request, return } h.Write(w, res.Raw) +} + +func (h *AlertAPI) getAlertMessage(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { + message := &alerting.AlertMessage{ + ID: ps.ByName("message_id"), + } + exists, err := orm.Get(message) + if !exists || err != nil { + log.Error(err) + h.WriteJSON(w, util.MapStr{ + "_id": message.ID, + "found": false, + }, http.StatusNotFound) + return + } + rule := &alerting.Rule{ + ID: message.RuleID, + } + exists, err = orm.Get(rule) + if !exists || err != nil { + log.Error(err) + h.WriteError(w, fmt.Sprintf("rule[%s] not found", rule.ID), http.StatusInternalServerError) + return + } + conditionExpressions := make([]string, 0, len(rule.Conditions.Items)) + metricExpression, _ := rule.Metrics.GenerateExpression() + for _, cond := range rule.Conditions.Items { + expression, _ := cond.GenerateConditionExpression() + conditionExpressions = append(conditionExpressions, strings.ReplaceAll(expression, "result", metricExpression)) + } + var duration time.Duration + if message.Status == alerting.MessageStateRecovered { + duration = message.Updated.Sub(message.Created) + }else{ + duration = time.Now().Sub(message.Created) + } + detailObj := util.MapStr{ + "title": message.Title, + "message": message.Message, + "severity": message.Severity, + "created": message.Created, + "updated": message.Updated, + "resource_name": rule.Resource.Name, + "resource_object": rule.Resource.Objects, + "condition_expressions": conditionExpressions, + "duration": duration.Milliseconds(), + } + h.WriteJSON(w, detailObj, http.StatusOK) } \ No newline at end of file diff --git a/plugin/api/alerting/rule.go b/plugin/api/alerting/rule.go index 0d422f35..98da1348 100644 --- a/plugin/api/alerting/rule.go +++ b/plugin/api/alerting/rule.go @@ -221,6 +221,22 @@ func (alertAPI *AlertAPI) deleteRule(w http.ResponseWriter, req *http.Request, p task.DeleteTask(obj.ID) clearKV(obj.ID) + delDsl := util.MapStr{ + "query": util.MapStr{ + "term": util.MapStr{ + "rule_id": id, + }, + }, + } + err = orm.DeleteBy(alerting.AlertMessage{}, util.MustToJSONBytes(delDsl)) + if err != nil { + log.Error(err) + } + err = orm.DeleteBy(alerting.Alert{}, util.MustToJSONBytes(delDsl)) + if err != nil { + log.Error(err) + } + alertAPI.WriteJSON(w, util.MapStr{ "_id": obj.ID, "result": "deleted", diff --git a/service/alerting/elasticsearch/engine.go b/service/alerting/elasticsearch/engine.go index ae78db78..c39e8d4b 100644 --- a/service/alerting/elasticsearch/engine.go +++ b/service/alerting/elasticsearch/engine.go @@ -973,10 +973,12 @@ func getLastAlertMessage(ruleID string, duration time.Duration) (*alerting.Alert } func saveAlertMessageToES(message *alerting.AlertMessage) error { + message.Updated = time.Now() return orm.Save(message) } func saveAlertMessage(message *alerting.AlertMessage) error { + //todo diff message if not change , then skip save to es ? err := saveAlertMessageToES(message) if err != nil { return err @@ -990,49 +992,6 @@ func saveAlertMessage(message *alerting.AlertMessage) error { return err } -func hasAcknowledgedRule(ruleID string, startTime time.Time) (bool, error){ - queryDsl := util.MapStr{ - "size": 1, - "query": util.MapStr{ - "bool": util.MapStr{ - "must":[]util.MapStr{ - { - "term": util.MapStr{ - "rule_id": util.MapStr{ - "value": ruleID, - }, - }, - }, - { - "term": util.MapStr{ - "state": alerting.AlertStateAcknowledge, - }, - }, - { - "range": util.MapStr{ - "created": util.MapStr{ - "gte": startTime, - }, - }, - }, - }, - - }, - }, - } - q := orm.Query{ - WildcardIndex: true, - RawQuery: util.MustToJSONBytes(queryDsl), - } - err, searchResult := orm.Search(alerting.Alert{}, &q ) - if err != nil { - return false, err - } - if len(searchResult.Result) == 0 { - return false, nil - } - return true, nil -} func readTimeFromKV(bucketKey string, key []byte)(time.Time, error){ timeBytes, err := kv.GetValue(bucketKey, key)