Commit c618c05b authored by 李科's avatar 李科

feat: 告警总览

parent ea1e61a8
...@@ -108,6 +108,9 @@ require ( ...@@ -108,6 +108,9 @@ require (
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect
github.com/sirupsen/logrus v1.9.2 // indirect github.com/sirupsen/logrus v1.9.2 // indirect
github.com/syndtr/goleveldb v1.0.0 // 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/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect github.com/ugorji/go/codec v1.2.9 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
......
...@@ -647,6 +647,12 @@ github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE= ...@@ -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/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 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=
github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= 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/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/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
......
...@@ -21,25 +21,9 @@ type AlertArray struct { ...@@ -21,25 +21,9 @@ type AlertArray struct {
TotalCount int `json:"total_count"` // 总预警数 TotalCount int `json:"total_count"` // 总预警数
} }
type RiskLevelDistribution struct { type AlertDistribution struct {
Name string `json:"name"` // 名称 Name string `json:"name"` // 名称
//RiskLevel int `json:"risk_level"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险 Value int `json:"value"`
//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 AlertFrequencyDistribution struct { type AlertFrequencyDistribution struct {
......
...@@ -62,3 +62,46 @@ type Hits struct { ...@@ -62,3 +62,46 @@ type Hits struct {
MaxScore float64 `json:"max_score"` MaxScore float64 `json:"max_score"`
Hits []SubHits `json:"hits"` 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"`
}
...@@ -6,9 +6,9 @@ import ( ...@@ -6,9 +6,9 @@ import (
type AlertOverviewItem struct { type AlertOverviewItem struct {
AlertOverview []entity.AlertOverview `json:"alert_overview"` AlertOverview []entity.AlertOverview `json:"alert_overview"`
RiskLevelDistribution []entity.RiskLevelDistribution `json:"risk_level_distribution"` RiskLevelDistribution []entity.AlertDistribution `json:"risk_level_distribution"`
AlertStatusDistribution []entity.AlertStatusDistribution `json:"alert_status_distribution"` AlertStatusDistribution []entity.AlertDistribution `json:"alert_status_distribution"`
AlertClassDistribution []entity.AlertClassDistribution `json:"alert_class_distribution"` AlertClassDistribution []entity.AlertDistribution `json:"alert_class_distribution"`
AlertFrequencyDistribution entity.AlertFrequencyDistribution `json:"alert_frequency_distribution"` AlertFrequencyDistribution entity.AlertFrequencyDistribution `json:"alert_frequency_distribution"`
} }
......
...@@ -148,7 +148,7 @@ func RiskLeveText(code int) string { ...@@ -148,7 +148,7 @@ func RiskLeveText(code int) string {
case RiskLevelCritical: case RiskLevelCritical:
return "重大风险" return "重大风险"
default: default:
return "" return "未知"
} }
} }
...@@ -159,6 +159,19 @@ const ( ...@@ -159,6 +159,19 @@ const (
AlertClosed AlertClosed
) )
func AlertStatusText(code int) string {
switch code {
case AlertRecovered:
return "已恢复"
case AlertNotRecovered:
return "未恢复"
case AlertClosed:
return "已关闭"
default:
return "未知"
}
}
// 是否处置(工单管理),1:已处置,2:未处置 // 是否处置(工单管理),1:已处置,2:未处置
const ( const (
IsDisposedYes = 1 IsDisposedYes = 1
...@@ -172,7 +185,7 @@ func DisposedStatusText(code int) string { ...@@ -172,7 +185,7 @@ func DisposedStatusText(code int) string {
case IsDisposedNo: case IsDisposedNo:
return "未处置" return "未处置"
default: default:
return "未知状态" return "未知"
} }
} }
......
...@@ -155,6 +155,18 @@ func (a *AlertClassSvc) List(req request.ListAlertClass) (resp response.AlertCla ...@@ -155,6 +155,18 @@ func (a *AlertClassSvc) List(req request.ListAlertClass) (resp response.AlertCla
return 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) { func (a *AlertClassSvc) Tree(req request.ListAlertClass) (resp []*response.AlertClassNode, err error) {
db, err := client.GetDbClient() db, err := client.GetDbClient()
if err != nil { if err != nil {
......
package service package service
import ( import (
"context"
"errors"
"fmt"
"github.com/jinzhu/copier" "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/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "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/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/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"
"io"
"net/http"
"strings"
"time"
"xorm.io/xorm" "xorm.io/xorm"
) )
...@@ -37,207 +49,465 @@ func (a *AlertOverviewSvc) Update(session *xorm.Session, req request.UpdateAlert ...@@ -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) { 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{ resp = response.AlertOverviewItem{
AlertOverview: []entity.AlertOverview{ AlertOverview: alertOverviewList,
{ RiskLevelDistribution: riskLevelDistributions,
RiskLevel: 4, AlertStatusDistribution: alertStatusDistributions,
UnresolvedCount: 10, AlertClassDistribution: alertClassDistributions,
TotalCount: 24, AlertFrequencyDistribution: alertFrequencyDistribution,
List: []entity.AlertArray{ }
{ return
MetricName: "CPU使用率过高", }
UnresolvedCount: 4,
TotalCount: 8, func (a *AlertOverviewSvc) AlertOverview(req request.DetailAlertOverview) (resp []entity.AlertOverview, err error) {
}, var (
{ sources response.AggAlertOverview
MetricName: "内存不足", )
UnresolvedCount: 1,
TotalCount: 2, cli, err := client.GetOpenSearch()
}, if err != nil {
{ return
MetricName: "磁盘空间不足", }
UnresolvedCount: 3,
TotalCount: 4, if req.StartTime == "" {
}, req.StartTime = time.Now().Format("2006-01-02")
{ }
MetricName: "服务中断", if req.EndTime == "" {
UnresolvedCount: 1, req.EndTime = time.Now().Add(time.Hour * 24).Format("2006-01-02")
TotalCount: 4, }
},
{ content := strings.NewReader(fmt.Sprintf(`{
MetricName: "响应时间超时", "size": 0,
UnresolvedCount: 2, "query": {
TotalCount: 6, "range": {
}, "created_at": {
}, "gte": "%s",
CreatedBy: "admin", "lte": "%s"
CreatedAt: now, }
UpdatedBy: "admin", }
UpdatedAt: now, },
}, "aggs": {
{ "group": {
RiskLevel: 3, "terms": {
UnresolvedCount: 8, "field": "risk_level",
TotalCount: 26, "size": 10
List: []entity.AlertArray{ },
{ "aggs": {
MetricName: "CPU使用率过高", "group": {
UnresolvedCount: 4, "terms": {
TotalCount: 12, "field": "metric_config_id",
}, "size": 10
{ },
MetricName: "内存不足", "aggs": {
UnresolvedCount: 1, "unresolved_count": {
TotalCount: 10, "filter": {
}, "term": {
{ "status": 2
MetricName: "磁盘空间不足", }
UnresolvedCount: 3, }
TotalCount: 8, }
}, }
{ }
MetricName: "服务中断", }
UnresolvedCount: 1, }
TotalCount: 4, }
}, }`, req.StartTime, req.EndTime))
{
MetricName: "响应时间超时", res := opensearchapi.SearchRequest{
UnresolvedCount: 2, Index: []string{OpenSearchIndex},
TotalCount: 6, Body: content,
}, }
}, do, err := res.Do(context.Background(), cli)
CreatedBy: "admin", if err != nil {
CreatedAt: now, return
UpdatedBy: "admin", }
UpdatedAt: now, defer do.Body.Close()
}, if do.StatusCode < http.StatusOK && do.StatusCode > http.StatusIMUsed {
{ err = errors.New(do.String())
RiskLevel: 2, return
UnresolvedCount: 13, }
TotalCount: 50, body, err := io.ReadAll(do.Body)
List: []entity.AlertArray{ if err != nil {
{ return
MetricName: "CPU使用率过高", }
UnresolvedCount: 4,
TotalCount: 12, result := gjson.GetBytes(body, "aggregations")
}, err = json.Unmarshal([]byte(result.String()), &sources)
{ if err != nil {
MetricName: "内存不足", return
UnresolvedCount: 1, }
TotalCount: 10,
}, now := jsontime.Now()
{ for _, v := range sources.Group.Buckets {
MetricName: "磁盘空间不足", alertOverview := entity.AlertOverview{
UnresolvedCount: 3, RiskLevel: v.Key,
TotalCount: 8, UnresolvedCount: 0,
}, TotalCount: v.DocCount,
{ List: nil,
MetricName: "服务中断", CreatedBy: a.User.SystemAccount,
UnresolvedCount: 1, CreatedAt: now,
TotalCount: 4, UpdatedBy: a.User.SystemAccount,
}, UpdatedAt: now,
{ }
MetricName: "响应时间超时", var unresolvedCount int
UnresolvedCount: 2, var alertArray []entity.AlertArray
TotalCount: 6, for _, bucket := range v.Group.Buckets {
}, alertArray = append(alertArray, entity.AlertArray{
}, MetricName: bucket.Key,
CreatedBy: "admin", UnresolvedCount: bucket.UnresolvedCount.DocCount,
CreatedAt: now, TotalCount: bucket.DocCount,
UpdatedBy: "admin", })
UpdatedAt: now, unresolvedCount += bucket.UnresolvedCount.DocCount
}, }
{ alertOverview.UnresolvedCount = unresolvedCount
RiskLevel: 1, alertOverview.List = alertArray
UnresolvedCount: 8, resp = append(resp, alertOverview)
TotalCount: 20, }
List: []entity.AlertArray{ return
{
MetricName: "CPU使用率过高", }
UnresolvedCount: 4,
TotalCount: 12, func (a *AlertOverviewSvc) RiskLevelDistribution(req request.DetailAlertOverview) (resp []entity.AlertDistribution, err error) {
}, var (
{ sources response.AlertDistributionGroup
MetricName: "内存不足", )
UnresolvedCount: 1,
TotalCount: 10, cli, err := client.GetOpenSearch()
}, if err != nil {
{ return
MetricName: "磁盘空间不足", }
UnresolvedCount: 3,
TotalCount: 8, if req.StartTime == "" {
}, req.StartTime = time.Now().Format("2006-01-02")
{ }
MetricName: "服务中断", if req.EndTime == "" {
UnresolvedCount: 1, req.EndTime = time.Now().Add(time.Hour * 24).Format("2006-01-02")
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},
},
} }
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 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) { func (a *AlertOverviewSvc) List(req request.ListAlertOverview) (resp response.AlertOverviewList, err error) {
......
...@@ -93,6 +93,17 @@ func (m *MetricConfigSvc) List(req request.ListMetricConfig) (resp response.Metr ...@@ -93,6 +93,17 @@ func (m *MetricConfigSvc) List(req request.ListMetricConfig) (resp response.Metr
return 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) { func (m *MetricConfigSvc) Delete(ids []string) (err error) {
db, err := client.GetDbClient() db, err := client.GetDbClient()
if err != nil { if err != nil {
......
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