Commit 42ba9e54 authored by 李科's avatar 李科

feat: 回调推送

parent dbe68c86
...@@ -4,41 +4,41 @@ import ( ...@@ -4,41 +4,41 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
) )
// Alert 预警 // Alert 预警
type Alert struct { type Alert struct {
Id int `json:"id"` // 预警列表ID,主键,自增长 Id int `json:"id"` // 预警id
AlertPoint string `json:"alert_point"` // 预警点 AlertPoint string `json:"alert_point"` // 预警点:预警分类/预警规则名称 ClassParentName/AlertRulesName
AlertRulesId string `json:"alert_rules_id"` // 告警规则id AlertRulesId string `json:"alert_rules_id"` // 告警规则id
AlertRulesName string `json:"alert_rules_name"` // 告警规则名称
RiskLevel int `json:"risk_level"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险 RiskLevel int `json:"risk_level"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
AlertTime jsontime.Time `json:"alert_time"` // 预警时间 AlertTime jsontime.Time `json:"alert_time"` // 预警时间
ClassId int `json:"class_id"` // 预警对象id(级联:预警分类/预警对象) ClassId int `json:"class_id"` // 预警对象id(级联:预警分类/预警对象)
ClassParentName string `json:"class_parent_name"` // 预警分类名称 TODO 该字段做关联存储或查询 ClassParentName string `json:"class_parent_name"` // 预警分类名称 TODO 该字段做关联存储或查询
ClassName string `json:"class_name"` // 预警对象名称 TODO 该字段做关联存储或查询 ClassName string `json:"class_name"` // 预警对象名称 TODO 该字段做关联存储或查询
MetricConfigId string `json:"metric_config_id"` // 预警指标id // 预警指标 MetricConfigId string `json:"metric_config_id"` // 预警指标id
MetricConfigName string `json:"metric_config_name"` // 预警指标名称 MetricConfigName string `json:"metric_config_name"` // 预警指标名称
AlertRuleType string `json:"alert_rule_type"` // 预警规则类型id TODO 该字段做关联存储或查询 AlertRuleType string `json:"alert_rule_type"` // 预警规则类型id TODO 该字段做关联存储或查询
AlertRuleTypeName string `json:"alert_rule_type_name"` // 预警规则类型名称 TODO 该字段做关联存储或查询 AlertRuleTypeName string `json:"alert_rule_type_name"` // 预警规则类型名称 TODO 该字段做关联存储或查询
CurrentValue float64 `json:"current_value"` // 当前报警值 CurrentValue float64 `json:"current_value"` // 当前报警值
AlertCondition AlertCondition `json:"alert_condition" xorm:"alert_condition"` AlertCondition AlertCondition `json:"alert_condition"` // 预警范围
NotificationCount int `json:"notification_count"` // 通知人数 NotificationCount int `json:"notification_count"` // 通知人数
PushCount int `json:"push_count"` // 推送次数 PushCount int `json:"push_count"` // 推送次数
LastPushTime jsontime.Time `json:"last_push_time"` // 最近推送时间 LastPushTime jsontime.Time `json:"last_push_time"` // 最近推送时间
Status int `json:"status"` // 状态,1:已恢复 2:未恢复 3:已关闭 Status int `json:"status"` // 状态,1:已恢复 2:未恢复 3:已关闭
PushRecords []PushRecord `json:"push_records"` PushRecords []PushRecord `json:"push_records"` // 推送记录列表
DisposedList []DisposedList `json:"disposed_list"` // 处置列表 DisposedList []Disposed `json:"disposed_list"` // 处置列表
IsDisposed int `json:"is_disposed"` // 是否处置(工单管理),1:已处置,2:未处置 通过DisposedList逻辑处理回显 IsDisposed int `json:"is_disposed"` // 是否处置(工单管理),1:已处置,2:未处置 通过DisposedList逻辑处理回显
CloseRemark string `json:"close_remark"` // 关闭备注(预警关闭提醒) CloseRemark string `json:"close_remark"` // 关闭备注(预警关闭提醒)
CloseUser string `json:"close_user"` // 关闭用户,预警关闭提醒 CloseUser string `json:"close_user"` // 关闭用户,预警关闭提醒
CloseTime jsontime.Time `json:"close_time"` // 关闭关闭时间,预警关闭提醒 CloseTime jsontime.Time `json:"close_time"` // 关闭关闭时间,预警关闭提醒
DeferPush int `json:"defer_push" xorm:"defer_push"` // 延迟三天推送: 0:否 1:是 三天内将不再自动推送该告警信息给处置人员,可手动推送,但告警数据依然会出现 DeferPush int `json:"defer_push"` // 延迟三天推送: 0:否 1:是 三天内将不再自动推送该告警信息给处置人员,可手动推送,但告警数据依然会出现
CreatedBy string `json:"created_by"` // 创建人
CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人 CreatedAt jsontime.Time `json:"created_at"` // 创建时间
CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间 UpdatedBy string `json:"updated_by"` // 更新人
UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人 UpdatedAt jsontime.Time `json:"updated_at"` // 更新时间
UpdatedAt jsontime.Time `json:"updated_at" xorm:"'updated_at'"` // 更新时间
} }
type DisposedList struct { type Disposed struct {
IsDisposed int `json:"is_disposed"` // 是否处置(工单管理),1:已处置,2:未处置 IsDisposed int `json:"is_disposed"` // 是否处置(工单管理),1:已处置,2:未处置
DisposalContent string `json:"disposal_content"` // 处置内容(工单管理,结果反馈) DisposalContent string `json:"disposal_content"` // 处置内容(工单管理,结果反馈)
DisposalUser string `json:"disposal_user"` // 处置人(工单管理,结果反馈) DisposalUser string `json:"disposal_user"` // 处置人(工单管理,结果反馈)
......
...@@ -9,13 +9,14 @@ type DetailAlert struct { ...@@ -9,13 +9,14 @@ type DetailAlert struct {
} }
type ListAlert struct { type ListAlert struct {
Id int `json:"id" form:"id"` Id int `json:"id" form:"id"`
Ids []int `json:"ids" form:"ids"` // 预警ids Ids []int `json:"ids" form:"ids"` // 预警ids
RiskLevel int `json:"risk_level" form:"risk_level" binding:"omitempty,oneof=1 2 3 4"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险 AlertRulesId string `json:"alert_rules_id" form:"alert_rules_id"` // 告警规则id
Status int `json:"status" form:"status" binding:"omitempty,oneof=1 2 3"` // 状态,1:已恢复 2:未恢复 3:已关闭 RiskLevel int `json:"risk_level" form:"risk_level" binding:"omitempty,oneof=1 2 3 4"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
Keyword string `json:"keyword" form:"keyword"` // 预警点/分类/指标 Status int `json:"status" form:"status" binding:"omitempty,oneof=1 2 3"` // 状态,1:已恢复 2:未恢复 3:已关闭
StartTime string `json:"start_time" form:"start_time" binding:"omitempty,datetime=2006-01-02 15:04:05"` Keyword string `json:"keyword" form:"keyword"` // 预警点/分类/指标
EndTime string `json:"end_time" form:"end_time" binding:"omitempty,datetime=2006-01-02 15:04:05"` StartTime string `json:"start_time" form:"start_time" binding:"omitempty,datetime=2006-01-02 15:04:05"`
EndTime string `json:"end_time" form:"end_time" binding:"omitempty,datetime=2006-01-02 15:04:05"`
Pagination Pagination
} }
...@@ -24,13 +25,19 @@ type ExistAlert struct { ...@@ -24,13 +25,19 @@ type ExistAlert struct {
AlertRulesId string `json:"alert_rules_id" form:"'alert_rules_id'"` // 告警规则id AlertRulesId string `json:"alert_rules_id" form:"'alert_rules_id'"` // 告警规则id
} }
type CreateAlert struct {
entity.Alert
}
type UpdateAlert struct { type UpdateAlert struct {
Id int `json:"id" form:"id" binding:"required"` Id int `json:"id" form:"id" binding:"required"`
CloseRemark string `json:"close_remark" form:"close_remark"` // 关闭备注 CloseRemark string `json:"close_remark" form:"close_remark"` // 关闭备注
DeferPush int `json:"defer_push" form:"defer_push" binding:"omitempty,oneof=0 1"` // 延迟三天推送: 0:否 1:是 三天内将不再自动推送该告警信息给处置人员,可手动推送,但告警数据依然会出现 DeferPush int `json:"defer_push" form:"defer_push" binding:"omitempty,oneof=0 1"` // 延迟三天推送: 0:否 1:是 三天内将不再自动推送该告警信息给处置人员,可手动推送,但告警数据依然会出现
RiskLevel int `json:"risk_level" form:"risk_level" binding:"omitempty,oneof=1 2 3 4"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险 RiskLevel int `json:"risk_level" form:"risk_level" binding:"omitempty,oneof=1 2 3 4"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
Status int `json:"status" form:"status" binding:"omitempty,oneof=1 2 3"` // 状态,1:已恢复 2:未恢复 3:已关闭 Status int `json:"status" form:"status" binding:"omitempty,oneof=1 2 3"` // 状态,1:已恢复 2:未恢复 3:已关闭
CurrentValue float64 `json:"current_value" form:"current_value"` // 当前报警值
DisposalContent string `json:"disposal_content" form:"disposal_content"` // 处置内容(工单管理,结果反馈) DisposalContent string `json:"disposal_content" form:"disposal_content"` // 处置内容(工单管理,结果反馈)
PushCount int `json:"push_count" form:"push_count"` // 推送次数
PushRecords []entity.PushRecord `json:"push_records" form:"push_records"` PushRecords []entity.PushRecord `json:"push_records" form:"push_records"`
} }
......
...@@ -26,6 +26,12 @@ type CatIndices struct { ...@@ -26,6 +26,12 @@ type CatIndices struct {
PriStoreSize string `json:"pri.store.size"` PriStoreSize string `json:"pri.store.size"`
} }
type CatIndexCount struct {
Epoch string `json:"epoch"`
Timestamp string `json:"timestamp"`
Count string `json:"count"`
}
type OpenSearchSource struct { type OpenSearchSource struct {
Took int `json:"took"` Took int `json:"took"`
TimedOut bool `json:"timed_out"` TimedOut bool `json:"timed_out"`
......
...@@ -5,7 +5,8 @@ import "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" ...@@ -5,7 +5,8 @@ import "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
type AlertRulesItem struct { type AlertRulesItem struct {
entity.AlertRules `xorm:"extends"` entity.AlertRules `xorm:"extends"`
Expr string `json:"expr" form:"expr"` // 指标表达式(PromQL语句) Expr string `json:"expr" form:"expr"` // 指标表达式(PromQL语句)
AlertRuleType string `json:"alert_rule_type" xorm:"alert_rule_type"` // 预警规则类型 关联字典表 AlertRuleType string `json:"alert_rule_type" xorm:"alert_rule_type"` // 预警规则类型
AlertRuleTypeName string `json:"alert_rule_type_name"` // 预警规则类型名称
ClassParentName string `json:"class_parent_name" xorm:"class_parent_name"` ClassParentName string `json:"class_parent_name" xorm:"class_parent_name"`
ClassName string `json:"class_name" xorm:"class_name"` ClassName string `json:"class_name" xorm:"class_name"`
MetricConfigName string `json:"metric_config_name" xorm:"metric_config_name"` MetricConfigName string `json:"metric_config_name" xorm:"metric_config_name"`
......
...@@ -3,39 +3,32 @@ package controller ...@@ -3,39 +3,32 @@ package controller
import ( import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/prometheus/alertmanager/notify/webhook" "github.com/prometheus/alertmanager/notify/webhook"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/service"
"go.uber.org/zap" "go.uber.org/zap"
) )
// AlertWebhook 回调 // AlertWebhook 回调
func AlertWebhook(c *gin.Context) { func AlertWebhook(c *gin.Context) {
// 读取请求体原始数据
var req webhook.Message var req webhook.Message
if err := c.ShouldBind(&req); err != nil { if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil) SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return return
} }
conf.Logger.Info("------>webhook.Message------>", zap.Any("message", req))
/*bodyBytes, err := io.ReadAll(c.Request.Body) svc := service.AlertWebhookSvc{User: header.GetUser(c)}
db, err := client.GetDbClient()
if err != nil { if err != nil {
// 处理错误 SendJsonResponse(c, resp.DbConnectError.WithError(err), nil)
c.String(500, "Error reading request body")
return return
}*/ }
err = svc.AlertWebhook(db.NewSession(), req)
// 输出请求体原始数据到控制台 if err != nil {
//log.Printf("原始数据------>\n%s\n<------", string(bodyBytes)) SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
// 将请求体数据重新放入请求中,以便后续处理 }
//c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
conf.Logger.Info("------>webhook.Message------>", zap.Any("message", req))
/*var payload map[string]interface{}
if err := c.ShouldBind(&payload); err != nil {
log.Println("Failed to parse JSON: ", err)
SendJsonResponse(c, err, "")
}*/
SendJsonResponse(c, resp.OK, req) SendJsonResponse(c, resp.OK, req)
} }
...@@ -145,3 +145,10 @@ func RiskLeveText(code int) string { ...@@ -145,3 +145,10 @@ func RiskLeveText(code int) string {
return "" return ""
} }
} }
// 预警状态,1:已恢复 2:未恢复 3:已关闭
const (
AlertRecovered = iota + 1
AlertNotRecovered
AlertClosed
)
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"go.uber.org/zap" "go.uber.org/zap"
"io" "io"
...@@ -52,6 +53,15 @@ var ( ...@@ -52,6 +53,15 @@ var (
"alert_rules_id": { "alert_rules_id": {
"type": "keyword" "type": "keyword"
}, },
"alert_rules_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"risk_level": { "risk_level": {
"type": "integer" "type": "integer"
}, },
...@@ -324,7 +334,7 @@ func (a *AlertSvc) Indices() (indices []string, err error) { ...@@ -324,7 +334,7 @@ func (a *AlertSvc) Indices() (indices []string, err error) {
return return
} }
defer do.Body.Close() defer do.Body.Close()
if do.StatusCode != http.StatusOK { if do.StatusCode < http.StatusOK && do.StatusCode > http.StatusIMUsed {
err = errors.New(do.String()) err = errors.New(do.String())
return return
} }
...@@ -346,7 +356,7 @@ func (a *AlertSvc) Indices() (indices []string, err error) { ...@@ -346,7 +356,7 @@ func (a *AlertSvc) Indices() (indices []string, err error) {
return return
} }
func (a *AlertSvc) IndexSearch(req request.ListAlert) (resp response.AlertList, err error) { func (a *AlertSvc) DocSearch(req request.ListAlert) (resp response.AlertList, err error) {
var ( var (
sources response.OpenSearchSource sources response.OpenSearchSource
) )
...@@ -362,6 +372,10 @@ func (a *AlertSvc) IndexSearch(req request.ListAlert) (resp response.AlertList, ...@@ -362,6 +372,10 @@ func (a *AlertSvc) IndexSearch(req request.ListAlert) (resp response.AlertList,
boolQuery.Must(elastic.NewMatchQuery("id", req.Id)) boolQuery.Must(elastic.NewMatchQuery("id", req.Id))
} }
if req.AlertRulesId != "" {
boolQuery.Must(elastic.NewMatchQuery("alert_rules_id", req.AlertRulesId))
}
if req.RiskLevel != 0 { if req.RiskLevel != 0 {
boolQuery.Must(elastic.NewMatchQuery("risk_level", req.RiskLevel)) boolQuery.Must(elastic.NewMatchQuery("risk_level", req.RiskLevel))
} }
...@@ -417,7 +431,7 @@ func (a *AlertSvc) IndexSearch(req request.ListAlert) (resp response.AlertList, ...@@ -417,7 +431,7 @@ func (a *AlertSvc) IndexSearch(req request.ListAlert) (resp response.AlertList,
return return
} }
defer do.Body.Close() defer do.Body.Close()
if do.StatusCode != http.StatusOK { if do.StatusCode < http.StatusOK && do.StatusCode > http.StatusIMUsed {
err = errors.New(do.String()) err = errors.New(do.String())
return return
} }
...@@ -473,7 +487,7 @@ func (a *AlertSvc) IndexDocExist(req request.ExistAlert) (exist bool, err error) ...@@ -473,7 +487,7 @@ func (a *AlertSvc) IndexDocExist(req request.ExistAlert) (exist bool, err error)
return return
} }
defer do.Body.Close() defer do.Body.Close()
if do.StatusCode != http.StatusOK { if do.StatusCode < http.StatusOK && do.StatusCode > http.StatusIMUsed {
err = errors.New(do.String()) err = errors.New(do.String())
return return
} }
...@@ -493,7 +507,97 @@ func (a *AlertSvc) IndexDocExist(req request.ExistAlert) (exist bool, err error) ...@@ -493,7 +507,97 @@ func (a *AlertSvc) IndexDocExist(req request.ExistAlert) (exist bool, err error)
return return
} }
func (a *AlertSvc) IndexUpdate(req request.UpdateAlert) (err error) { func (a *AlertSvc) CatCount(indexName ...string) (count int) {
var (
list []response.CatIndexCount
index string
)
cli, err := client.GetOpenSearch()
if err != nil {
return
}
if len(indexName) > 0 && indexName[0] != "" {
index = indexName[0] + "*"
} else {
index = OpenSearchIndex + "*"
}
res := opensearchapi.CatCountRequest{
Index: []string{index},
Format: "json",
}
do, err := res.Do(context.Background(), cli)
if err != nil {
return
}
defer do.Body.Close()
if do.StatusCode < http.StatusOK && do.StatusCode > http.StatusIMUsed {
err = errors.New(do.String())
return
}
body, err := io.ReadAll(do.Body)
if err != nil {
return
}
err = json.Unmarshal(body, &list)
if err != nil {
return
}
if len(list) > 0 {
count = cast.ToInt(list[0].Count)
}
return
}
func (a *AlertSvc) DocCreate(req request.CreateAlert) (err error) {
var (
sources response.OpenSearchSource
)
cli, err := client.GetOpenSearch()
if err != nil {
return
}
b, _ := json.Marshal(&req.Alert)
docStr := string(b)
if docStr == "" {
return errors.New("doc marshal failed")
}
content := strings.NewReader(fmt.Sprintf(`%s`, docStr))
res := opensearchapi.CreateRequest{
Index: OpenSearchIndex,
DocumentID: cast.ToString(req.Id),
Body: content,
}
do, err := res.Do(context.Background(), cli)
if err != nil {
return
}
defer do.Body.Close()
if do.StatusCode < http.StatusOK && do.StatusCode > http.StatusIMUsed {
err = errors.New(do.String())
return
}
body, err := io.ReadAll(do.Body)
if err != nil {
return
}
err = json.Unmarshal(body, &sources)
if err != nil {
return
}
conf.Logger.Info("--->alert create--->", zap.Any("DocCreate", sources))
return
}
func (a *AlertSvc) DocUpdate(req request.UpdateAlert) (err error) {
var ( var (
sources response.OpenSearchSource sources response.OpenSearchSource
now = jsontime.Now() now = jsontime.Now()
...@@ -517,23 +621,15 @@ func (a *AlertSvc) IndexUpdate(req request.UpdateAlert) (err error) { ...@@ -517,23 +621,15 @@ func (a *AlertSvc) IndexUpdate(req request.UpdateAlert) (err error) {
if req.Status != 0 { if req.Status != 0 {
doc["status"] = req.Status doc["status"] = req.Status
} }
doc["updated_at"] = now if req.CurrentValue != 0 {
doc["current_value"] = req.CurrentValue
if req.DisposalContent != "" {
var detailAlert response.AlertItem
detailAlert, err = a.GetDataById(request.DetailAlert{Id: req.Id})
if err != nil {
return err
}
disposedList := detailAlert.DisposedList
disposedList = append(disposedList, entity.DisposedList{
IsDisposed: req.Status,
DisposalContent: req.DisposalContent,
DisposalUser: a.User.SystemAccount,
DisposalTime: now,
})
doc["disposed_list"] = disposedList
} }
/*if req.CurrentValue != 0 {
doc["current_value"] = req.CurrentValue
}*/
doc["updated_by"] = a.User.SystemAccount
doc["updated_at"] = now
if len(req.PushRecords) > 0 { if len(req.PushRecords) > 0 {
doc["push_records"] = req.PushRecords doc["push_records"] = req.PushRecords
...@@ -564,7 +660,7 @@ func (a *AlertSvc) IndexUpdate(req request.UpdateAlert) (err error) { ...@@ -564,7 +660,7 @@ func (a *AlertSvc) IndexUpdate(req request.UpdateAlert) (err error) {
return return
} }
defer do.Body.Close() defer do.Body.Close()
if do.StatusCode != http.StatusOK { if do.StatusCode < http.StatusOK && do.StatusCode > http.StatusIMUsed {
err = errors.New(do.String()) err = errors.New(do.String())
return return
} }
...@@ -578,18 +674,38 @@ func (a *AlertSvc) IndexUpdate(req request.UpdateAlert) (err error) { ...@@ -578,18 +674,38 @@ func (a *AlertSvc) IndexUpdate(req request.UpdateAlert) (err error) {
return return
} }
conf.Logger.Info("--->alert update--->", zap.Any("IndexUpdate", sources)) conf.Logger.Info("--->alert update--->", zap.Any("DocUpdate", sources))
return return
} }
func (a *AlertSvc) Create() error {
cli, err := client.GetOpenSearch()
if err != nil {
return err
}
res := opensearchapi.IndicesCreateRequest{
Index: OpenSearchIndex,
Body: Mapping,
}
do, err := res.Do(context.Background(), cli)
if err != nil {
return err
}
defer do.Body.Close()
if do.StatusCode != http.StatusOK {
return errors.New(do.String())
}
return nil
}
func (a *AlertSvc) Update(req request.UpdateAlert) error { func (a *AlertSvc) Update(req request.UpdateAlert) error {
err := a.IndexUpdate(req) err := a.DocUpdate(req)
return err return err
} }
func (a *AlertSvc) BatchPushAlert(req request.BatchPushAlert) (err error) { func (a *AlertSvc) BatchPushAlert(req request.BatchPushAlert) (err error) {
now := jsontime.Now() now := jsontime.Now()
resp, err := a.IndexSearch(request.ListAlert{Ids: req.Ids}) resp, err := a.DocSearch(request.ListAlert{Ids: req.Ids})
if err != nil { if err != nil {
return return
} }
...@@ -619,7 +735,7 @@ func (a *AlertSvc) BatchPushAlert(req request.BatchPushAlert) (err error) { ...@@ -619,7 +735,7 @@ func (a *AlertSvc) BatchPushAlert(req request.BatchPushAlert) (err error) {
pushRecords = append(pushRecords, data) pushRecords = append(pushRecords, data)
} }
err = a.IndexUpdate(request.UpdateAlert{ err = a.DocUpdate(request.UpdateAlert{
Id: alert.Id, Id: alert.Id,
PushRecords: pushRecords, PushRecords: pushRecords,
}) })
...@@ -642,7 +758,7 @@ func (a *AlertSvc) BatchCloseAlert(req request.BatchCloseAlert) (err error) { ...@@ -642,7 +758,7 @@ func (a *AlertSvc) BatchCloseAlert(req request.BatchCloseAlert) (err error) {
ids = append(ids, req.Id) ids = append(ids, req.Id)
} }
for _, id := range ids { for _, id := range ids {
err = a.IndexUpdate(request.UpdateAlert{ err = a.DocUpdate(request.UpdateAlert{
Id: id, Id: id,
CloseRemark: req.CloseRemark, CloseRemark: req.CloseRemark,
DeferPush: req.DeferPush, DeferPush: req.DeferPush,
...@@ -658,15 +774,26 @@ func (a *AlertSvc) BatchCloseAlert(req request.BatchCloseAlert) (err error) { ...@@ -658,15 +774,26 @@ func (a *AlertSvc) BatchCloseAlert(req request.BatchCloseAlert) (err error) {
} }
func (a *AlertSvc) GetDataById(req request.DetailAlert) (resp response.AlertItem, err error) { func (a *AlertSvc) GetDataById(req request.DetailAlert) (resp response.AlertItem, err error) {
list, err := a.IndexSearch(request.ListAlert{Id: req.Id}) list, err := a.DocSearch(request.ListAlert{Id: req.Id})
if len(list.List) > 0 { if len(list.List) > 0 {
resp = list.List[0] resp = list.List[0]
} }
return return
} }
func (a *AlertSvc) GetDataByAlertRulesIdAndRiskLevel(alertRulesId string, riskLevel int, status int) (resp response.AlertItem, err error) {
list, err := a.DocSearch(request.ListAlert{AlertRulesId: alertRulesId, RiskLevel: riskLevel, Status: status})
if len(list.List) > 0 {
resp = list.List[0]
}
/*if resp.Id == 0 {
err = errors.New("no data found")
}*/
return
}
func (a *AlertSvc) List(req request.ListAlert) (resp response.AlertList, err error) { func (a *AlertSvc) List(req request.ListAlert) (resp response.AlertList, err error) {
resp, err = a.IndexSearch(req) resp, err = a.DocSearch(req)
resp.TotalCount = int64(len(resp.List)) resp.TotalCount = int64(len(resp.List))
return return
} }
...@@ -684,10 +811,10 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) { ...@@ -684,10 +811,10 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) {
return err return err
} }
if detailAlert.Status == 1 { if detailAlert.Status == constant.AlertRecovered {
return errors.New("alert has been restored") return errors.New("alert has been restored")
} }
if detailAlert.Status == 3 { if detailAlert.Status == constant.AlertClosed {
return errors.New("alert has been closed") return errors.New("alert has been closed")
} }
...@@ -700,7 +827,7 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) { ...@@ -700,7 +827,7 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) {
doc["status"] = req.Status doc["status"] = req.Status
if req.DisposalContent != "" { if req.DisposalContent != "" {
disposedList := detailAlert.DisposedList disposedList := detailAlert.DisposedList
disposedList = append(disposedList, entity.DisposedList{ disposedList = append(disposedList, entity.Disposed{
IsDisposed: req.Status, IsDisposed: req.Status,
DisposalContent: req.DisposalContent, DisposalContent: req.DisposalContent,
DisposalUser: a.User.SystemAccount, DisposalUser: a.User.SystemAccount,
...@@ -730,7 +857,7 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) { ...@@ -730,7 +857,7 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) {
return return
} }
defer do.Body.Close() defer do.Body.Close()
if do.StatusCode != http.StatusOK { if do.StatusCode < http.StatusOK && do.StatusCode > http.StatusIMUsed {
err = errors.New(do.String()) err = errors.New(do.String())
return return
} }
......
...@@ -279,10 +279,11 @@ func (a *AlertRulesSvc) List(req request.ListAlertRules) (resp response.AlertRul ...@@ -279,10 +279,11 @@ func (a *AlertRulesSvc) List(req request.ListAlertRules) (resp response.AlertRul
} }
session := db.NewSession() session := db.NewSession()
defer session.Close() defer session.Close()
session.Table(new(entity.AlertRules)).Alias("r").Select("r.*,acp.class_name class_parent_name,ac.class_name,mc.expr,mc.metric_name metric_config_name,mc.alert_rule_type") session.Table(new(entity.AlertRules)).Alias("r").Select("r.*,acp.class_name class_parent_name,ac.class_name,mc.expr,mc.metric_name metric_config_name,mc.alert_rule_type,dict.name alert_rule_type_name")
session.Join("LEFT", "metric_config mc", "mc.id = r.metric_config_id") session.Join("LEFT", "metric_config mc", "mc.id = r.metric_config_id")
session.Join("LEFT", "alert_class ac", "ac.class_id = r.class_id") session.Join("LEFT", "alert_class ac", "ac.class_id = r.class_id")
session.Join("LEFT", "alert_class acp", "acp.class_id = ac.parent_id") session.Join("LEFT", "alert_class acp", "acp.class_id = ac.parent_id")
session.Join("LEFT", "dict", "dict.id = mc.alert_rule_type")
if req.Id != "" { if req.Id != "" {
session.Where("r.id = ?", req.Id) session.Where("r.id = ?", req.Id)
} }
......
package service package service
import ( import (
"errors"
"github.com/prometheus/alertmanager/notify/webhook" "github.com/prometheus/alertmanager/notify/webhook"
"github.com/spf13/cast"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"xorm.io/xorm" "xorm.io/xorm"
) )
...@@ -10,10 +16,116 @@ type AlertWebhookSvc struct { ...@@ -10,10 +16,116 @@ type AlertWebhookSvc struct {
User entity.SystemUserInfo User entity.SystemUserInfo
} }
// TODO AlertManager 回调接口 // AlertWebhook Alertmanager 回调接口
func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Message) (id string, err error) { func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Message) (err error) {
// 1.判断该opensearch数据是否恢复 now := jsontime.Now()
// 1.1.如果恢复,则查询当前opensearch最大id值,插入新的数据到预警列表 alertSvc := AlertSvc{User: a.User}
// 1.2如果未恢复,根据id更新该条数据 alertRulesSvc := AlertRulesSvc{User: a.User}
for _, alert := range req.Alerts {
var (
alertRulesId string
riskLevelStr string
riskLevel int
currentValueStr string
currentValue float64
ok bool
alertItem response.AlertItem
alertRulesItem response.AlertRulesItem
alertStatus int
alertCondition entity.AlertCondition
)
if alertRulesId, ok = alert.Labels["alert_rules_id"]; !ok {
return errors.New("alert_rules_id not found in the map")
}
if riskLevelStr, ok = alert.Labels["risk_level"]; !ok {
return errors.New("risk_level not found in the map")
}
riskLevel = cast.ToInt(riskLevelStr)
if currentValueStr, ok = alert.Annotations["value"]; !ok {
return errors.New("value not found in the map")
}
currentValue = cast.ToFloat64(currentValueStr)
alertRulesItem, err = alertRulesSvc.GetDataById(request.DetailAlertRules{Id: alertRulesId})
if err != nil {
return
}
alertItem, err = alertSvc.GetDataByAlertRulesIdAndRiskLevel(alertRulesId, riskLevel, 2)
if err != nil {
return
}
var newData bool
if alertItem.Id == 0 { // 新数据
newData = true
}
switch newData {
case true: // 新增数据到OpenSearch
max := alertSvc.CatCount(OpenSearchIndex)
if max == 0 {
return
}
alertId := max + 1
for _, v := range alertRulesItem.AlertCondition {
if v.RiskLevel == riskLevel {
alertCondition = v
break
}
}
err = alertSvc.DocCreate(request.CreateAlert{Alert: entity.Alert{
Id: alertId,
AlertPoint: alertRulesItem.ClassParentName + "/" + alertRulesItem.MetricName,
AlertRulesId: alertRulesItem.Id,
AlertRulesName: alertRulesItem.MetricName,
RiskLevel: riskLevel,
AlertTime: jsontime.Time(alert.StartsAt),
ClassId: alertRulesItem.ClassId,
ClassParentName: alertRulesItem.ClassParentName,
ClassName: alertRulesItem.ClassName,
MetricConfigId: alertRulesItem.MetricConfigId,
MetricConfigName: alertRulesItem.MetricConfigName,
AlertRuleType: alertRulesItem.AlertRuleType,
AlertRuleTypeName: alertRulesItem.AlertRuleTypeName,
CurrentValue: currentValue,
AlertCondition: alertCondition,
NotificationCount: len(alertRulesItem.NotifyRecipients),
PushCount: 1,
LastPushTime: now,
Status: constant.AlertNotRecovered,
CreatedBy: a.User.SystemAccount,
CreatedAt: now,
UpdatedBy: a.User.SystemAccount,
UpdatedAt: now,
}})
if err != nil {
return
}
default: // 旧数据,更新或解决
switch alert.Status {
case "firing":
alertStatus = constant.AlertNotRecovered
case "resolved":
alertStatus = constant.AlertRecovered
}
err = alertSvc.Update(request.UpdateAlert{
Id: alertItem.Id,
CurrentValue: currentValue,
RiskLevel: riskLevel,
Status: alertStatus,
})
}
}
return return
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment