feat: 添加KPI忙时0609统计接口及相关服务逻辑

This commit is contained in:
TsMask
2025-09-01 18:14:17 +08:00
parent d0375de101
commit bd4a52316d
4 changed files with 138 additions and 5 deletions

View File

@@ -17,16 +17,18 @@ import (
// 实例化控制层 IMSController 结构体
var NewIMS = &IMSController{
neInfoService: neService.NewNeInfo,
cdrEventService: neDataService.NewCDREvent,
neInfoService: neService.NewNeInfo,
cdrEventService: neDataService.NewCDREvent,
kpiReportService: neDataService.NewKpiReport,
}
// 网元IMS
//
// PATH /ims
type IMSController struct {
neInfoService *neService.NeInfo // 网元信息服务
cdrEventService *neDataService.CDREvent // CDR会话事件服务
neInfoService *neService.NeInfo // 网元信息服务
cdrEventService *neDataService.CDREvent // CDR会话事件服务
kpiReportService *neDataService.KpiReport // 统计信息服务
}
// CDR会话列表
@@ -236,3 +238,44 @@ func (s *IMSController) UeSessionList(c *gin.Context) {
c.JSON(200, resp.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))
}

View File

@@ -184,6 +184,10 @@ func Setup(router *gin.Engine) {
middleware.AuthorizeUser(nil),
controller.NewIMS.UeSessionList,
)
imsGroup.GET("/kpi/busy-hour",
// middleware.AuthorizeUser(nil),
controller.NewIMS.KPIBusyHour,
)
}
// 网元SMSC

View File

@@ -115,7 +115,24 @@ func (r KpiReport) SelectUPF(rmUID string, beginTime, endTime int64) []model.Kpi
tx = tx.Where("created_at <= ?", endTime)
// 查询数据
rows := []model.KpiReport{}
if err := tx.Select("kpi_values").Find(&rows).Error; err != nil {
if err := tx.Select("kpi_values", "created_at").Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}
return rows
}
// SelectIMS 查询IMS数据
func (r KpiReport) SelectIMS(rmUID string, beginTime, endTime int64) []model.KpiReport {
tx := db.DB("").Model(&model.KpiReport{})
// 表名
tx = tx.Table("kpi_report_ims")
tx = tx.Where("rm_uid = ?", rmUID)
tx = tx.Where("created_at >= ?", beginTime)
tx = tx.Where("created_at <= ?", endTime)
// 查询数据
rows := []model.KpiReport{}
if err := tx.Select("kpi_values", "created_at").Find(&rows).Error; err != nil {
logger.Errorf("query find err => %v", err.Error())
return rows
}

View File

@@ -280,3 +280,72 @@ func (r KpiReport) UPFTodayFlowLoad(day int) {
}
}
}
// IMSBusyHour IMS忙时流量统计
// SCSCF.06呼叫尝试次数 SCSCF.09呼叫成功次数
func (r KpiReport) 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)
}
// 转换为毫秒级时间戳
rows := r.kpiReportRepository.SelectIMS(rmUID, beginTime.UnixMilli(), endTime.UnixMilli())
// 创建一个map来存储按时间段合并后的数据
timeGroup := make(map[int64]map[string]int64)
// 遍历每个数据项
for _, row := range rows {
// 将毫秒时间戳转换为小时级时间戳(保留到小时的起始毫秒)
timeHour := row.CreatedAt / 3600000 * 3600000 // 1小时 = 3600000毫秒
// 解析 JSON 字符串为 map
var kpiValues []map[string]any
err := json.Unmarshal([]byte(row.KpiValues), &kpiValues)
if err != nil {
continue
}
var callAttempts, callCompletions int64
for _, v := range kpiValues {
if k, ok := v["kpiId"]; ok {
if k == "SCSCF.06" {
callAttempts = parse.Number(v["value"])
}
if k == "SCSCF.09" {
callCompletions = parse.Number(v["value"])
}
}
}
// 合并到对应的小时段
if _, exists := timeGroup[timeHour]; !exists {
timeGroup[timeHour] = map[string]int64{
"callAttempts": 0,
"callCompletions": 0,
}
}
timeGroup[timeHour]["callAttempts"] += callAttempts
timeGroup[timeHour]["callCompletions"] += callCompletions
}
// 时间组合输出
data := make([]map[string]any, 0, len(timeGroup))
for hour, sums := range timeGroup {
data = append(data, map[string]any{
"timeGroup": fmt.Sprintf("%d", hour),
"callAttempts": sums["callAttempts"],
"callCompletions": sums["callCompletions"],
})
}
return data
}