feat: omc原始代码

This commit is contained in:
TsMask
2024-03-12 10:58:33 +08:00
parent 5133c93971
commit 2d01bb86d1
432 changed files with 66597 additions and 1 deletions

View File

@@ -0,0 +1,81 @@
package controller
import (
"strings"
"nms_nbi/src/framework/i18n"
"nms_nbi/src/framework/utils/ctx"
"nms_nbi/src/framework/utils/parse"
"nms_nbi/src/framework/vo/result"
"nms_nbi/src/modules/network_data/model"
neDataService "nms_nbi/src/modules/network_data/service"
neService "nms_nbi/src/modules/network_element/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 AMFController 结构体
var NewAMFController = &AMFController{
neInfoService: neService.NewNeInfoImpl,
ueEventService: neDataService.NewUEEventImpl,
}
// 网元AMF
//
// PATH /amf
type AMFController struct {
// 网元信息服务
neInfoService neService.INeInfo
// CDR会话事件服务
ueEventService neDataService.IUEEvent
}
// UE会话列表
//
// GET /ue/list
func (s *AMFController) UEList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys model.UEEventQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取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
}
querys.RmUID = neInfo.RmUID
// 查询数据
data := s.ueEventService.SelectPage(querys)
c.JSON(200, result.Ok(data))
}
// UE会话删除
//
// DELETE /ue/:ueIds
func (s *AMFController) UERemove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
ueIds := c.Param("ueIds")
if ueIds == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 处理字符转id数组后去重
ids := strings.Split(ueIds, ",")
uniqueIDs := parse.RemoveDuplicates(ids)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
rows, err := s.ueEventService.DeleteByIds(uniqueIDs)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, result.OkMsg(msg))
}

View File

@@ -0,0 +1,81 @@
package controller
import (
"strings"
"nms_nbi/src/framework/i18n"
"nms_nbi/src/framework/utils/ctx"
"nms_nbi/src/framework/utils/parse"
"nms_nbi/src/framework/vo/result"
"nms_nbi/src/modules/network_data/model"
neDataService "nms_nbi/src/modules/network_data/service"
neService "nms_nbi/src/modules/network_element/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 IMSController 结构体
var NewIMSController = &IMSController{
neInfoService: neService.NewNeInfoImpl,
cdrEventService: neDataService.NewCDREventImpl,
}
// 网元IMS
//
// PATH /ims
type IMSController struct {
// 网元信息服务
neInfoService neService.INeInfo
// CDR会话事件服务
cdrEventService neDataService.ICDREvent
}
// CDR会话列表
//
// GET /cdr/list
func (s *IMSController) CDRList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys model.CDREventQuery
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取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
}
querys.RmUID = neInfo.RmUID
// 查询数据
data := s.cdrEventService.SelectPage(querys)
c.JSON(200, result.Ok(data))
}
// CDR会话删除
//
// DELETE /cdr/:cdrIds
func (s *IMSController) CDRRemove(c *gin.Context) {
language := ctx.AcceptLanguage(c)
cdrIds := c.Param("cdrIds")
if cdrIds == "" {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 处理字符转id数组后去重
ids := strings.Split(cdrIds, ",")
uniqueIDs := parse.RemoveDuplicates(ids)
if len(uniqueIDs) <= 0 {
c.JSON(200, result.Err(nil))
return
}
rows, err := s.cdrEventService.DeleteByIds(uniqueIDs)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
}
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, result.OkMsg(msg))
}

View File

