diff --git a/src/modules/network_data/controller/ims.go b/src/modules/network_data/controller/ims.go index b415c46c..f5a2a8ae 100644 --- a/src/modules/network_data/controller/ims.go +++ b/src/modules/network_data/controller/ims.go @@ -9,6 +9,8 @@ import ( "be.ems/src/framework/i18n" "be.ems/src/framework/logger" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" "be.ems/src/framework/utils/ctx" "be.ems/src/framework/utils/date" "be.ems/src/framework/utils/file" @@ -25,16 +27,18 @@ import ( // 实例化控制层 IMSController 结构体 var NewIMS = &IMSController{ - neInfoService: neService.NewNeInfo, - cdrEventService: neDataService.NewCDREventIMS, + neInfoService: neService.NewNeInfo, + cdrEventService: neDataService.NewCDREventIMS, + kpiReportService: neDataService.NewPerfKPI, } // 网元IMS // // PATH /ims type IMSController struct { - neInfoService *neService.NeInfo // 网元信息服务 - cdrEventService *neDataService.CDREventIMS // CDR会话事件服务 + neInfoService *neService.NeInfo // 网元信息服务 + cdrEventService *neDataService.CDREventIMS // CDR会话事件服务 + kpiReportService *neDataService.PerfKPI // 统计信息服务 } // CDR会话列表 @@ -374,3 +378,44 @@ func (s *IMSController) UeSessionList(c *gin.Context) { c.JSON(200, result.OkData(data)) } + +// KPI 忙时统计 +// +// GET /kpi/busy-hour +// +// @Tags network_data/ims +// @Accept json +// @Produce json +// @Param neId query string true "NE ID" default(001) +// @Param timestamp query int64 false "timestamp" +// @Success 200 {object} object "Response Results" +// @Security TokenAuth +// @Summary Busy hour statistics +// @Description Busy hour statistics +// @Router /neData/ims/kpi/busy-hour [get] +func (s IMSController) KPIBusyHour(c *gin.Context) { + language := reqctx.AcceptLanguage(c) + var query struct { + NeID string `form:"neId" binding:"required"` + Timestamp int64 `form:"timestamp" binding:"required"` // 时间戳毫秒 年月日返回每小时的总和 年月日时返回该小时的总和 + } + if err := c.ShouldBindQuery(&query); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs)) + return + } + if query.Timestamp < 1e12 || query.Timestamp > 1e13 { + c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "timestamp format is ms")) + return + } + + // 查询网元获取IP + neInfo := s.neInfoService.FindByNeTypeAndNeID("IMS", query.NeID) + if neInfo.NeId != query.NeID || neInfo.IP == "" { + c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) + return + } + + data := s.kpiReportService.IMSBusyHour(neInfo.RmUID, query.Timestamp) + c.JSON(200, resp.OkData(data)) +} diff --git a/src/modules/network_data/controller/smf.go b/src/modules/network_data/controller/smf.go index d6c91531..78de5f75 100644 --- a/src/modules/network_data/controller/smf.go +++ b/src/modules/network_data/controller/smf.go @@ -412,7 +412,7 @@ func (s *SMFController) SubUserNum(c *gin.Context) { // @Security TokenAuth // @Summary Online session user list information // @Description Online session user list information -// @Router /neData/smf/session/list [get] +// @Router /neData/smf/sub/list [get] func (s *SMFController) SubUserList(c *gin.Context) { language := ctx.AcceptLanguage(c) var query struct { diff --git a/src/modules/network_data/network_data.go b/src/modules/network_data/network_data.go index fe59b888..2bc328c8 100644 --- a/src/modules/network_data/network_data.go +++ b/src/modules/network_data/network_data.go @@ -105,6 +105,10 @@ func Setup(router *gin.Engine) { middleware.PreAuthorize(nil), controller.NewIMS.UeSessionList, ) + imsGroup.GET("/kpi/busy-hour", + middleware.PreAuthorize(nil), + controller.NewIMS.KPIBusyHour, + ) } // 网元SMSC diff --git a/src/modules/network_data/repository/all_perf_kpi.go b/src/modules/network_data/repository/all_perf_kpi.go index 743bb2aa..aacef538 100644 --- a/src/modules/network_data/repository/all_perf_kpi.go +++ b/src/modules/network_data/repository/all_perf_kpi.go @@ -301,3 +301,39 @@ func (r *PerfKPI) SelectUPFTotalFlow(neType, rmUID, startDate, endDate string) m } return results[0] } + +// SelectIMSBusyHour 查询IMS忙时流量 SCSCF.06呼叫尝试次数 SCSCF.09呼叫成功次数 +func (r *PerfKPI) SelectIMSBusyHour(rmUID string, startDate, endDate int64) []map[string]any { + // 查询条件拼接 + var conditions []string + var params []any + if rmUID != "" { + conditions = append(conditions, "kims.rm_uid = ?") + params = append(params, rmUID) + } + if startDate > 0 { + conditions = append(conditions, "kims.created_at >= ?") + params = append(params, startDate) + } + if endDate > 0 { + conditions = append(conditions, "kims.created_at <= ?") + params = append(params, endDate) + } + // 构建查询条件语句 + whereSql := "" + if len(conditions) > 0 { + whereSql += " where " + strings.Join(conditions, " and ") + } + + // 查询数据 3600秒=1小时 + querySql := `SELECT + CONCAT(FLOOR(kims.created_at / (3600 * 1000)) * (3600 * 1000)) AS timeGroup, + sum( CASE WHEN JSON_EXTRACT(kims.kpi_values, '$[5].kpi_id') = 'SCSCF.06' THEN JSON_EXTRACT(kims.kpi_values, '$[5].value') ELSE 0 END ) AS 'callAttempts', + sum( CASE WHEN JSON_EXTRACT(kims.kpi_values, '$[8].kpi_id') = ' ' THEN JSON_EXTRACT(kims.kpi_values, '$[8].value') ELSE 0 END ) AS 'callCompletions' + FROM kpi_report_ims kims` + results, err := datasource.RawDB("", querySql+whereSql+" GROUP by timeGroup ", params) + if err != nil { + logger.Errorf("query err => %v", err) + } + return results +} diff --git a/src/modules/network_data/service/all_perf_kpi.go b/src/modules/network_data/service/all_perf_kpi.go index a361d535..d9a76a8d 100644 --- a/src/modules/network_data/service/all_perf_kpi.go +++ b/src/modules/network_data/service/all_perf_kpi.go @@ -265,3 +265,24 @@ func (r PerfKPI) UPFTodayFlowLoad(day int) { } } } + +// IMSBusyHour IMS忙时流量统计 +func (r PerfKPI) IMSBusyHour(rmUID string, timestamp int64) []map[string]any { + t := time.UnixMilli(timestamp) + beginTime := t + endTime := t + // 检查时分秒是否都为零 + if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 { + // 获取当天起始时间(00:00:00) + beginTime = t.Truncate(time.Hour) + // 计算当天结束时间(23:59:59) + endTime = beginTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second) + } else { + // 起始时间:当前小时的 00 分 00 秒 + beginTime = t.Truncate(time.Hour) + // 结束时间:当前小时的 59 分 59 秒 999 毫秒 + endTime = beginTime.Add(time.Hour - time.Millisecond) + } + // 转换为毫秒级时间戳 + return r.perfKPIRepository.SelectIMSBusyHour(rmUID, beginTime.UnixMilli(), endTime.UnixMilli()) +}