diff --git a/src/modules/network_element/controller/perf_kpi.go b/src/modules/network_element/controller/perf_kpi.go new file mode 100644 index 00000000..05919a05 --- /dev/null +++ b/src/modules/network_element/controller/perf_kpi.go @@ -0,0 +1,90 @@ +package controller + +import ( + "ems.agt/lib/core/utils/date" + "ems.agt/src/framework/i18n" + "ems.agt/src/framework/utils/ctx" + "ems.agt/src/framework/vo/result" + neService "ems.agt/src/modules/network_element/service" + "github.com/gin-gonic/gin" +) + +// 实例化控制层 PerfKPIController 结构体 +var NewPerfKPI = &PerfKPIController{ + neInfoService: neService.NewNeInfoImpl, + perfKPIService: neService.NewPerfKPIImpl, +} + +// 性能统计 +// +// PATH /kpi +type PerfKPIController struct { + // 网元信息服务 + neInfoService neService.INeInfo + // 统计信息服务 + perfKPIService neService.IPerfKPI +} + +// 获取统计数据 +// +// GET /data +func (s *PerfKPIController) GoldKPI(c *gin.Context) { + language := ctx.AcceptLanguage(c) + var querys struct { + NeType string `form:"neType" binding:"required"` + NeID string `form:"neId" binding:"required"` + StartTime string `form:"startTime" binding:"required"` + EndTime string `form:"endTime" binding:"required"` + Interval int64 `form:"interval" binding:"required"` + } + if err := c.ShouldBindQuery(&querys); err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + // 时间格式校验 + startTime := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS) + if startTime.IsZero() { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + } + startTimeStr := startTime.Format(date.YYYY_MM_DD_HH_MM_SS) + endTime := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS) + if startTime.IsZero() { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + } + endTimeStr := endTime.Format(date.YYYY_MM_DD_HH_MM_SS) + + // 查询网元获取IP + neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID) + if neInfo.NeId != querys.NeID || neInfo.IP == "" { + c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) + return + } + + // 获取数据指标id + var kpiIds []string + kpiTitles := s.perfKPIService.SelectGoldKPITitle(neInfo.NeType) + for _, kpiId := range kpiTitles { + kpiIds = append(kpiIds, kpiId.KPIID) + } + + // 查询数据 + kpiData := s.perfKPIService.SelectGoldKPI(neInfo.RmUID, neInfo.NeType, startTimeStr, endTimeStr, kpiIds, querys.Interval) + c.JSON(200, result.OkData(kpiData)) +} + +// 获取统计标题 +// +// GET /title +func (s *PerfKPIController) Title(c *gin.Context) { + language := ctx.AcceptLanguage(c) + neType := c.Query("neType") + if neType == "" { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + kpiTitles := s.perfKPIService.SelectGoldKPITitle(neType) + + c.JSON(200, result.OkData(kpiTitles)) +} diff --git a/src/modules/network_element/model/perf_kpi.go b/src/modules/network_element/model/perf_kpi.go new file mode 100644 index 00000000..def01641 --- /dev/null +++ b/src/modules/network_element/model/perf_kpi.go @@ -0,0 +1,11 @@ +package model + +// GoldKPITitle 黄金指标标题信息对象 kpi_title +type GoldKPITitle struct { + ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` + NeType string `json:"neType" gorm:"column:ne_type"` + KPIID string `json:"kpiId" gorm:"column:kpi_id"` + TitleJson string `json:"titleJson" gorm:"column:title_json"` + CnTitle string `json:"cnTitle" gorm:"column:cn_title"` + EnTitle string `json:"enTitle" gorm:"column:en_title"` +} diff --git a/src/modules/network_element/network_element.go b/src/modules/network_element/network_element.go index bcb385b5..d156c50d 100644 --- a/src/modules/network_element/network_element.go +++ b/src/modules/network_element/network_element.go @@ -141,4 +141,17 @@ func Setup(router *gin.Engine) { ) } + // 性能统计信息 + kpiGroup := neGroup.Group("/kpi") + { + kpiGroup.GET("/title", + middleware.PreAuthorize(nil), + controller.NewPerfKPI.Title, + ) + kpiGroup.GET("/data", + middleware.PreAuthorize(nil), + controller.NewPerfKPI.GoldKPI, + ) + } + } diff --git a/src/modules/network_element/repository/perf_kpi.go b/src/modules/network_element/repository/perf_kpi.go new file mode 100644 index 00000000..3035dca1 --- /dev/null +++ b/src/modules/network_element/repository/perf_kpi.go @@ -0,0 +1,12 @@ +package repository + +import "ems.agt/src/modules/network_element/model" + +// 性能统计 数据层接口 +type IPerfKPI interface { + // SelectGoldKPI 通过ne_type和ne_id查询网元信息 + SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any + + // SelectGoldKPITitle + SelectGoldKPITitle(neType string) []model.GoldKPITitle +} diff --git a/src/modules/network_element/repository/perf_kpi.impl.go b/src/modules/network_element/repository/perf_kpi.impl.go new file mode 100644 index 00000000..7a45f482 --- /dev/null +++ b/src/modules/network_element/repository/perf_kpi.impl.go @@ -0,0 +1,77 @@ +package repository + +import ( + "fmt" + "strings" + + "ems.agt/src/framework/datasource" + "ems.agt/src/framework/logger" + "ems.agt/src/modules/network_element/model" +) + +// 实例化数据层 PerfKPIImpl 结构体 +var NewPerfKPIImpl = &PerfKPIImpl{} + +// PerfKPIImpl 性能统计 数据层处理 +type PerfKPIImpl struct{} + +// SelectGoldKPI 通过网元指标数据信息 +func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any { + // 查询条件拼接 + var conditions []string + var params []any + if rmUID != "" { + conditions = append(conditions, "gk.rm_uid = ?") + params = append(params, rmUID) + } + if neType != "" { + conditions = append(conditions, "gk.ne_type = ?") + params = append(params, neType) + } + if startTime != "" { + conditions = append(conditions, "gk.start_time >= ?") + params = append(params, startTime) + } + if endTime != "" { + conditions = append(conditions, "gk.start_time <= ?") + params = append(params, endTime) + } + // 构建查询条件语句 + whereSql := "" + if len(conditions) > 0 { + whereSql += " where " + strings.Join(conditions, " and ") + } + + // 查询字段列 + timeFormat := "DATE_FORMAT(gk.start_time, '%Y-%m-%d %H:')" + minuteGroup := fmt.Sprintf("LPAD(FLOOR(MINUTE(gk.start_time) / %d) * %d, 2, '0')", interval, interval) + groupByField := fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, minuteGroup) + var fields = []string{ + groupByField, + "min(CASE WHEN gk.index != '' THEN gk.index ELSE 0 END) AS startIndex", + "min(CASE WHEN gk.ne_name != '' THEN gk.ne_name ELSE 0 END) AS neName", + } + for _, kid := range kpiIds { + str := fmt.Sprintf("sum(CASE WHEN gk.kpi_id = '%s' THEN gk.value ELSE 0 END) AS '%s'", kid, kid) + fields = append(fields, str) + } + fieldsSql := strings.Join(fields, ",") + + // 查询数据 + querySql := fmt.Sprintf("SELECT %s FROM gold_kpi gk %s GROUP BY timeGroup", fieldsSql, whereSql) + results, err := datasource.RawDB("", querySql, params) + if err != nil { + logger.Errorf("query err => %v", err) + } + return results +} + +// SelectGoldKPITitle 通过网元指标数据信息 +func (r *PerfKPIImpl) SelectGoldKPITitle(neType string) []model.GoldKPITitle { + result := []model.GoldKPITitle{} + tx := datasource.DefaultDB().Table("kpi_title").Where("ne_type = ?", neType).Find(&result) + if err := tx.Error; err != nil { + logger.Errorf("Delete err => %v", err) + } + return result +} diff --git a/src/modules/network_element/service/perf_kpi.go b/src/modules/network_element/service/perf_kpi.go new file mode 100644 index 00000000..201d2f84 --- /dev/null +++ b/src/modules/network_element/service/perf_kpi.go @@ -0,0 +1,12 @@ +package service + +import "ems.agt/src/modules/network_element/model" + +// 性能统计 数据层接口 +type IPerfKPI interface { + // SelectGoldKPI 通过ne_type和ne_id查询网元信息 + SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any + + // SelectGoldKPITitle + SelectGoldKPITitle(neType string) []model.GoldKPITitle +} diff --git a/src/modules/network_element/service/perf_kpi.impl.go b/src/modules/network_element/service/perf_kpi.impl.go new file mode 100644 index 00000000..40032390 --- /dev/null +++ b/src/modules/network_element/service/perf_kpi.impl.go @@ -0,0 +1,31 @@ +package service + +import ( + "ems.agt/src/modules/network_element/model" + "ems.agt/src/modules/network_element/repository" +) + +// 实例化数据层 PerfKPIImpl 结构体 +var NewPerfKPIImpl = &PerfKPIImpl{ + perfKPIRepository: repository.NewPerfKPIImpl, +} + +// PerfKPIImpl 性能统计 数据层处理 +type PerfKPIImpl struct { + // 性能统计数据信息 + perfKPIRepository repository.IPerfKPI +} + +// SelectGoldKPI 通过网元指标数据信息 +func (r *PerfKPIImpl) SelectGoldKPI(rmUID, neType string, startTime, endTime string, kpiIds []string, interval int64) []map[string]any { + data := r.perfKPIRepository.SelectGoldKPI(rmUID, neType, startTime, endTime, kpiIds, interval) + if data == nil { + return []map[string]any{} + } + return data +} + +// SelectGoldKPITitle 通过网元指标数据信息 +func (r *PerfKPIImpl) SelectGoldKPITitle(neType string) []model.GoldKPITitle { + return r.perfKPIRepository.SelectGoldKPITitle(neType) +}