@@ -0,0 +1,85 @@
package controller
import (
"nms_nbi/lib/core/utils/date"
"nms_nbi/src/framework/i18n"
"nms_nbi/src/framework/utils/ctx"
"nms_nbi/src/framework/vo/result"
"nms_nbi/src/modules/network_data/model"
neDataService "nms_nbi/src/modules/network_data/service"
neService "nms_nbi/src/modules/network_element/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 PerfKPIController 结构体
var NewPerfKPIController = &PerfKPIController{
neInfoService: neService.NewNeInfoImpl,
perfKPIService: neDataService.NewPerfKPIImpl,
}
// 性能统计
//
// PATH /kpi
type PerfKPIController struct {
// 网元信息服务
neInfoService neService.INeInfo
// 统计信息服务
perfKPIService neDataService.IPerfKPI
}
// 获取统计数据
//
// GET /data
func (s *PerfKPIController) GoldKPI(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys model.GoldKPIQuery
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")))
return
}
endTime := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
if endTime.IsZero() {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
if querys.Interval < 5 || querys.Interval > 3600 {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取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
}
querys.RmUID = neInfo.RmUID
// 查询数据
kpiData := s.perfKPIService.SelectGoldKPI(querys)
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))
}

View File

@@ -0,0 +1,55 @@
package controller
import (
"nms_nbi/src/framework/i18n"
"nms_nbi/src/framework/utils/ctx"
"nms_nbi/src/framework/vo/result"
neDataService "nms_nbi/src/modules/network_data/service"
neService "nms_nbi/src/modules/network_element/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 UPFController 结构体
var NewUPFController = &UPFController{
neInfoService: neService.NewNeInfoImpl,
perfKPIService: neDataService.NewPerfKPIImpl,
}
// 网元UPF
//
// PATH /upf
type UPFController struct {
// 网元信息服务
neInfoService neService.INeInfo
// 统计信息服务
perfKPIService neDataService.IPerfKPI
}
// 总流量数 N3上行 N6下行
// 单位 比特(bit)
//
// GET /totalFlow
func (s *UPFController) TotalFlow(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
NeType string `json:"neType" form:"neType" binding:"required"`
NeID string `form:"neId" binding:"required"`
Day int `form:"day" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); querys.Day < 0 || err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元获取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
}
data := s.perfKPIService.SelectUPFTotalFlow(neInfo.NeType, neInfo.RmUID, querys.Day)
c.JSON(200, result.OkData(data))
}

View File

@@ -0,0 +1,28 @@
package model
import "time"
// CDREvent CDR会话对象 cdr_event
type CDREvent struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type"`
NeName string `json:"neName" gorm:"column:ne_name"`
RmUID string `json:"rmUID" gorm:"column:rm_uid"`
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
CDRJSONStr string `json:"cdrJSON" gorm:"column:cdr_json"`
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
}
// CDREventQuery CDR会话对象查询参数结构体
type CDREventQuery struct {
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型, 暂时支持IMS
NeID string `json:"neId" form:"neId" binding:"required"`
RmUID string `json:"rmUID" form:"rmUID"`
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC MOSM MTSM
StartTime string `json:"startTime" form:"startTime"`
EndTime string `json:"endTime" form:"endTime"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序asc desc
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
}

View File

@@ -0,0 +1,23 @@
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"`
}
// GoldKPIQuery 黄金指标查询参数结构体
type GoldKPIQuery 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"`
RmUID string `form:"rmUID"`
SortField string `form:"sortField" binding:"omitempty,oneof=timeGroup"`
SortOrder string `form:"sortOrder" binding:"omitempty,oneof=asc desc"`
}

View File

@@ -0,0 +1,29 @@
package model
import "time"
// UEEvent UE会话对象 ue_event
type UEEvent struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type"`
NeName string `json:"neName" gorm:"column:ne_name"`
RmUID string `json:"rmUID" gorm:"column:rm_uid"`
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
EventType string `json:"eventType" gorm:"column:event_type"`
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"`
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
}
// UEEventQuery UE会话对象查询参数结构体
type UEEventQuery struct {
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型, 暂时支持AMF
NeID string `json:"neId" form:"neId" binding:"required"`
RmUID string `json:"rmUID" form:"rmUID"`
EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state
StartTime string `json:"startTime" form:"startTime"`
EndTime string `json:"endTime" form:"endTime"`
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序asc desc
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
}

View File

