diff --git a/src/bean/entity/alert_overview.go b/src/bean/entity/alert_overview.go index 3390cd44d2cfdd96522f6d10a7091b6c834fe96c..af85db31d6455d3e99ed6fde5b65fdb58b7c6b53 100644 --- a/src/bean/entity/alert_overview.go +++ b/src/bean/entity/alert_overview.go @@ -1,17 +1,18 @@ package entity -import "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" +import ( + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" +) type AlertOverview struct { - RiskLevel int `json:"risk_level"` - MetricName string `json:"metric_name" xorm:"'metric_name'"` // 预警规则名称(指标名称) - UnresolvedCount int `json:"unresolved_count"` // 未恢复数量 - TotalCount int `json:"total_count"` // 总预警数 - List []AlertArray `json:"list"` // 预警列表 - CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人 - CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间 - UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人 - UpdatedAt jsontime.Time `json:"updated_at" xorm:"'updated_at'"` // 更新时间 + RiskLevel int `json:"risk_level"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险 + UnresolvedCount int `json:"unresolved_count"` // 未恢复数量 + TotalCount int `json:"total_count"` // 总预警数 + List []AlertArray `json:"list"` // 预警列表 + CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人 + CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间 + UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人 + UpdatedAt jsontime.Time `json:"updated_at" xorm:"'updated_at'"` // 更新时间 } type AlertArray struct { @@ -20,6 +21,29 @@ type AlertArray struct { TotalCount int `json:"total_count"` // 总预警数 } +type RiskLevelDistribution struct { + Name string `json:"name"` // 名称 + RiskLevel int `json:"risk_level"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险 + Percentage string `json:"percentage"` // 百分比 +} + +type AlertStatusDistribution struct { + Name string `json:"name"` // 名称 + Status int `json:"status"` // 状态,1:已恢复 2:未恢复 3:已关闭 + Percentage string `json:"percentage"` // 百分比 +} + +type AlertClassDistribution struct { + Name string `json:"name"` // 名称 + ClassId int `json:"class_id"` // 预警分类id + Percentage string `json:"percentage"` // 百分比 +} + +type AlertFrequencyDistribution struct { + Name string `json:"name"` // 名称 + Count int `json:"count"` // 数量 +} + func (a *AlertOverview) TableName() string { - return "alert_overview" + return "alert_overview.go" } diff --git a/src/bean/vo/request/alert_overview.go b/src/bean/vo/request/alert_overview.go new file mode 100644 index 0000000000000000000000000000000000000000..aea312e2dac14e79b2e2c45fc797dd329d285c2b --- /dev/null +++ b/src/bean/vo/request/alert_overview.go @@ -0,0 +1,35 @@ +package request + +type AddAlertOverview struct { + ClassName string `json:"class_name" form:"class_name" binding:"required"` + ParentId int `json:"parent_id" form:"parent_id" binding:"omitempty,oneof=0 1"` + SortOrder int `json:"sort_order" form:"sort_order"` + SourceFrom int `json:"source_from" form:"source_from" binding:"omitempty,oneof=1 2"` // 数据来源 1:默认 2:自定义 +} + +type UpdateAlertOverview struct { + ClassId int `json:"class_id" form:"class_id" binding:"required"` + ClassName string `json:"class_name" form:"class_name" binding:"required"` +} + +type DeleteAlertOverview struct { + ClassId int `json:"class_id" form:"class_id"` + ClassIds []int `json:"class_ids" form:"class_ids" binding:"required_without=ClassId"` +} + +type MoveAlertOverview struct { + ClassId int `json:"class_id" form:"class_id" binding:"required"` + Direction string `json:"direction" form:"direction" binding:"oneof=up down"` +} + +type DetailAlertOverview struct { + OverviewTime string `json:"overview_time" form:"overview_time" binding:"omitempty,oneof=today week month year"` + 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"` +} + +type ListAlertOverview struct { + ClassId int `json:"class_id" form:"class_id"` + ClassName string `json:"class_name" form:"class_name"` + Pagination +} diff --git a/src/bean/vo/response/alert_overview.go b/src/bean/vo/response/alert_overview.go new file mode 100644 index 0000000000000000000000000000000000000000..3885be2cd60085b3a1251c4926364d2cfcc04bce --- /dev/null +++ b/src/bean/vo/response/alert_overview.go @@ -0,0 +1,23 @@ +package response + +import ( + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" +) + +type AlertOverviewItem struct { + AlertOverview []entity.AlertOverview `json:"alert_overview"` + RiskLevelDistribution []entity.RiskLevelDistribution `json:"risk_level_distribution"` + AlertStatusDistribution []entity.AlertStatusDistribution `json:"alert_status_distribution"` + AlertClassDistribution []entity.AlertClassDistribution `json:"alert_class_distribution"` + AlertFrequencyDistribution []entity.AlertFrequencyDistribution `json:"alert_frequency_distribution"` +} + +type AlertOverviewList struct { + TotalCount int64 `json:"total_count"` + List []AlertOverviewItem `json:"list"` +} + +type AlertOverviewNode struct { + entity.AlertOverview + Children []*AlertOverviewNode `json:"children"` +} diff --git a/src/controller/alert_overview.go b/src/controller/alert_overview.go new file mode 100644 index 0000000000000000000000000000000000000000..2cb24d07361950d44307ad8e9510c1b81432d5e8 --- /dev/null +++ b/src/controller/alert_overview.go @@ -0,0 +1,107 @@ +package controller + +import ( + "github.com/gin-gonic/gin" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client" + "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" +) + +// AddAlertOverview 新增任务 +func AddAlertOverview(c *gin.Context) { + var req request.AddAlertOverview + if err := c.ShouldBind(&req); err != nil { + SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil) + return + } + + svc := service.AlertOverviewSvc{User: header.GetUser(c)} + db, err := client.GetDbClient() + if err != nil { + SendJsonResponse(c, resp.DbConnectError.WithError(err), nil) + return + } + _, err = svc.Add(db.NewSession(), req) + if err != nil { + SendJsonResponse(c, resp.FAIL.WithError(err), nil) + return + } + SendJsonResponse(c, resp.OK, nil) +} + +func UpdateAlertOverview(c *gin.Context) { + var req request.UpdateAlertOverview + if err := c.ShouldBind(&req); err != nil { + SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil) + return + } + + svc := service.AlertOverviewSvc{User: header.GetUser(c)} + db, err := client.GetDbClient() + if err != nil { + SendJsonResponse(c, resp.DbConnectError.WithError(err), nil) + return + } + err = svc.Update(db.NewSession(), req) + if err != nil { + SendJsonResponse(c, resp.FAIL.WithError(err), nil) + return + } + SendJsonResponse(c, resp.OK, nil) +} + +func DetailAlertOverview(c *gin.Context) { + var req request.DetailAlertOverview + if err := c.ShouldBind(&req); err != nil { + SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil) + return + } + + svc := service.AlertOverviewSvc{User: header.GetUser(c)} + data, err := svc.Overview(req) + if err != nil { + SendJsonResponse(c, resp.FAIL.WithError(err), nil) + return + } + SendJsonResponse(c, resp.OK, data) +} + +func ListAlertOverview(c *gin.Context) { + var req request.ListAlertOverview + if err := c.ShouldBind(&req); err != nil { + SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil) + return + } + svc := service.AlertOverviewSvc{User: header.GetUser(c)} + data, err := svc.List(req) + if err != nil { + SendJsonResponse(c, resp.FAIL.WithError(err), nil) + return + } + SendJsonResponse(c, resp.OK, data) +} + +func DeleteAlertOverview(c *gin.Context) { + var req request.DeleteAlertOverview + if err := c.ShouldBind(&req); err != nil { + SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil) + return + } + var ids []int + switch len(req.ClassIds) { + case 0: + ids = append(ids, req.ClassId) + default: + ids = req.ClassIds + } + + svc := service.AlertOverviewSvc{User: header.GetUser(c)} + err := svc.Delete(ids) + if err != nil { + SendJsonResponse(c, resp.FAIL.WithError(err), nil) + return + } + SendJsonResponse(c, resp.OK, nil) +} diff --git a/src/router/alertoverviewrouter.go.go b/src/router/alertoverviewrouter.go.go new file mode 100644 index 0000000000000000000000000000000000000000..c4927327e1f3153ef3564f5e2adc387971f61698 --- /dev/null +++ b/src/router/alertoverviewrouter.go.go @@ -0,0 +1,16 @@ +package router + +import ( + "fmt" + "github.com/gin-gonic/gin" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/controller" +) + +// InitAlertOverviewRouter 初始化预警总览配置路由 +func InitAlertOverviewRouter(e *gin.Engine) { + group := e.Group(fmt.Sprintf("%s/alert_overview", conf.Options.Prefix)) + { + group.GET("", controller.DetailAlertOverview) + } +} diff --git a/src/router/router.go b/src/router/router.go index 8d099fb2a4ff1f0ee95413b70f83c651eadfdea2..0856e5324b3ed53ab024e41df299cbd8441fc7be 100644 --- a/src/router/router.go +++ b/src/router/router.go @@ -59,6 +59,8 @@ func Load(r *gin.Engine, middleware ...gin.HandlerFunc) { InitAlertListRouter(r) // 初始化prometheus路由 InitPrometheusRouter(r) + // 初始化预警总览配置路由 + InitAlertOverviewRouter(r) // 初始化工单管理路由 InitWorkOrderRouter(r) } diff --git a/src/service/alert_overview.go b/src/service/alert_overview.go new file mode 100644 index 0000000000000000000000000000000000000000..1d8cc722581daf6a22759222df0d38aac396afdc --- /dev/null +++ b/src/service/alert_overview.go @@ -0,0 +1,309 @@ +package service + +import ( + "github.com/jinzhu/copier" + "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/common/client" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" + "xorm.io/xorm" +) + +type AlertOverviewSvc struct { + User entity.SystemUserInfo +} + +func (a *AlertOverviewSvc) Add(session *xorm.Session, req request.AddAlertOverview) (classId int, err error) { + now := jsontime.Now() + data := entity.AlertOverview{ + CreatedBy: a.User.SystemAccount, + CreatedAt: now, + UpdatedBy: a.User.SystemAccount, + UpdatedAt: now, + } + _ = copier.Copy(&data, &req) + return +} + +func (a *AlertOverviewSvc) Update(session *xorm.Session, req request.UpdateAlertOverview) error { + now := jsontime.Now() + data := entity.AlertOverview{ + UpdatedBy: a.User.SystemAccount, + UpdatedAt: now, + } + _ = copier.Copy(&data, &req) + return nil +} + +func (a *AlertOverviewSvc) Overview(req request.DetailAlertOverview) (resp response.AlertOverviewItem, err error) { + now := jsontime.Now() + resp = response.AlertOverviewItem{ + AlertOverview: []entity.AlertOverview{ + { + RiskLevel: 4, + UnresolvedCount: 10, + TotalCount: 24, + List: []entity.AlertArray{ + { + MetricName: "CPU使用率过高", + UnresolvedCount: 4, + TotalCount: 8, + }, + { + MetricName: "内存不足", + UnresolvedCount: 1, + TotalCount: 2, + }, + { + MetricName: "磁盘空间不足", + UnresolvedCount: 3, + TotalCount: 4, + }, + { + MetricName: "服务中断", + UnresolvedCount: 1, + TotalCount: 4, + }, + { + MetricName: "响应时间超时", + UnresolvedCount: 2, + TotalCount: 6, + }, + }, + CreatedBy: "admin", + CreatedAt: now, + UpdatedBy: "admin", + UpdatedAt: now, + }, + { + RiskLevel: 3, + UnresolvedCount: 8, + TotalCount: 26, + List: []entity.AlertArray{ + { + MetricName: "CPU使用率过高", + UnresolvedCount: 4, + TotalCount: 12, + }, + { + MetricName: "内存不足", + UnresolvedCount: 1, + TotalCount: 10, + }, + { + MetricName: "磁盘空间不足", + UnresolvedCount: 3, + TotalCount: 8, + }, + { + MetricName: "服务中断", + UnresolvedCount: 1, + TotalCount: 4, + }, + { + MetricName: "响应时间超时", + UnresolvedCount: 2, + TotalCount: 6, + }, + }, + CreatedBy: "admin", + CreatedAt: now, + UpdatedBy: "admin", + UpdatedAt: now, + }, + { + RiskLevel: 2, + UnresolvedCount: 13, + TotalCount: 50, + List: []entity.AlertArray{ + { + MetricName: "CPU使用率过高", + UnresolvedCount: 4, + TotalCount: 12, + }, + { + MetricName: "内存不足", + UnresolvedCount: 1, + TotalCount: 10, + }, + { + MetricName: "磁盘空间不足", + UnresolvedCount: 3, + TotalCount: 8, + }, + { + MetricName: "服务中断", + UnresolvedCount: 1, + TotalCount: 4, + }, + { + MetricName: "响应时间超时", + UnresolvedCount: 2, + TotalCount: 6, + }, + }, + CreatedBy: "admin", + CreatedAt: now, + UpdatedBy: "admin", + UpdatedAt: now, + }, + { + RiskLevel: 1, + UnresolvedCount: 8, + TotalCount: 20, + List: []entity.AlertArray{ + { + MetricName: "CPU使用率过高", + UnresolvedCount: 4, + TotalCount: 12, + }, + { + MetricName: "内存不足", + UnresolvedCount: 1, + TotalCount: 10, + }, + { + MetricName: "磁盘空间不足", + UnresolvedCount: 3, + TotalCount: 8, + }, + { + MetricName: "服务中断", + UnresolvedCount: 1, + TotalCount: 4, + }, + { + MetricName: "响应时间超时", + UnresolvedCount: 2, + TotalCount: 6, + }, + }, + CreatedBy: "admin", + CreatedAt: now, + UpdatedBy: "admin", + UpdatedAt: now, + }, + }, + RiskLevelDistribution: []entity.RiskLevelDistribution{ + { + Name: "重大风险", + RiskLevel: 4, + Percentage: "10%", + }, + { + Name: "较大风险", + RiskLevel: 3, + Percentage: "20%", + }, + { + Name: "一般风险", + RiskLevel: 2, + Percentage: "30%", + }, + { + Name: "低风险", + RiskLevel: 1, + Percentage: "40%", + }, + }, + AlertStatusDistribution: []entity.AlertStatusDistribution{ + { + Name: "未恢复", + Status: 1, + Percentage: "30%", + }, + { + Name: "已恢复", + Status: 2, + Percentage: "70%", + }, + }, + AlertClassDistribution: []entity.AlertClassDistribution{ + { + Name: "容器集群", + ClassId: 1, + Percentage: "30%", + }, + { + Name: "容器节点", + ClassId: 2, + Percentage: "20%", + }, + { + Name: "容器组", + ClassId: 3, + Percentage: "30%", + }, + { + Name: "网关", + ClassId: 4, + Percentage: "20%", + }, + }, + AlertFrequencyDistribution: []entity.AlertFrequencyDistribution{ + { + Name: "0-3时", + Count: 12, + }, + { + Name: "3-6时", + Count: 20, + }, + { + Name: "6-9时", + Count: 11, + }, + { + Name: "9-12时", + Count: 50, + }, + { + Name: "12-15时", + Count: 60, + }, + { + Name: "15-18时", + Count: 30, + }, + { + Name: "18-21时", + Count: 16, + }, + { + Name: "21-24时", + Count: 6, + }, + }, + } + + return +} + +func (a *AlertOverviewSvc) List(req request.ListAlertOverview) (resp response.AlertOverviewList, err error) { + db, err := client.GetDbClient() + if err != nil { + return + } + session := db.NewSession() + defer session.Close() + session.Where("source_from = 1") + if req.ClassId != 0 { + session.Where("class_id = ?", req.ClassId) + } + if req.ClassName != "" { + session.Where("class_name LIKE ?", "%"+req.ClassName+"%") + } + resp.TotalCount, err = session.Limit(req.GetPageSize(), (req.GetPage()-1)*req.GetPageSize()). + OrderBy("sort_order").FindAndCount(&resp.List) + return +} + +func (a *AlertOverviewSvc) Delete(ids []int) (err error) { + db, err := client.GetDbClient() + if err != nil { + return + } + _, err = db.NewSession().In("class_id", ids).Delete(&entity.AlertOverview{}) + return +}