diff --git a/go.mod b/go.mod index 892bc61659649177ff03759098b6ebb4d4b429eb..ee2fc148198fa438f6dcb94f9c0df2d111734a57 100644 --- a/go.mod +++ b/go.mod @@ -108,6 +108,9 @@ require ( github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect github.com/sirupsen/logrus v1.9.2 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect + github.com/tidwall/gjson v1.16.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.9 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect diff --git a/go.sum b/go.sum index fc8a3b91fa2892767e9f65e12e6051a3116313a3..2c414d8c8ce8158dcd8655e2b58ea4099a409749 100644 --- a/go.sum +++ b/go.sum @@ -647,6 +647,12 @@ github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE= github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw= github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= +github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= +github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= diff --git a/src/bean/entity/alert_overview.go b/src/bean/entity/alert_overview.go index 44320cd789bb216da27865d124b8792b47095fb6..0398e8316555b004eb32c08a8c8ff9233ae6d493 100644 --- a/src/bean/entity/alert_overview.go +++ b/src/bean/entity/alert_overview.go @@ -21,25 +21,9 @@ 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"` // 百分比 - Value int `json:"value"` -} - -type AlertStatusDistribution struct { - Name string `json:"name"` // 名称 - //Status int `json:"status"` // 状态,1:已恢复 2:未恢复 3:已关闭 - //Percentage string `json:"percentage"` // 百分比 - Value int `json:"value"` -} - -type AlertClassDistribution struct { - Name string `json:"name"` // 名称 - //ClassId int `json:"class_id"` // 预警分类id - //Percentage string `json:"percentage"` // 百分比 - Value int `json:"value"` +type AlertDistribution struct { + Name string `json:"name"` // 名称 + Value int `json:"value"` } type AlertFrequencyDistribution struct { diff --git a/src/bean/vo/response/alert.go b/src/bean/vo/response/alert.go index 5c729b01921c483d2ee7b491aea6bde1b13df0ae..70a7ea32d0eee73303f8531c13ca3764bf43f41b 100644 --- a/src/bean/vo/response/alert.go +++ b/src/bean/vo/response/alert.go @@ -62,3 +62,46 @@ type Hits struct { MaxScore float64 `json:"max_score"` Hits []SubHits `json:"hits"` } + +type AggAlertOverview struct { + Group struct { + DocCountErrorUpperBound int `json:"doc_count_error_upper_bound"` + SumOtherDocCount int `json:"sum_other_doc_count"` + Buckets []struct { + Key int `json:"key"` + DocCount int `json:"doc_count"` + Group struct { + DocCountErrorUpperBound int `json:"doc_count_error_upper_bound"` + SumOtherDocCount int `json:"sum_other_doc_count"` + Buckets []struct { + Key string `json:"key"` + DocCount int `json:"doc_count"` + UnresolvedCount struct { + DocCount int `json:"doc_count"` + } `json:"unresolved_count"` + } `json:"buckets"` + } `json:"group"` + } `json:"buckets"` + } `json:"group"` +} + +type AlertDistributionGroup struct { + Group struct { + DocCountErrorUpperBound int `json:"doc_count_error_upper_bound"` + SumOtherDocCount int `json:"sum_other_doc_count"` + Buckets []struct { + Key int `json:"key"` + DocCount int `json:"doc_count"` + } `json:"buckets"` + } `json:"group"` +} + +type DateHistogramGroup struct { + Group struct { + Buckets []struct { + KeyAsString string `json:"key_as_string"` + Key int64 `json:"key"` + DocCount int `json:"doc_count"` + } `json:"buckets"` + } `json:"group"` +} diff --git a/src/bean/vo/response/alert_overview.go b/src/bean/vo/response/alert_overview.go index ec2615e3106d669e23e388ff514e976b4ed57db4..c6356940aa036d94e4d101bf02c02ffe0fffbd86 100644 --- a/src/bean/vo/response/alert_overview.go +++ b/src/bean/vo/response/alert_overview.go @@ -6,9 +6,9 @@ import ( 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"` + RiskLevelDistribution []entity.AlertDistribution `json:"risk_level_distribution"` + AlertStatusDistribution []entity.AlertDistribution `json:"alert_status_distribution"` + AlertClassDistribution []entity.AlertDistribution `json:"alert_class_distribution"` AlertFrequencyDistribution entity.AlertFrequencyDistribution `json:"alert_frequency_distribution"` } diff --git a/src/pkg/beagle/constant/constant.go b/src/pkg/beagle/constant/constant.go index 308251d997b09206525226cee77d415a3c728053..01b181b04f274da7d358bb24f00e6da0ec88c012 100644 --- a/src/pkg/beagle/constant/constant.go +++ b/src/pkg/beagle/constant/constant.go @@ -148,7 +148,7 @@ func RiskLeveText(code int) string { case RiskLevelCritical: return "重大风险" default: - return "" + return "未知" } } @@ -159,6 +159,19 @@ const ( AlertClosed ) +func AlertStatusText(code int) string { + switch code { + case AlertRecovered: + return "已恢复" + case AlertNotRecovered: + return "未恢复" + case AlertClosed: + return "已关闭" + default: + return "未知" + } +} + // 是否处置(工单管理),1:已处置,2:未处置 const ( IsDisposedYes = 1 @@ -172,7 +185,7 @@ func DisposedStatusText(code int) string { case IsDisposedNo: return "未处置" default: - return "未知状态" + return "未知" } } diff --git a/src/service/alert_class.go b/src/service/alert_class.go index 60f320d45ccc584a9f7427be495dba21914f26d1..0e587fb2535a2f2fdbe829381bace6b1a8f5d5de 100644 --- a/src/service/alert_class.go +++ b/src/service/alert_class.go @@ -155,6 +155,18 @@ func (a *AlertClassSvc) List(req request.ListAlertClass) (resp response.AlertCla return } +func (a *AlertClassSvc) AlertObjectList() (resp response.AlertClassList, err error) { + db, err := client.GetDbClient() + if err != nil { + return + } + session := db.NewSession() + defer session.Close() + session.Where("parent_id <> 0") + resp.TotalCount, err = session.OrderBy("sort_order").FindAndCount(&resp.List) + return +} + func (a *AlertClassSvc) Tree(req request.ListAlertClass) (resp []*response.AlertClassNode, err error) { db, err := client.GetDbClient() if err != nil { diff --git a/src/service/alert_overview.go b/src/service/alert_overview.go index 581e2df29e9696bc55ffcbbfbb4a2815bfe08559..9d2b1b33c2613012fd4a6c89f63287e5541e4ce1 100644 --- a/src/service/alert_overview.go +++ b/src/service/alert_overview.go @@ -1,12 +1,24 @@ package service import ( + "context" + "errors" + "fmt" "github.com/jinzhu/copier" + json "github.com/json-iterator/go" + "github.com/opensearch-project/opensearch-go/opensearchapi" + "github.com/spf13/cast" + "github.com/tidwall/gjson" "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/constant" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" + "io" + "net/http" + "strings" + "time" "xorm.io/xorm" ) @@ -37,207 +49,465 @@ func (a *AlertOverviewSvc) Update(session *xorm.Session, req request.UpdateAlert } func (a *AlertOverviewSvc) Overview(req request.DetailAlertOverview) (resp response.AlertOverviewItem, err error) { - now := jsontime.Now() + alertOverviewList, _ := a.AlertOverview(req) + metricConfigSvc := MetricConfigSvc{User: a.User} + nameList, _ := metricConfigSvc.NameList() + for i := 0; i < len(alertOverviewList); i++ { + for j := 0; j < len(alertOverviewList[i].List); j++ { + for _, v := range nameList.List { + if v.Id == alertOverviewList[i].List[j].MetricName { + alertOverviewList[i].List[j].MetricName = v.MetricName + break + } + } + } + } + + riskLevelDistributions, _ := a.RiskLevelDistribution(req) + alertStatusDistributions, _ := a.AlertStatusDistribution(req) + alertClassDistributions, _ := a.AlertClassDistribution(req) + alertFrequencyDistribution, _ := a.AlertFrequencyDistribution(req) 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: "重大风险", - Value: 1, - }, - { - Name: "较大风险", - Value: 2, - }, - { - Name: "一般风险", - Value: 3, - }, - { - Name: "低风险", - Value: 4, - }, - }, - AlertStatusDistribution: []entity.AlertStatusDistribution{ - { - Name: "未恢复", - Value: 4, - }, - { - Name: "已恢复", - Value: 6, - }, - }, - AlertClassDistribution: []entity.AlertClassDistribution{ - { - Name: "容器集群", - Value: 1, - }, - { - Name: "容器节点", - Value: 2, - }, - { - Name: "容器组", - Value: 3, - }, - { - Name: "网关", - Value: 4, - }, - }, - AlertFrequencyDistribution: entity.AlertFrequencyDistribution{ - XAxis: []string{"0-3时", "3-6时", "6-9时", "9-12时", "12-15时", "15-18时", "18-21时", "21-24时"}, - Data: []int{12, 20, 11, 50, 60, 30, 16, 6}, - }, + AlertOverview: alertOverviewList, + RiskLevelDistribution: riskLevelDistributions, + AlertStatusDistribution: alertStatusDistributions, + AlertClassDistribution: alertClassDistributions, + AlertFrequencyDistribution: alertFrequencyDistribution, + } + return +} + +func (a *AlertOverviewSvc) AlertOverview(req request.DetailAlertOverview) (resp []entity.AlertOverview, err error) { + var ( + sources response.AggAlertOverview + ) + + cli, err := client.GetOpenSearch() + if err != nil { + return + } + + if req.StartTime == "" { + req.StartTime = time.Now().Format("2006-01-02") + } + if req.EndTime == "" { + req.EndTime = time.Now().Add(time.Hour * 24).Format("2006-01-02") + } + + content := strings.NewReader(fmt.Sprintf(`{ + "size": 0, + "query": { + "range": { + "created_at": { + "gte": "%s", + "lte": "%s" + } + } + }, + "aggs": { + "group": { + "terms": { + "field": "risk_level", + "size": 10 + }, + "aggs": { + "group": { + "terms": { + "field": "metric_config_id", + "size": 10 + }, + "aggs": { + "unresolved_count": { + "filter": { + "term": { + "status": 2 + } + } + } + } + } + } + } + } +}`, req.StartTime, req.EndTime)) + + res := opensearchapi.SearchRequest{ + Index: []string{OpenSearchIndex}, + 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 + } + + result := gjson.GetBytes(body, "aggregations") + err = json.Unmarshal([]byte(result.String()), &sources) + if err != nil { + return + } + + now := jsontime.Now() + for _, v := range sources.Group.Buckets { + alertOverview := entity.AlertOverview{ + RiskLevel: v.Key, + UnresolvedCount: 0, + TotalCount: v.DocCount, + List: nil, + CreatedBy: a.User.SystemAccount, + CreatedAt: now, + UpdatedBy: a.User.SystemAccount, + UpdatedAt: now, + } + var unresolvedCount int + var alertArray []entity.AlertArray + for _, bucket := range v.Group.Buckets { + alertArray = append(alertArray, entity.AlertArray{ + MetricName: bucket.Key, + UnresolvedCount: bucket.UnresolvedCount.DocCount, + TotalCount: bucket.DocCount, + }) + unresolvedCount += bucket.UnresolvedCount.DocCount + } + alertOverview.UnresolvedCount = unresolvedCount + alertOverview.List = alertArray + resp = append(resp, alertOverview) + } + return + +} + +func (a *AlertOverviewSvc) RiskLevelDistribution(req request.DetailAlertOverview) (resp []entity.AlertDistribution, err error) { + var ( + sources response.AlertDistributionGroup + ) + + cli, err := client.GetOpenSearch() + if err != nil { + return + } + + if req.StartTime == "" { + req.StartTime = time.Now().Format("2006-01-02") + } + if req.EndTime == "" { + req.EndTime = time.Now().Add(time.Hour * 24).Format("2006-01-02") } + content := strings.NewReader(fmt.Sprintf(`{ + "size": 0, + "query": { + "range": { + "created_at": { + "gte": "%s", + "lte": "%s" + } + } + }, + "aggs": { + "group": { + "terms": { + "field": "risk_level", + "size": 10 + } + } + } +}`, req.StartTime, req.EndTime)) + + res := opensearchapi.SearchRequest{ + Index: []string{OpenSearchIndex}, + 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 + } + + result := gjson.GetBytes(body, "aggregations") + err = json.Unmarshal([]byte(result.String()), &sources) + if err != nil { + return + } + + var alertDistributions []entity.AlertDistribution + riskLevels := []int{constant.RiskLevelLow, constant.RiskLevelModerate, constant.RiskLevelHigh, constant.RiskLevelCritical} + for _, level := range riskLevels { + riskLevelDistribution := entity.AlertDistribution{Name: constant.RiskLeveText(level)} + for _, bucket := range sources.Group.Buckets { + if level == bucket.Key { + riskLevelDistribution.Value = bucket.DocCount + break + } + } + alertDistributions = append(alertDistributions, riskLevelDistribution) + } + resp = alertDistributions return + +} + +func (a *AlertOverviewSvc) AlertStatusDistribution(req request.DetailAlertOverview) (resp []entity.AlertDistribution, err error) { + var ( + sources response.AlertDistributionGroup + ) + + cli, err := client.GetOpenSearch() + if err != nil { + return + } + + if req.StartTime == "" { + req.StartTime = time.Now().Format("2006-01-02") + } + if req.EndTime == "" { + req.EndTime = time.Now().Add(time.Hour * 24).Format("2006-01-02") + } + + content := strings.NewReader(fmt.Sprintf(`{ + "size": 0, + "query": { + "range": { + "created_at": { + "gte": "%s", + "lte": "%s" + } + } + }, + "aggs": { + "group": { + "terms": { + "field": "status", + "size": 10 + } + } + } +}`, req.StartTime, req.EndTime)) + + res := opensearchapi.SearchRequest{ + Index: []string{OpenSearchIndex}, + 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 + } + + result := gjson.GetBytes(body, "aggregations") + err = json.Unmarshal([]byte(result.String()), &sources) + if err != nil { + return + } + + var alertDistributions []entity.AlertDistribution + alertStatusList := []int{constant.AlertRecovered, constant.AlertNotRecovered, constant.AlertClosed} + for _, status := range alertStatusList { + alertStatusDistribution := entity.AlertDistribution{Name: constant.AlertStatusText(status)} + for _, bucket := range sources.Group.Buckets { + if status == bucket.Key { + alertStatusDistribution.Value = bucket.DocCount + break + } + } + alertDistributions = append(alertDistributions, alertStatusDistribution) + } + resp = alertDistributions + return + +} + +func (a *AlertOverviewSvc) AlertClassDistribution(req request.DetailAlertOverview) (resp []entity.AlertDistribution, err error) { + var ( + sources response.AlertDistributionGroup + ) + + cli, err := client.GetOpenSearch() + if err != nil { + return + } + + if req.StartTime == "" { + req.StartTime = time.Now().Format("2006-01-02") + } + if req.EndTime == "" { + req.EndTime = time.Now().Add(time.Hour * 24).Format("2006-01-02") + } + + content := strings.NewReader(fmt.Sprintf(`{ + "size": 0, + "query": { + "range": { + "created_at": { + "gte": "%s", + "lte": "%s" + } + } + }, + "aggs": { + "group": { + "terms": { + "field": "class_id", + "size": 10 + } + } + } +}`, req.StartTime, req.EndTime)) + + res := opensearchapi.SearchRequest{ + Index: []string{OpenSearchIndex}, + 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 + } + + result := gjson.GetBytes(body, "aggregations") + err = json.Unmarshal([]byte(result.String()), &sources) + if err != nil { + return + } + + alertClassSvc := AlertClassSvc{User: a.User} + alertObjectList, err := alertClassSvc.AlertObjectList() + + var alertDistributions []entity.AlertDistribution + for _, bucket := range sources.Group.Buckets { + alertDistribution := entity.AlertDistribution{Value: bucket.DocCount} + for _, object := range alertObjectList.List { + if bucket.Key == object.ClassId { + alertDistribution.Name = object.ClassName + } + } + alertDistributions = append(alertDistributions, alertDistribution) + } + resp = alertDistributions + return + +} + +func (a *AlertOverviewSvc) AlertFrequencyDistribution(req request.DetailAlertOverview) (resp entity.AlertFrequencyDistribution, err error) { + var ( + sources response.DateHistogramGroup + ) + + cli, err := client.GetOpenSearch() + if err != nil { + return + } + + if req.StartTime == "" { + req.StartTime = time.Now().Format("2006-01-02") + } + if req.EndTime == "" { + req.EndTime = time.Now().Add(time.Hour * 24).Format("2006-01-02") + } + + /* + "gte": "now/d", + "lt": "now+1d/d" + */ + /* + "gte": "2023-07-17", + "lte": "2023-07-18" + */ + content := strings.NewReader(`{ + "size": 0, + "query": { + "range": { + "created_at": { + "gte": "now/d", + "lt": "now+1d/d" + } + } + }, + "aggs": { + "group": { + "date_histogram": { + "field": "created_at", + "interval": "3h", + "format": "HH", + "time_zone": "+00:00" + } + } + } + }`) + + res := opensearchapi.SearchRequest{ + Index: []string{OpenSearchIndex}, + 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 + } + + result := gjson.GetBytes(body, "aggregations") + err = json.Unmarshal([]byte(result.String()), &sources) + if err != nil { + return + } + + alertFrequencyDistribution := entity.AlertFrequencyDistribution{ + XAxis: []string{"0-3时", "3-6时", "6-9时", "9-12时", "12-15时", "15-18时", "18-21时", "21-24时"}, + Data: []int{0, 0, 0, 0, 0, 0, 0, 0}, + } + + for i := 0; i < len(alertFrequencyDistribution.XAxis); i++ { + for _, bucket := range sources.Group.Buckets { + if cast.ToInt(bucket.KeyAsString) == i*3 { + alertFrequencyDistribution.Data[i] = bucket.DocCount + break + } + } + } + + resp = alertFrequencyDistribution + return + } func (a *AlertOverviewSvc) List(req request.ListAlertOverview) (resp response.AlertOverviewList, err error) { diff --git a/src/service/metric_config.go b/src/service/metric_config.go index 0039073ee2e5e50763415f8e9f8179272c5eb12b..bdd664363db57bc0456c31318232cf7ef15aa9e7 100644 --- a/src/service/metric_config.go +++ b/src/service/metric_config.go @@ -93,6 +93,17 @@ func (m *MetricConfigSvc) List(req request.ListMetricConfig) (resp response.Metr return } +func (m *MetricConfigSvc) NameList() (resp response.MetricConfigList, err error) { + db, err := client.GetDbClient() + if err != nil { + return + } + session := db.NewSession() + defer session.Close() + resp.TotalCount, err = session.Select("id,metric_name").FindAndCount(&resp.List) + return +} + func (m *MetricConfigSvc) Delete(ids []string) (err error) { db, err := client.GetDbClient() if err != nil {