@@ -0,0 +1,72 @@
package networkdata
import (
"nms_nbi/src/framework/logger"
"nms_nbi/src/framework/middleware"
"nms_nbi/src/framework/middleware/collectlogs"
"nms_nbi/src/modules/network_data/controller"
"github.com/gin-gonic/gin"
)
// 模块路由注册
func Setup(router *gin.Engine) {
logger.Infof("开始加载 ====> network_data 模块路由")
neDataGroup := router.Group("/neData")
// 性能统计信息
kpiGroup := neDataGroup.Group("/kpi")
{
kpiGroup.GET("/title",
middleware.PreAuthorize(nil),
controller.NewPerfKPIController.Title,
)
kpiGroup.GET("/data",
middleware.PreAuthorize(nil),
controller.NewPerfKPIController.GoldKPI,
)
}
// 网元IMS
imsGroup := neDataGroup.Group("/ims")
{
// CDR会话事件列表
imsGroup.GET("/cdr/list",
middleware.PreAuthorize(nil),
controller.NewIMSController.CDRList,
)
// CDR会话删除
imsGroup.DELETE("/cdr/:cdrIds",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewIMSController.CDRRemove,
)
}
// 网元AMF
amfGroup := neDataGroup.Group("/amf")
{
// UE会话事件
amfGroup.GET("/ue/list",
middleware.PreAuthorize(nil),
controller.NewAMFController.UEList,
)
// UE会话删除
amfGroup.DELETE("/ue/:ueIds",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewAMFController.UERemove,
)
}
// 网元UPF
upfGroup := neDataGroup.Group("/upf")
{
upfGroup.GET("/totalFlow",
middleware.PreAuthorize(nil),
controller.NewUPFController.TotalFlow,
)
}
}

View File

@@ -0,0 +1,15 @@
package repository
import "nms_nbi/src/modules/network_data/model"
// CDR会话事件 数据层接口
type ICDREvent interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.CDREventQuery) map[string]any
// SelectByIds 通过ID查询
SelectByIds(cdrIds []string) []model.CDREvent
// DeleteByIds 批量删除信息
DeleteByIds(cdrIds []string) int64
}

View File

@@ -0,0 +1,171 @@
package repository
import (
"fmt"
"strings"
"nms_nbi/src/framework/datasource"
"nms_nbi/src/framework/logger"
"nms_nbi/src/framework/utils/date"
"nms_nbi/src/framework/utils/parse"
"nms_nbi/src/framework/utils/repo"
"nms_nbi/src/modules/network_data/model"
)
// 实例化数据层 CDREventImpl 结构体
var NewCDREventImpl = &CDREventImpl{
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event`,
resultMap: map[string]string{
"id": "ID",
"ne_type": "NeType",
"ne_name": "NeName",
"rm_uid": "RmUID",
"timestamp": "Timestamp",
"cdr_json": "CDRJSONStr",
"created_at": "CreatedAt",
},
}
// CDREventImpl CDR会话事件 数据层处理
type CDREventImpl struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
resultMap map[string]string
}
// convertResultRows 将结果记录转实体结果组
func (r *CDREventImpl) convertResultRows(rows []map[string]any) []model.CDREvent {
arr := make([]model.CDREvent, 0)
for _, row := range rows {
item := model.CDREvent{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
repo.SetFieldValue(&item, keyMapper, value)
}
}
arr = append(arr, item)
}
return arr
}
// SelectPage 根据条件分页查询
func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if querys.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, querys.NeType)
}
if querys.RmUID != "" {
conditions = append(conditions, "rm_uid = ?")
params = append(params, querys.RmUID)
}
if querys.RmUID != "" {
conditions = append(conditions, "rm_uid = ?")
params = append(params, querys.RmUID)
}
if querys.StartTime != "" {
conditions = append(conditions, "timestamp >= ?")
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
params = append(params, beginDate.Unix())
}
if querys.EndTime != "" {
conditions = append(conditions, "timestamp <= ?")
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
params = append(params, endDate.Unix())
}
if querys.RecordType != "" {
recordTypes := strings.Split(querys.RecordType, ",")
placeholder := repo.KeyPlaceholderByQuery(len(recordTypes))
conditions = append(conditions, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') in (%s)", placeholder))
for _, recordType := range recordTypes {
params = append(params, recordType)
}
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
result := map[string]any{
"total": 0,
"rows": []model.CDREvent{},
}
// 查询数量 长度为0直接返回
totalSql := "select count(1) as 'total' from cdr_event"
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
if err != nil {
logger.Errorf("total err => %v", err)
return result
}
total := parse.Number(totalRows[0]["total"])
if total == 0 {
return result
} else {
result["total"] = total
}
// 分页
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
pageSql := " limit ?,? "
params = append(params, pageNum*pageSize)
params = append(params, pageSize)
// 排序
orderSql := ""
if querys.SortField != "" {
sortSql := querys.SortField
if querys.SortOrder != "" {
if querys.SortOrder == "desc" {
sortSql += " desc "
} else {
sortSql += " asc "
}
}
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
}
// 查询数据
querySql := r.selectSql + whereSql + orderSql + pageSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
// 转换实体
result["rows"] = r.convertResultRows(results)
return result
}
// SelectByIds 通过ID查询
func (r *CDREventImpl) SelectByIds(cdrIds []string) []model.CDREvent {
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
querySql := r.selectSql + " where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(cdrIds)
results, err := datasource.RawDB("", querySql, parameters)
if err != nil {
logger.Errorf("query err => %v", err)
return []model.CDREvent{}
}
// 转换实体
return r.convertResultRows(results)
}
// DeleteByIds 批量删除信息
func (r *CDREventImpl) DeleteByIds(cdrIds []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
sql := "delete from cdr_event where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(cdrIds)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {
logger.Errorf("delete err => %v", err)
return 0
}
return results
}

View File

@@ -0,0 +1,15 @@
package repository
import "nms_nbi/src/modules/network_data/model"
// 性能统计 数据层接口
type IPerfKPI interface {
// SelectGoldKPI 通过网元指标数据信息
SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any
// SelectGoldKPITitle 网元对应的指标名称
SelectGoldKPITitle(neType string) []model.GoldKPITitle
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
SelectUPFTotalFlow(neType, rmUID, startDate, endDate string) map[string]any
}

View File

@@ -0,0 +1,133 @@
package repository
import (
"fmt"
"strings"
"nms_nbi/src/framework/datasource"
"nms_nbi/src/framework/logger"
"nms_nbi/src/modules/network_data/model"
)
// 实例化数据层 PerfKPIImpl 结构体
var NewPerfKPIImpl = &PerfKPIImpl{}
// PerfKPIImpl 性能统计 数据层处理
type PerfKPIImpl struct{}
// SelectGoldKPI 通过网元指标数据信息
func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if query.RmUID != "" {
conditions = append(conditions, "gk.rm_uid = ?")
params = append(params, query.RmUID)
}
if query.NeType != "" {
conditions = append(conditions, "gk.ne_type = ?")
params = append(params, query.NeType)
}
if query.StartTime != "" {
conditions = append(conditions, "gk.start_time >= ?")
params = append(params, query.StartTime)
}
if query.EndTime != "" {
conditions = append(conditions, "gk.start_time <= ?")
params = append(params, query.EndTime)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
// 查询字段列
timeFormat := "DATE_FORMAT(gk.start_time, '%Y-%m-%d %H:%i:')"
secondGroup := fmt.Sprintf("LPAD(FLOOR(SECOND(gk.start_time) / %d) * %d, 2, '0')", query.Interval, query.Interval)
groupByField := fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, secondGroup)
if query.Interval > 60 {
minute := query.Interval / 60
timeFormat = "DATE_FORMAT(gk.start_time, '%Y-%m-%d %H:')"
minuteGroup := fmt.Sprintf("LPAD(FLOOR(MINUTE(gk.start_time) / %d) * %d, 2, '0')", minute, minute)
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_type != '' THEN gk.ne_type ELSE 0 END) AS neType",
"min(CASE WHEN gk.ne_name != '' THEN gk.ne_name ELSE 0 END) AS neName",
}
for _, kid := range kpiIds {
// 特殊字段只取最后一次收到的非0值
if kid == "AMF.01" || kid == "UDM.01" || kid == "UDM.02" || kid == "UDM.03" || kid == "SMF.01" {
str := fmt.Sprintf("IFNULL(SUBSTRING_INDEX(GROUP_CONCAT( CASE WHEN gk.kpi_id = '%s' and gk.VALUE != 0 THEN gk.VALUE END ), ',', 1), 0) AS '%s'", kid, kid)
fields = append(fields, str)
} else {
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, ",")
// 查询数据
if query.SortField == "" {
query.SortField = "timeGroup"
}
if query.SortOrder == "" {
query.SortOrder = "desc"
}
orderSql := fmt.Sprintf(" order by %s %s", query.SortField, query.SortOrder)
querySql := fmt.Sprintf("SELECT %s FROM gold_kpi gk %s GROUP BY timeGroup %s", fieldsSql, whereSql, orderSql)
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("Find err => %v", err)
}
return result
}
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
func (r *PerfKPIImpl) SelectUPFTotalFlow(neType, rmUID, startDate, endDate string) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if neType != "" {
conditions = append(conditions, "gk.ne_type = ?")
params = append(params, neType)
}
if rmUID != "" {
conditions = append(conditions, "gk.rm_uid = ?")
params = append(params, rmUID)
}
if startDate != "" {
conditions = append(conditions, "gk.date >= ?")
params = append(params, startDate)
}
if endDate != "" {
conditions = append(conditions, "gk.date <= ?")
params = append(params, endDate)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
// 查询数据
querySql := fmt.Sprintf("SELECT sum( CASE WHEN gk.kpi_id = 'UPF.03' THEN gk.VALUE ELSE 0 END ) AS 'up', sum( CASE WHEN gk.kpi_id = 'UPF.06' THEN gk.VALUE ELSE 0 END ) AS 'down' FROM gold_kpi gk %s", whereSql)
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
return results[0]
}

View File

@@ -0,0 +1,15 @@
package repository
import "nms_nbi/src/modules/network_data/model"
// UE会话事件 数据层接口
type IUEEvent interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.UEEventQuery) map[string]any
// SelectByIds 通过ID查询
SelectByIds(ueIds []string) []model.UEEvent
// DeleteByIds 批量删除信息
DeleteByIds(ueIds []string) int64
}

View File

@@ -0,0 +1,168 @@
package repository
import (
"fmt"
"strings"
"nms_nbi/src/framework/datasource"
"nms_nbi/src/framework/logger"
"nms_nbi/src/framework/utils/date"
"nms_nbi/src/framework/utils/parse"
"nms_nbi/src/framework/utils/repo"
"nms_nbi/src/modules/network_data/model"
)
// 实例化数据层 UEEventImpl 结构体
var NewUEEventImpl = &UEEventImpl{
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, event_type, event_json, created_at from ue_event`,
resultMap: map[string]string{
"id": "ID",
"ne_type": "NeType",
"ne_name": "NeName",
"rm_uid": "RmUID",
"timestamp": "Timestamp",
"event_type": "EventType",
"event_json": "EventJSONStr",
"created_at": "CreatedAt",
},
}
// UEEventImpl UE会话事件 数据层处理
type UEEventImpl struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
resultMap map[string]string
}
// convertResultRows 将结果记录转实体结果组
func (r *UEEventImpl) convertResultRows(rows []map[string]any) []model.UEEvent {
arr := make([]model.UEEvent, 0)
for _, row := range rows {
item := model.UEEvent{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
repo.SetFieldValue(&item, keyMapper, value)
}
}
arr = append(arr, item)
}
return arr
}
// SelectPage 根据条件分页查询
func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
// 查询条件拼接
var conditions []string
var params []any
if querys.NeType != "" {
conditions = append(conditions, "ne_type = ?")
params = append(params, querys.NeType)
}
if querys.RmUID != "" {
conditions = append(conditions, "rm_uid = ?")
params = append(params, querys.RmUID)
}
if querys.StartTime != "" {
conditions = append(conditions, "timestamp >= ?")
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
params = append(params, beginDate.Unix())
}
if querys.EndTime != "" {
conditions = append(conditions, "timestamp <= ?")
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
params = append(params, endDate.Unix())
}
if querys.EventType != "" {
eventTypes := strings.Split(querys.EventType, ",")
placeholder := repo.KeyPlaceholderByQuery(len(eventTypes))
conditions = append(conditions, fmt.Sprintf("event_type in (%s)", placeholder))
for _, eventType := range eventTypes {
params = append(params, eventType)
}
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
result := map[string]any{
"total": 0,
"rows": []model.CDREvent{},
}
// 查询数量 长度为0直接返回
totalSql := "select count(1) as 'total' from ue_event"
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
if err != nil {
logger.Errorf("total err => %v", err)
return result
}
total := parse.Number(totalRows[0]["total"])
if total == 0 {
return result
} else {
result["total"] = total
}
// 分页
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
pageSql := " limit ?,? "
params = append(params, pageNum*pageSize)
params = append(params, pageSize)
// 排序
orderSql := ""
if querys.SortField != "" {
sortSql := querys.SortField
if querys.SortOrder != "" {
if querys.SortOrder == "desc" {
sortSql += " desc "
} else {
sortSql += " asc "
}
}
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
}
// 查询数据
querySql := r.selectSql + whereSql + orderSql + pageSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
logger.Errorf("query err => %v", err)
}
// 转换实体
result["rows"] = r.convertResultRows(results)
return result
}
// SelectByIds 通过ID查询
func (r *UEEventImpl) SelectByIds(ueIds []string) []model.UEEvent {
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
querySql := r.selectSql + " where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(ueIds)
results, err := datasource.RawDB("", querySql, parameters)
if err != nil {
logger.Errorf("query err => %v", err)
return []model.UEEvent{}
}
// 转换实体
return r.convertResultRows(results)
}
// DeleteByIds 批量删除信息
func (r *UEEventImpl) DeleteByIds(ueIds []string) int64 {
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
sql := "delete from ue_event where id in (" + placeholder + ")"
parameters := repo.ConvertIdsSlice(ueIds)
results, err := datasource.ExecDB("", sql, parameters)
if err != nil {
logger.Errorf("delete err => %v", err)
return 0
}
return results
}

View File

@@ -0,0 +1,12 @@
package service
import "nms_nbi/src/modules/network_data/model"
// CDR会话事件 服务层接口
type ICDREvent interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.CDREventQuery) map[string]any
// DeleteByIds 批量删除信息
DeleteByIds(cdrIds []string) (int64, error)
}

View File

@@ -0,0 +1,40 @@
package service
import (
"fmt"
"nms_nbi/src/modules/network_data/model"
"nms_nbi/src/modules/network_data/repository"
)
// 实例化数据层 CDREventImpl 结构体
var NewCDREventImpl = &CDREventImpl{
cdrEventRepository: repository.NewCDREventImpl,
}
// CDREventImpl CDR会话事件 服务层处理
type CDREventImpl struct {
// CDR会话事件数据信息
cdrEventRepository repository.ICDREvent
}
// SelectPage 根据条件分页查询
func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
return r.cdrEventRepository.SelectPage(querys)
}
// DeleteByIds 批量删除信息
func (r *CDREventImpl) DeleteByIds(cdrIds []string) (int64, error) {
// 检查是否存在
ids := r.cdrEventRepository.SelectByIds(cdrIds)
if len(ids) <= 0 {
return 0, fmt.Errorf("not data")
}
if len(ids) == len(cdrIds) {
rows := r.cdrEventRepository.DeleteByIds(cdrIds)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}

View File

@@ -0,0 +1,15 @@
package service
import "nms_nbi/src/modules/network_data/model"
// 性能统计 服务层接口
type IPerfKPI interface {
// SelectGoldKPI 通过网元指标数据信息
SelectGoldKPI(query model.GoldKPIQuery) []map[string]any
// SelectGoldKPITitle 网元对应的指标名称
SelectGoldKPITitle(neType string) []model.GoldKPITitle
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
SelectUPFTotalFlow(neType, rmUID string, day int) map[string]any
}

View File

@@ -0,0 +1,76 @@
package service
import (
"encoding/json"
"fmt"
"time"
"nms_nbi/src/framework/constants/cachekey"
"nms_nbi/src/framework/redis"
"nms_nbi/src/modules/network_data/model"
"nms_nbi/src/modules/network_data/repository"
)
// 实例化数据层 PerfKPIImpl 结构体
var NewPerfKPIImpl = &PerfKPIImpl{
perfKPIRepository: repository.NewPerfKPIImpl,
}
// PerfKPIImpl 性能统计 服务层处理
type PerfKPIImpl struct {
// 性能统计数据信息
perfKPIRepository repository.IPerfKPI
}
// SelectGoldKPI 通过网元指标数据信息
func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery) []map[string]any {
// 获取数据指标id
var kpiIds []string
kpiTitles := r.perfKPIRepository.SelectGoldKPITitle(query.NeType)
for _, kpiId := range kpiTitles {
kpiIds = append(kpiIds, kpiId.KPIID)
}
data := r.perfKPIRepository.SelectGoldKPI(query, kpiIds)
if data == nil {
return []map[string]any{}
}
return data
}
// SelectGoldKPITitle 网元对应的指标名称
func (r *PerfKPIImpl) SelectGoldKPITitle(neType string) []model.GoldKPITitle {
return r.perfKPIRepository.SelectGoldKPITitle(neType)
}
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
func (r *PerfKPIImpl) SelectUPFTotalFlow(neType, rmUID string, day int) map[string]any {
// 获取当前日期
now := time.Now()
endDate := now.Format("2006-01-02")
// 将当前日期前几天数
afterDays := now.AddDate(0, 0, -day)
startDate := afterDays.Format("2006-01-02")
var info map[string]any
// 读取缓存数据 小于2分钟重新缓存
key := fmt.Sprintf("%sUPF:totalFlow:%s_%d", cachekey.NE_DATA_KEY, rmUID, day)
infoStr, _ := redis.Get("", key)
if infoStr != "" {
json.Unmarshal([]byte(infoStr), &info)
expireSecond, _ := redis.GetExpire("", key)
expireMinute := (time.Duration(int64(expireSecond)) * time.Second)
if expireMinute > 2*time.Minute {
return info
}
}
info = r.perfKPIRepository.SelectUPFTotalFlow(neType, rmUID, startDate, endDate)
// 保存到缓存
infoJSON, _ := json.Marshal(info)
redis.SetByExpire("", key, string(infoJSON), time.Duration(10)*time.Minute)
return info
}

View File

@@ -0,0 +1,12 @@
package service
import "nms_nbi/src/modules/network_data/model"
// UE会话事件 服务层接口
type IUEEvent interface {
// SelectPage 根据条件分页查询
SelectPage(querys model.UEEventQuery) map[string]any
// DeleteByIds 批量删除信息
DeleteByIds(ueIds []string) (int64, error)
}

View File

@@ -0,0 +1,40 @@
package service
import (
"fmt"
"nms_nbi/src/modules/network_data/model"
"nms_nbi/src/modules/network_data/repository"
)
// 实例化数据层 UEEventImpl 结构体
var NewUEEventImpl = &UEEventImpl{
ueEventRepository: repository.NewUEEventImpl,
}
// UEEventImpl UE会话事件 服务层处理
type UEEventImpl struct {
// UE会话事件数据信息
ueEventRepository repository.IUEEvent
}
// SelectPage 根据条件分页查询
func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
return r.ueEventRepository.SelectPage(querys)
}
// DeleteByIds 批量删除信息
func (r *UEEventImpl) DeleteByIds(ueIds []string) (int64, error) {
// 检查是否存在
ids := r.ueEventRepository.SelectByIds(ueIds)
if len(ids) <= 0 {
return 0, fmt.Errorf("no data")
}
if len(ids) == len(ueIds) {
rows := r.ueEventRepository.DeleteByIds(ueIds)
return rows, nil
}
// 删除信息失败!
return 0, fmt.Errorf("delete fail")
}