diff --git a/features/cdr/cdrevent.go b/features/cdr/cdrevent.go index 63642072..f04f74d4 100644 --- a/features/cdr/cdrevent.go +++ b/features/cdr/cdrevent.go @@ -1,15 +1,17 @@ package cdr import ( + "encoding/json" "fmt" "net/http" "strings" + "time" "be.ems/lib/config" "be.ems/lib/core/ctx" - "be.ems/lib/dborm" "be.ems/lib/log" "be.ems/lib/services" + "be.ems/src/framework/database/db" neService "be.ems/src/modules/network_element/service" wsService "be.ems/src/modules/ws/service" ) @@ -22,55 +24,78 @@ var ( CustomUriCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile" ) -// CDREvent CDR数据表格结构体 -type CDREvent struct { - NeType string `json:"neType" xorm:"ne_type"` - NeName string `json:"neName" xorm:"ne_name"` - RmUID string `json:"rmUID" xorm:"rm_uid"` - Timestamp int `json:"timestamp" xorm:"timestamp"` - CDR map[string]any `json:"CDR" xorm:"cdr_json"` -} - // PostCDREventFrom 接收CDR数据请求 func PostCDREventFrom(w http.ResponseWriter, r *http.Request) { log.Info("PostCDREventFrom processing... ") neType := ctx.GetParam(r, "elementTypeValue") - var cdrEvent CDREvent - if err := ctx.ShouldBindJSON(r, &cdrEvent); err != nil { + var body struct { + NeType string `json:"neType" ` + NeName string `json:"neName" ` + RmUID string `json:"rmUID" ` + Timestamp int `json:"timestamp" ` + CDR map[string]any `json:"CDR" ` + } + if err := ctx.ShouldBindJSON(r, &body); err != nil { services.ResponseInternalServerError500ProcessError(w, err) return } - neTypeLower := strings.ToLower(cdrEvent.NeType) + neTypeLower := strings.ToLower(body.NeType) if neType == "" || neType != neTypeLower { services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element types")) return } + // 是否存在网元 + neInfo := neService.NewNeInfo.FindByRmuid(body.RmUID) + if neInfo.NeType != body.NeType || neInfo.RmUID != body.RmUID { + services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("network element does not exist")) + return + } + + cdrByte, err := json.Marshal(body.CDR) + if err != nil { + services.ResponseInternalServerError500ProcessError(w, err) + return + } + + // 执行插入表 + type CDREvent struct { + ID int64 `json:"-" 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"` // 接收到的timestamp秒级存储毫秒时间戳 + CdrJson string `json:"cdrJSON" gorm:"column:cdr_json"` // data JSON String + CreatedAt int64 `json:"-" gorm:"column:created_at"` // 记录创建存储毫秒 + } + data := CDREvent{ + NeType: body.NeType, + NeName: body.NeName, + RmUid: body.RmUID, + Timestamp: int64(body.Timestamp) * 1000, + CdrJson: string(cdrByte), + CreatedAt: time.Now().UnixMilli(), + } tableName := fmt.Sprintf("cdr_event_%s", neTypeLower) - affected, err := dborm.XormInsertTableOne(tableName, cdrEvent) - if err != nil && affected <= 0 { + if err := db.DB("").Table(tableName).Create(&data).Error; err != nil { log.Error("Failed to insert "+tableName, err) services.ResponseInternalServerError500ProcessError(w, err) return } - // 发送到匹配的网元 - neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(cdrEvent.RmUID) - if neInfo.RmUID == cdrEvent.RmUID { - // 推送到ws订阅组 - switch neInfo.NeType { - case "IMS": - if v, ok := cdrEvent.CDR["recordType"]; ok && (v == "MOC" || v == "MTSM") { - wsService.NewWSSend.ByGroupID(wsService.GROUP_IMS_CDR+neInfo.NeId, cdrEvent) - } - case "SMF": - wsService.NewWSSend.ByGroupID(wsService.GROUP_SMF_CDR+neInfo.NeId, cdrEvent) - case "SMSC": - wsService.NewWSSend.ByGroupID(wsService.GROUP_SMSC_CDR+neInfo.NeId, cdrEvent) - case "SGWC": - wsService.NewWSSend.ByGroupID(wsService.GROUP_SGWC_CDR+neInfo.NeId, cdrEvent) + // 推送到ws订阅组 + switch neInfo.NeType { + case "IMS": + if v, ok := body.CDR["recordType"]; ok && (v == "MOC" || v == "MTSM") { + wsService.NewWSSend.ByGroupID(wsService.GROUP_IMS_CDR+neInfo.NeId, data) } + case "SMF": + wsService.NewWSSend.ByGroupID(wsService.GROUP_SMF_CDR+neInfo.NeId, data) + case "SMSC": + wsService.NewWSSend.ByGroupID(wsService.GROUP_SMSC_CDR+neInfo.NeId, data) + case "SGWC": + wsService.NewWSSend.ByGroupID(wsService.GROUP_SGWC_CDR+neInfo.NeId, data) } services.ResponseStatusOK204NoContent(w) diff --git a/features/cm/ne.go b/features/cm/ne.go index a00dbe92..18b2ce30 100644 --- a/features/cm/ne.go +++ b/features/cm/ne.go @@ -15,7 +15,8 @@ import ( "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/services" - tokenConst "be.ems/src/framework/constants/token" + "be.ems/src/framework/constants" + "be.ems/src/framework/database/db" neService "be.ems/src/modules/network_element/service" "github.com/go-resty/resty/v2" @@ -293,7 +294,7 @@ func PutNeInfo(w http.ResponseWriter, r *http.Request) { body, _ = json.Marshal(omcNeConfig) response, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). SetBody(body). @@ -748,20 +749,20 @@ func DownloadNeBackupFile(w http.ResponseWriter, r *http.Request) { } sql := fmt.Sprintf("select * from ne_backup where ne_type='%s' and file_name='%s'", neTypeUpper, fileName) - neBackup, err := dborm.XormGetDataBySQL(sql) + neBackup, err := db.RawDB("", sql, nil) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return - } else if len(*neBackup) == 0 { + } else if len(neBackup) == 0 { err := global.ErrCMNotFoundTargetBackupFile log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) return } - path := (*neBackup)[0]["path"] - md5Sum := (*neBackup)[0]["md5_sum"] + path := fmt.Sprint(neBackup[0]["path"]) + md5Sum := fmt.Sprint(neBackup[0]["md5_sum"]) services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, md5Sum) } @@ -793,12 +794,12 @@ func DeleteNeBackupFile(w http.ResponseWriter, r *http.Request) { } sql := fmt.Sprintf("select * from ne_backup where ne_type='%s' and file_name='%s'", neTypeUpper, fileName) - neBackup, err := dborm.XormGetDataBySQL(sql) + neBackup, err := db.RawDB("", sql, nil) if err != nil { log.Error("Faile to XormGetDataBySQL:", err) services.ResponseInternalServerError500ProcessError(w, err) return - } else if len(*neBackup) == 0 { + } else if len(neBackup) == 0 { err := global.ErrCMNotFoundTargetBackupFile log.Error(err) services.ResponseInternalServerError500ProcessError(w, err) @@ -813,7 +814,7 @@ func DeleteNeBackupFile(w http.ResponseWriter, r *http.Request) { return } - path := (*neBackup)[0]["path"] + path := neBackup[0]["path"] filePath := fmt.Sprintf("%s/%s", path, fileName) err = os.Remove(filePath) if err != nil { diff --git a/features/cm/param.go b/features/cm/param.go index afaaea50..1b1266d0 100644 --- a/features/cm/param.go +++ b/features/cm/param.go @@ -39,7 +39,7 @@ func GetParamConfigFromNF(w http.ResponseWriter, r *http.Request) { return } - neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId) + neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId) var response services.DataResponse if neInfo.NeId == neId && neInfo.NeId != "" { @@ -76,7 +76,7 @@ func PostParamConfigToNF(w http.ResponseWriter, r *http.Request) { return } - neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId) + neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId) if neInfo.NeId != neId || neInfo.NeId == "" { log.Error("neId is empty") @@ -128,7 +128,7 @@ func PutParamConfigToNF(w http.ResponseWriter, r *http.Request) { } neId := ctx.GetQuery(r, "ne_id") - neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId) + neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId) if neInfo.NeId != neId || neInfo.NeId == "" { log.Error("neId is empty") @@ -181,7 +181,7 @@ func DeleteParamConfigToNF(w http.ResponseWriter, r *http.Request) { } neId := ctx.GetQuery(r, "ne_id") - neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId) + neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId) if neInfo.NeId != neId || neInfo.NeId == "" { log.Error("neId is empty") diff --git a/features/dbrest/dbrest.go b/features/dbrest/dbrest.go index 4524d516..d11f981a 100644 --- a/features/dbrest/dbrest.go +++ b/features/dbrest/dbrest.go @@ -7,7 +7,6 @@ import ( "net/http" "regexp" "strings" - "time" "be.ems/lib/config" "be.ems/lib/core/ctx" @@ -15,9 +14,9 @@ import ( "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/services" + "be.ems/src/framework/database/db" "github.com/gorilla/mux" - "xorm.io/xorm" ) type XormResponse struct { @@ -62,56 +61,6 @@ var ( ) -var XEngine *xorm.Engine - -type DatabaseClient struct { - dbType string - dbUrl string - dbConnMaxLifetime time.Duration - dbMaxIdleConns int - dbMaxOpenConns int - IsShowSQL bool - - XEngine *xorm.Engine -} - -var DbClient DatabaseClient - -func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error { - // DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local", - // dbUser, dbPassword, dbHost, dbPort, dbName) - DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", - dbUser, dbPassword, dbHost, dbPort, dbName, dbParam) - DbClient.dbType = dbType - DbClient.dbConnMaxLifetime = 0 - DbClient.dbMaxIdleConns = 0 - DbClient.dbMaxOpenConns = 0 - - if log.GetLevel() == log.LOG_TRACE { - DbClient.IsShowSQL = true - } - log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl) - - var err error - DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl) - if err != nil { - log.Error("Failed to connet database:", err) - return err - } - DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime) - DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns) - DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns) - DbClient.XEngine.DatabaseTZ = time.Local // 必须 - DbClient.XEngine.TZLocation = time.Local // 必须 - if DbClient.IsShowSQL { - //DbClient.XEngine.SetLogger(&log.Elogger) - DbClient.XEngine.ShowSQL(true) - } - XEngine = DbClient.XEngine - - return nil -} - func GetUriSQLArray(r *http.Request) []string { var sa []string vars := r.URL.Query() @@ -181,17 +130,13 @@ func GetTableName(sql string) string { func IsQuerySQL(s string) bool { ts := strings.Trim(strings.ToLower(s), " ") - if strings.Index(ts, "select") != 0 { - return false - } - return true + return strings.Index(ts, "select") == 0 } // xorm Get data from database func ExtDatabaseExecSQL(w http.ResponseWriter, r *http.Request) { log.Debug("ExtDatabaseExecSQL processing... ") - var sql []string // var err error // _, err = services.CheckExtValidRequest(w, r) @@ -202,7 +147,7 @@ func ExtDatabaseExecSQL(w http.ResponseWriter, r *http.Request) { //vars := mux.Vars(r) //tblName := vars["objectTypeValue"] - sql = GetUriSQLArray(r) + var sql = GetUriSQLArray(r) // select as must, todo ... ls := services.ExtGetUriPageLimitString(r) @@ -229,7 +174,7 @@ func ExtDatabaseExecSQL(w http.ResponseWriter, r *http.Request) { querySQL = querySQL + " " + ls } log.Debug("querySQL:", querySQL) - rows, err := DbClient.XEngine.Exec(querySQL) + rows, err := db.RawDB("", querySQL, nil) if err != nil { log.Error("SQL failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) @@ -313,7 +258,7 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) { querySQL = querySQL + " " + ls } log.Debug("querySQL:", querySQL) - rows, err := DbClient.XEngine.QueryInterface(querySQL) + rows, err := db.RawDB("", querySQL, nil) if err != nil { log.Error("SQL failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) @@ -374,20 +319,18 @@ func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) { tn, sql := dborm.ConstructInsertSQL(tbname, insertData) log.Tracef("tn: %s sql :%s", tn, sql) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() + var affected int64 for _, s := range sql { - res, err := xSession.Exec(s) + n, err := db.ExecDB("", s, nil) if err != nil { log.Error("Insert failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - n, _ := res.RowsAffected() affected = affected + n } - xSession.Commit() + // affected, err := InsertDataWithJson(insertData) mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} @@ -440,20 +383,18 @@ func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) { tn, sql := dborm.ConstructUpdateSQL(tbname, updateData, wc) log.Tracef("tn: %s sql :%s", tn, sql) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() + var affected int64 for _, s := range sql { - res, err := xSession.Exec(s) + n, err := db.ExecDB("", s, nil) if err != nil { log.Error("Update failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - n, _ := res.RowsAffected() affected = affected + n } - xSession.Commit() + mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} mapRow[tn] = row @@ -494,16 +435,14 @@ func ExtDatabaseDeleteData(w http.ResponseWriter, r *http.Request) { log.Debug("Table name:", tbname, "wc:", wc) sql := dborm.ConstructDeleteSQL(tbname, wc) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() - res, err := xSession.Exec(sql) + + affected, err := db.ExecDB("", sql, nil) if err != nil { log.Error("Update failed, err:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - affected, _ := res.RowsAffected() - xSession.Commit() + mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} mapRow["data"] = row @@ -515,7 +454,6 @@ func DatabaseGetData(w http.ResponseWriter, r *http.Request) { log.Debug("DatabaseGetData processing... ") var sql []string - var err error // _, err = services.CheckFrontValidRequest(w, r) // if err != nil { @@ -546,7 +484,6 @@ func DatabaseGetData(w http.ResponseWriter, r *http.Request) { for i, s := range sql { log.Tracef("SQL[%d]: %s", i, sql[i]) - rows := make([]map[string]interface{}, 0) mapRows := make(map[string]interface{}) if s != "" { @@ -561,7 +498,7 @@ func DatabaseGetData(w http.ResponseWriter, r *http.Request) { querySQL = querySQL + " " + ls } log.Debug("querySQL:", querySQL) - rows, err = DbClient.XEngine.QueryInterface(querySQL) + rows, err := db.RawDB("", querySQL, nil) if err != nil { log.Error("QueryInterface failed:", err) services.ResponseInternalServerError500ProcessError(w, err) @@ -611,20 +548,18 @@ func DatabaseInsertData(w http.ResponseWriter, r *http.Request) { tn, sql := dborm.ConstructInsertSQL(tableName, insertData) log.Tracef("tn: %s sql :%s", tn, sql) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() + var affected int64 for _, s := range sql { - res, err := xSession.Exec(s) + n, err := db.ExecDB("", s, nil) if err != nil { log.Error("Insert failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - n, _ := res.RowsAffected() affected = affected + n } - xSession.Commit() + // affected, err := InsertDataWithJson(insertData) mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} @@ -653,20 +588,18 @@ func DatabaseUpdateData(w http.ResponseWriter, r *http.Request) { tn, sql := dborm.ConstructUpdateSQL(tblName, updateData, wc) log.Tracef("tn: %s sql :%s", tn, sql) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() + var affected int64 for _, s := range sql { - res, err := xSession.Exec(s) + n, err := db.ExecDB("", s, nil) if err != nil { log.Error("Update failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - n, _ := res.RowsAffected() affected = affected + n } - xSession.Commit() + mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} mapRow[tn] = row @@ -683,16 +616,14 @@ func DatabaseDeleteData(w http.ResponseWriter, r *http.Request) { log.Debug("Table name:", tblName, "wc:", wc) sql := dborm.ConstructDeleteSQL(tblName, wc) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() - res, err := xSession.Exec(sql) + + affected, err := db.ExecDB("", sql, nil) if err != nil { log.Error("Update failed, err:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - affected, _ := res.RowsAffected() - xSession.Commit() + mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} mapRow["data"] = row @@ -701,15 +632,25 @@ func DatabaseDeleteData(w http.ResponseWriter, r *http.Request) { // 连接用户实例 func DbConnection(w http.ResponseWriter, r *http.Request) { - if dborm.DbClient.XEngine == nil { + // 获取底层 SQL 数据库连接 + sqlDB, err := db.DB("").DB() + if err != nil { services.ResponseErrorWithJson(w, 400, "无连接") + return } + // 测试数据库连接 + err = sqlDB.Ping() + if err != nil { + services.ResponseErrorWithJson(w, 400, "无连接") + return + } + // 查询实例 - result, err := dborm.DbClient.XEngine.QueryString("SHOW PROCESSLIST;") + result, err := db.RawDB("", "SHOW PROCESSLIST;", nil) if err != nil { services.ResponseErrorWithJson(w, 500, err.Error()) } - filterData := []map[string]string{} + filterData := []map[string]any{} for _, r := range result { if r["User"] != "system user" { filterData = append(filterData, r) @@ -724,15 +665,24 @@ func DbConnection(w http.ResponseWriter, r *http.Request) { // 关闭数据库连接 func DbStop(w http.ResponseWriter, r *http.Request) { - if dborm.DbClient.XEngine == nil { + // 获取底层 SQL 数据库连接 + sqlDB, err := db.DB("").DB() + if err != nil { services.ResponseErrorWithJson(w, 400, "无连接") + return + } + // 测试数据库连接 + err = sqlDB.Ping() + if err != nil { + services.ResponseErrorWithJson(w, 400, "无连接") + return } // json 請求參數獲取 var bodyArgs struct { ID string `json:"ID" validate:"required"` } - err := ctx.ShouldBindJSON(r, &bodyArgs) + err = ctx.ShouldBindJSON(r, &bodyArgs) if err != nil { log.Error("io.ReadAll is failed:", err) services.ResponseErrorWithJson(w, 400, err.Error()) @@ -740,7 +690,7 @@ func DbStop(w http.ResponseWriter, r *http.Request) { } // 关闭 - rse, err := dborm.DbClient.XEngine.Exec("KILL ?;", bodyArgs.ID) + rse, err := db.ExecDB("", "KILL ?;", []any{bodyArgs.ID}) if err != nil { services.ResponseErrorWithJson(w, 500, err.Error()) return @@ -752,12 +702,9 @@ func DbStop(w http.ResponseWriter, r *http.Request) { func TaskDatabaseGetData(w http.ResponseWriter, r *http.Request) { log.Debug("DatabaseGetData processing... ") - var sql []string - var err error - vars := mux.Vars(r) tblName := vars["objectTypeValue"] - sql = GetUriSQLArray(r) + var sql = GetUriSQLArray(r) // select as must, todo ... if sql == nil { @@ -778,12 +725,11 @@ func TaskDatabaseGetData(w http.ResponseWriter, r *http.Request) { for i, s := range sql { log.Tracef("SQL[%d]: %s", i, sql[i]) - rows := make([]map[string]interface{}, 0) mapRows := make(map[string]interface{}) if s != "" { // err = XEngine.SQL(s).Find(&rows) - if IsQuerySQL(s) == false { + if !IsQuerySQL(s) { services.ResponseNotAcceptable406QuerySQLError(w) return } @@ -793,7 +739,7 @@ func TaskDatabaseGetData(w http.ResponseWriter, r *http.Request) { querySQL = querySQL + " " + ls } log.Debug("querySQL:", querySQL) - rows, err = DbClient.XEngine.QueryInterface(querySQL) + rows, err := db.RawDB("", querySQL, nil) if err != nil { log.Error("SQL failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) @@ -830,20 +776,18 @@ func TaskDatabaseInsertData(w http.ResponseWriter, r *http.Request) { tn, sql := dborm.ConstructInsertSQL(tableName, insertData) log.Tracef("tn: %s sql :%s", tn, sql) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() + var affected int64 for _, s := range sql { - res, err := xSession.Exec(s) + n, err := db.ExecDB("", s, nil) if err != nil { log.Error("Insert failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - n, _ := res.RowsAffected() affected = affected + n } - xSession.Commit() + // affected, err := InsertDataWithJson(insertData) mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} @@ -872,20 +816,18 @@ func TaskDatabaseUpdateData(w http.ResponseWriter, r *http.Request) { tn, sql := dborm.ConstructUpdateSQL(tblName, updateData, wc) log.Tracef("tn: %s sql :%s", tn, sql) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() + var affected int64 for _, s := range sql { - res, err := xSession.Exec(s) + n, err := db.ExecDB("", s, nil) if err != nil { log.Error("Update failed:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - n, _ := res.RowsAffected() affected = affected + n } - xSession.Commit() + mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} mapRow[tn] = row @@ -902,16 +844,14 @@ func TaskDatabaseDeleteData(w http.ResponseWriter, r *http.Request) { log.Debug("Table name:", tblName, "wc:", wc) sql := dborm.ConstructDeleteSQL(tblName, wc) - xSession := DbClient.XEngine.NewSession() - defer xSession.Close() - res, err := xSession.Exec(sql) + + affected, err := db.ExecDB("", sql, nil) if err != nil { log.Error("Update failed, err:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - affected, _ := res.RowsAffected() - xSession.Commit() + mapRow := make(map[string]interface{}) row := map[string]interface{}{"affectedRows": affected} mapRow["data"] = row diff --git a/features/event/event.go b/features/event/event.go index 0376bd8e..5e3853f1 100644 --- a/features/event/event.go +++ b/features/event/event.go @@ -1,6 +1,7 @@ package event import ( + "encoding/json" "fmt" "net/http" "strings" @@ -8,12 +9,15 @@ import ( "be.ems/lib/config" "be.ems/lib/core/ctx" - "be.ems/lib/dborm" "be.ems/lib/log" "be.ems/lib/services" + + "be.ems/src/framework/database/db" + "be.ems/src/framework/utils/date" "be.ems/src/framework/utils/parse" neService "be.ems/src/modules/network_element/service" wsService "be.ems/src/modules/ws/service" + "github.com/gin-gonic/gin" ) @@ -25,21 +29,11 @@ var ( CustomUriUEEvent = config.UriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent" ) -type UEEvent struct { - NeType string `json:"neType" xorm:"ne_type"` - NeName string `json:"neName" xorm:"ne_name"` - RmUID string `json:"rmUID" xorm:"rm_uid"` - Timestamp int64 `json:"timestamp" xorm:"timestamp"` - EventType string `json:"eventType" xorm:"event_type"` - EventJson map[string]any `json:"eventJSON" xorm:"event_json"` -} - // 旧AMF上报处理 func PostUEEventFromAMF(c *gin.Context) { log.Info("PostUEEventFromAMF processing... ") - - eventType, ok := c.Params.Get("eventType") - if !ok || eventType == "" { + eventType := c.Param("eventType") + if eventType == "" { log.Error("eventType is empty") services.ResponseNotFound404UriNotExist(c.Writer, c.Request) return @@ -51,21 +45,45 @@ func PostUEEventFromAMF(c *gin.Context) { return } - ueEvent := UEEvent{ - NeType: "AMF", - Timestamp: time.Now().Unix(), - EventType: eventType, + // 执行插入表 + 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"` // 接收到的timestamp秒级存储毫秒时间戳 + EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state + EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String + CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒 } + timestamp := time.Now().UnixMilli() + data := UEEvent{ + NeType: "AMF", + NeName: "", + RmUID: "", + Timestamp: timestamp, + EventType: eventType, + EventJSONStr: "", + CreatedAt: timestamp, + } + // 从eventJson中获取rmUID if v, ok := body["rmUID"]; ok { - ueEvent.RmUID = fmt.Sprint(v) + data.RmUID = fmt.Sprint(v) } else { - ueEvent.RmUID = "4400HXAMF001" + data.RmUID = "4400HXAMF001" } if v, ok := body["neName"]; ok { - ueEvent.NeName = fmt.Sprint(v) + data.NeName = fmt.Sprint(v) } else { - ueEvent.NeName = "AMF_001" + data.NeName = "AMF_001" + } + + // 是否存在网元 + neInfo := neService.NewNeInfo.FindByRmuid(data.RmUID) + if neInfo.NeType != "AMF" || neInfo.RmUID != data.RmUID { + services.ResponseInternalServerError500ProcessError(c.Writer, fmt.Errorf("network element does not exist")) + return } // 统一格式 @@ -92,7 +110,8 @@ func PostUEEventFromAMF(c *gin.Context) { eventJson["result"] = fmt.Sprint(v) } if v, ok := body["authTime"]; ok { - eventJson["timestamp"] = ueEvent.Timestamp + authTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS) + eventJson["timestamp"] = authTime.Unix() eventJson["time"] = fmt.Sprint(v) } case "detach": @@ -108,7 +127,8 @@ func PostUEEventFromAMF(c *gin.Context) { } } if v, ok := body["detachTime"]; ok { - eventJson["timestamp"] = ueEvent.Timestamp + detachTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS) + eventJson["timestamp"] = detachTime.Unix() eventJson["time"] = fmt.Sprint(v) } case "cm-state": @@ -123,27 +143,29 @@ func PostUEEventFromAMF(c *gin.Context) { eventJson["result"] = fmt.Sprint(v) } if v, ok := body["changeTime"]; ok { - eventJson["timestamp"] = ueEvent.Timestamp + changeTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS) + eventJson["timestamp"] = changeTime.Unix() eventJson["time"] = fmt.Sprint(v) } } - ueEvent.EventJson = eventJson - affected, err := dborm.XormInsertTableOne("ue_event_amf", ueEvent) - if err != nil && affected <= 0 { - log.Error("Failed to insert ue_event_amf:", err) + ueByte, err := json.Marshal(eventJson) + if err != nil { + services.ResponseInternalServerError500ProcessError(c.Writer, err) + return + } + data.EventJSONStr = string(ueByte) + + if err := db.DB("").Table("ue_event_amf").Create(&data).Error; err != nil { + log.Error("Failed to insert ue_event_amf", err) services.ResponseInternalServerError500ProcessError(c.Writer, err) return } - // 发送到匹配的网元 - neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(ueEvent.RmUID) - if neInfo.RmUID == ueEvent.RmUID { - // 推送到ws订阅组 - if ueEvent.NeType == "AMF" { - wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, ueEvent) - wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, ueEvent) - } + // 推送到ws订阅组 + if data.NeType == "AMF" { + wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, data) + wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, data) } services.ResponseStatusOK204NoContent(c.Writer) @@ -152,35 +174,74 @@ func PostUEEventFromAMF(c *gin.Context) { // UE上报处理 func PostUEEvent(w http.ResponseWriter, r *http.Request) { log.Info("PostUEEvent processing... ") - neType := ctx.GetParam(r, "elementTypeValue") - var ueEvent UEEvent - if err := ctx.ShouldBindJSON(r, &ueEvent); err != nil { + var body struct { + NeType string `json:"neType" ` + NeName string `json:"neName" ` + RmUID string `json:"rmUID" ` + Timestamp int64 `json:"timestamp" ` + EventType string `json:"eventType" ` + EventJson map[string]any `json:"eventJSON" ` + } + if err := ctx.ShouldBindJSON(r, &body); err != nil { services.ResponseInternalServerError500ProcessError(w, err) return } - ueEvent.NeType = strings.ToUpper(neType) - tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(neType)) - affected, err := dborm.XormInsertTableOne(tableName, ueEvent) - if err != nil && affected <= 0 { + neTypeLower := strings.ToLower(body.NeType) + if neType == "" || neType != neTypeLower { + services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element types")) + return + } + + // 是否存在网元 + neInfo := neService.NewNeInfo.FindByRmuid(body.RmUID) + if neInfo.NeType != body.NeType || neInfo.RmUID != body.RmUID { + services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("network element does not exist")) + return + } + + ueByte, err := json.Marshal(body.EventJson) + if err != nil { + services.ResponseInternalServerError500ProcessError(w, err) + return + } + + // 执行插入表 + type UEEvent struct { + ID string `json:"-" 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"` // 接收到的timestamp秒级存储毫秒时间戳 + EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state + EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String + CreatedAt int64 `json:"-" gorm:"column:created_at"` // 记录创建存储毫秒 + } + data := UEEvent{ + NeType: body.NeType, + NeName: body.NeName, + RmUID: body.RmUID, + Timestamp: int64(body.Timestamp) * 1000, + EventType: body.EventType, + EventJSONStr: string(ueByte), + CreatedAt: time.Now().UnixMilli(), + } + tableName := fmt.Sprintf("ue_event_%s", neTypeLower) + if err := db.DB("").Table(tableName).Create(&data).Error; err != nil { log.Error("Failed to insert "+tableName, err) services.ResponseInternalServerError500ProcessError(w, err) return } - // 发送到匹配的网元 - neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(ueEvent.RmUID) - if neInfo.RmUID == ueEvent.RmUID { - // 推送到ws订阅组 - if ueEvent.NeType == "MME" { - wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE, ueEvent) - wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE+"_"+neInfo.NeId, ueEvent) - } - if ueEvent.NeType == "AMF" { - wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, ueEvent) - wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, ueEvent) - } + // 推送到ws订阅组 + if body.NeType == "MME" { + wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE, data) + wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE+"_"+neInfo.NeId, data) + } + if body.NeType == "AMF" { + wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, data) + wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, data) } services.ResponseStatusOK204NoContent(w) diff --git a/features/fm/alarm.go b/features/fm/alarm.go index 7883ee1d..886745b1 100644 --- a/features/fm/alarm.go +++ b/features/fm/alarm.go @@ -4,22 +4,26 @@ import ( "database/sql" "encoding/json" "fmt" - "io" "net/http" "strconv" "strings" "time" "be.ems/lib/config" + "be.ems/lib/core/ctx" "be.ems/lib/dborm" "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/services" - "xorm.io/xorm" - "github.com/go-resty/resty/v2" - _ "github.com/go-sql-driver/mysql" - "github.com/gorilla/mux" + "be.ems/src/framework/resp" + "be.ems/src/framework/utils/date" + neDataModel "be.ems/src/modules/network_data/model" + neDataService "be.ems/src/modules/network_data/service" + neFetchlink "be.ems/src/modules/network_element/fetch_link" + neModel "be.ems/src/modules/network_element/model" + neService "be.ems/src/modules/network_element/service" + wsService "be.ems/src/modules/ws/service" ) const ( @@ -60,10 +64,6 @@ const ( AlarmSeqBeginNumber = 1 ) -type Response struct { - Data interface{} `json:"data"` -} - type Alarm struct { AlarmSeq int `json:"alarmSeq"` AlarmId string `json:"alarmId" xorm:"alarm_id"` @@ -94,18 +94,6 @@ type Alarm struct { ClearTime sql.NullTime `json:"clearTime"` } -type AlarmLog struct { - NeType string `json:"neType" xorm:"ne_type"` - NeId string `json:"neId" xorm:"ne_id"` - AlarmSeq int `json:"alarmSeq" xorm:"alarm_seq"` - AlarmId string `json:"alarmId" xorm:"alarm_id"` - AlarmCode int `json:"alarmCode" xorm:"alarm_code"` - AlarmStatus int `json:"alarmStatus" xorm:"alarm_status"` - EventTime string `json:"eventTime" xorm:"event_time"` - // ClearTime sql.NullTime `json:"clearTime" xorm:"clear_time"` - LogTime string `json:"logTime" xorm:"-"` -} - var ( // alarm management UriAlarms = config.DefaultUriPrefix + "/faultManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/alarms" @@ -115,90 +103,6 @@ var ( CustomUriAlarmsFmt = config.UriPrefix + "/faultManagement/v1/elementType/%s/objectType/alarms" ) -var client = resty.New() - -func init() { - /* - client. - SetTimeout(10 * time.Second). - SetRetryCount(1). - SetRetryWaitTime(1 * time.Second). - SetRetryMaxWaitTime(2 * time.Second). - SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) { - return 0, errors.New("quota exceeded") - }) - */ - client. - SetTimeout(time.Duration(500 * time.Millisecond)) - // SetRetryCount(1). - // SetRetryWaitTime(time.Duration(1 * time.Second)). - // SetRetryMaxWaitTime(time.Duration(2 * time.Second)) - //client.SetTimeout(2 * time.Second) -} - -var xEngine *xorm.Engine - -type DatabaseClient struct { - dbType string - dbUrl string - dbConnMaxLifetime time.Duration - dbMaxIdleConns int - dbMaxOpenConns int - IsShowSQL bool - - XEngine *xorm.Engine -} - -var DbClient DatabaseClient - -func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error { - DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", - dbUser, dbPassword, dbHost, dbPort, dbName, dbParam) - DbClient.dbType = dbType - DbClient.dbConnMaxLifetime = 0 - DbClient.dbMaxIdleConns = 0 - DbClient.dbMaxOpenConns = 0 - if log.GetLevel() == log.LOG_TRACE { - DbClient.IsShowSQL = true - } - log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl) - - var err error - DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl) - if err != nil { - log.Error("Failed to connet database:", err) - return err - } - DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime) - DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns) - DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns) - DbClient.XEngine.DatabaseTZ = time.Local // 必须 - DbClient.XEngine.TZLocation = time.Local // 必须 - if DbClient.IsShowSQL { - DbClient.XEngine.ShowSQL(true) - } - xEngine = DbClient.XEngine - - return nil -} - -func XormConnectDatabase(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) (*xorm.Engine, error) { - sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local", - dbUser, dbPassword, dbHost, dbPort, dbName) - log.Debugf("dbType:%s Connect to:%s:******@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local", - dbType, dbUser, dbHost, dbPort, dbName) - var err error - xEngine, err = xorm.NewEngine(dbType, sqlStr) //1、Create xorm engine - if err != nil { - log.Error("Failed to connect database:", err) - return nil, err - } - if log.GetLevel() == log.LOG_TRACE { - xEngine.ShowSQL(true) - } - return xEngine, nil -} - func IsNeedToAckAlarm(valueJson *dborm.ValueJson, alarm *Alarm) bool { log.Info("IsNeedToAckAlarm processing... ") if valueJson != nil { @@ -227,569 +131,444 @@ func SetAlarmAckInfo(valueJson *dborm.ValueJson, alarm *Alarm) { // process alarm post message from NFs func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) { log.Debug("PostAlarmFromNF processing... ") - - vars := mux.Vars(r) - apiVer := vars["apiVersion"] + apiVer := ctx.GetParam(r, "apiVersion") if apiVer != global.ApiVersionV1 { log.Error("Uri api version is invalid. apiVersion:", apiVer) - services.ResponseNotFound404UriNotExist(w, r) + services.ResponseWithJson(w, 422, resp.CodeMsg(40422, "api version is invalid")) return } - body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) - if err != nil { - log.Error("io.ReadAll is failed:", err) - services.ResponseNotFound404UriNotExist(w, r) + var body []Alarm + if err := ctx.ShouldBindJSON(r, &body); err != nil { + services.ResponseWithJson(w, 422, resp.ErrMsg(err.Error())) return } - log.Debug("Request body:", string(body)) - alarmArray := new([]Alarm) + // service object + neService := neService.NewNeInfo - err = json.Unmarshal(body, &alarmArray) - if err != nil { - log.Error("Failed to Unmarshal:", err) - services.ResponseBadRequest400InvalidJson(w) - return - } + for _, v := range body { + log.Debug("alarmData:", v) - valueJson, err := dborm.XormGetAAConfig() - if err != nil { - log.Error("Failed to XormGetAAConfig:", err) - //services.ResponseInternalServerError500ProcessError(w, err) - //return - } - log.Trace("valueJson:", valueJson) - // session := xEngine.NewSession() - // defer session.Close() - var activeAlarmNum int = 0 - for _, alarmData := range *alarmArray { - log.Debug("alarmData:", alarmData) + // 是否存在网元 neId实际是rmUID + neInfo := neService.FindByRmuid(v.NeId) + if neInfo.NeType != v.NeType { + msg := fmt.Sprintf("network element does not exist %s", v.NeId) + services.ResponseWithJson(w, 400, resp.ErrMsg(msg)) + return + } - session := xEngine.NewSession() - defer session.Close() - if alarmData.AlarmStatus == AlarmStatusClear { - alarmData.ClearType = ClearTypeAutoClear - alarmData.ClearTime.Valid = true - tm, _ := time.Parse(time.RFC3339, alarmData.EventTime) - log.Debugf("EventTime:%s tm:%d tm-datetime:%s", alarmData.EventTime, tm, tm.Local().Format(time.DateTime)) - alarmData.ClearTime.Time = tm - if IsNeedToAckAlarm(valueJson, &alarmData) { - SetAlarmAckInfo(valueJson, &alarmData) - affected, err := session.Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId). - Cols("alarm_status", "clear_type", "clear_time", "ack_state", "ack_time", "ack_user"). - Update(alarmData) - if err != nil && affected <= 0 { - log.Error("Failed to update alarm data:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) - continue - } - } else { - affected, err := session.Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId). - Cols("alarm_status", "clear_type", "clear_time"). - Update(alarmData) - if err != nil && affected <= 0 { - log.Error("Failed to update alarm data:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) - continue - } - } - log.Trace("alarmData:", alarmData) - var currentSeq string - var seq int - has, err := xEngine.Table("alarm"). - Where("ne_type=? and ne_id=?", alarmData.NeType, alarmData.NeId). - Desc("alarm_seq"). - Cols("alarm_seq"). - Limit(1). - Get(¤tSeq) - if err != nil { - log.Error("Failed to get alarm:", err) - continue - } - if has { - seq, _ = strconv.Atoi(currentSeq) - } + // 记录日志 + alarmSaveLog(neInfo, v) - eventTime := global.GetFmtTimeString(time.RFC3339, alarmData.EventTime, time.DateTime) - alarmLog := new(AlarmLog) - alarmLog.NeType = alarmData.NeType - alarmLog.NeId = alarmData.NeId - alarmLog.AlarmSeq = seq - alarmLog.AlarmId = alarmData.AlarmId - alarmLog.AlarmCode = alarmData.AlarmCode - alarmLog.AlarmStatus = alarmData.AlarmStatus - alarmLog.EventTime = eventTime - log.Trace("alarmLog:", alarmLog) + // 补充默认信息 + if v.LocationInfo == "" { + v.LocationInfo = fmt.Sprintf("Remote Host:%s", r.RemoteAddr) + } + if v.AddInfo == "" { + v.AddInfo = fmt.Sprintf("NeInfo:%s", v.NeType) + } + if v.ObjectUid == "" { + v.ObjectUid = neInfo.RmUID + } + if v.ObjectName == "" { + v.ObjectName = neInfo.NeName + } + if v.ObjectType == "" { + v.ObjectType = neInfo.NeType + } - affected, err := session.Insert(alarmLog) - if err != nil && affected <= 0 { - log.Error("Failed to insert alarm_log:", err) - } - - // todo: PerceivedSeverity set color - var severity string - has, err = xEngine.Table("alarm"). - Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime). - //OrderBy("FIELD(orig_severity, 'Critical', 'Major', 'Minor', 'Warning', 'Event') ASC"). - Asc("orig_severity"). - Cols("orig_severity"). - Limit(1). - Get(&severity) - if err != nil { - log.Error("Failed to get alarm:", err) - continue - } - log.Debugf("neType=%s, neId=%s, eventTime=%s, severity=%s", alarmData.NeType, alarmData.NeId, alarmData.EventTime, severity) - - if has && severity > alarmData.OrigSeverity { - // update exist record - _, err := session.Table("alarm"). - Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime). - Update(&Alarm{PerceivedSeverity: severity}) + // 告警事件 + if v.OrigSeverity == "Event" || v.OrigSeverity == "5" { + if v.AlarmStatus == AlarmStatusClear { + // 进行清除 + clearAlarmEvent, err := alarmEventClear(neInfo, v) if err != nil { - log.Error("Failed to update alarm:", err) - continue + services.ResponseWithJson(w, 400, resp.ErrMsg(err.Error())) + return } + groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM_EVENT, neInfo.NeType, neInfo.NeId) + wsService.NewWSSend.ByGroupID(groupID, clearAlarmEvent) } - session.Commit() - // for alarm forward time format - alarmData.EventTime = eventTime - } else { - activeAlarmNum++ - has, err := xEngine.Table("alarm"). - Where("alarm_id=? and ne_type=? and ne_id=? and alarm_status=1", - alarmData.AlarmId, alarmData.NeType, alarmData.NeId). - Exist() - if err == nil && has { - log.Warn("Exist the same alarm") - continue - } - - var currentSeq string - has, err = xEngine.Table("alarm"). - Where("ne_type=? and ne_id=?", alarmData.NeType, alarmData.NeId). - Desc("alarm_seq"). - //Desc("event_time"). - Cols("alarm_seq"). - Limit(1). - Get(¤tSeq) - if err != nil { - log.Error("Failed to get alarm:", err) - continue - } - log.Debugf("neType=%s, neId=%s, currentSeq=%s activeAlarmNum=%d", - alarmData.NeType, alarmData.NeId, currentSeq, activeAlarmNum) - - if has { - seq, _ := strconv.Atoi(currentSeq) - alarmData.AlarmSeq = seq + 1 - if alarmData.AlarmSeq > global.MaxInt32Number { - alarmData.AlarmSeq = AlarmSeqBeginNumber - } - } else { - alarmData.AlarmSeq = AlarmSeqBeginNumber - } - - // todo: PerceivedSeverity set color - var severity string - has, err = xEngine.Table("alarm"). - Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime). - //OrderBy("FIELD(orig_severity, 'Critical', 'Major', 'Minor', 'Warning', 'Event') ASC"). - Asc("orig_severity"). - Cols("orig_severity"). - Limit(1). - Get(&severity) - if err != nil { - log.Error("Failed to get alarm:", err) - continue - } - log.Debugf("neType=%s, neId=%s, eventTime=%s, severity=%s", alarmData.NeType, alarmData.NeId, alarmData.EventTime, severity) - - if !has || severity == alarmData.OrigSeverity { - alarmData.PerceivedSeverity = alarmData.OrigSeverity - } else if severity > alarmData.OrigSeverity { - alarmData.PerceivedSeverity = alarmData.OrigSeverity - } else { - alarmData.PerceivedSeverity = severity - // update exist record - _, err := session.Table("alarm"). - Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime). - Update(&Alarm{PerceivedSeverity: alarmData.PerceivedSeverity}) + if v.AlarmStatus == AlarmStatusActive { + // 进行新增 + newAlarmEvent, err := alarmEventNew(neInfo, v) if err != nil { - log.Error("Failed to update alarm:", err) - continue + services.ResponseWithJson(w, 400, resp.ErrMsg(err.Error())) + return } + groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM_EVENT, neInfo.NeType, neInfo.NeId) + wsService.NewWSSend.ByGroupID(groupID, newAlarmEvent) } - eventTime := global.GetFmtTimeString(time.RFC3339, alarmData.EventTime, time.DateTime) - alarmData.ObjectUid = alarmData.NeId - alarmData.ObjectType = "VNFM" - alarmData.EventTime = eventTime - if alarmData.LocationInfo == "" { - alarmData.LocationInfo = fmt.Sprintf("Host:%s", r.RemoteAddr) - } - if alarmData.AddInfo == "" { - alarmData.AddInfo = fmt.Sprintf("subNeInfo:%s", alarmData.NeType) - } - if IsNeedToAckAlarm(valueJson, &alarmData) { - SetAlarmAckInfo(valueJson, &alarmData) - } - log.Trace("alarmData:", alarmData) - if (alarmData.OrigSeverity == "Event" || alarmData.OrigSeverity == "5") && config.GetYamlConfig().Alarm.SplitEventAlarm { - affected, err := xEngine.Table("alarm_event").InsertOne(alarmData) - if err != nil && affected <= 0 { - log.Error("Failed to insert alarm_event:", err) - services.ResponseInternalServerError500ProcessError(w, err) - continue - } - } else { - affected, err := session.Insert(alarmData) - if err != nil && affected <= 0 { - log.Error("Failed to insert alarm data:", err) - services.ResponseInternalServerError500DatabaseOperationFailed(w) - continue - } - } - alarmLog := new(AlarmLog) - alarmLog.NeType = alarmData.NeType - alarmLog.NeId = alarmData.NeId - alarmLog.AlarmSeq = alarmData.AlarmSeq - alarmLog.AlarmId = alarmData.AlarmId - alarmLog.AlarmCode = alarmData.AlarmCode - alarmLog.AlarmStatus = alarmData.AlarmStatus - alarmLog.EventTime = eventTime - log.Trace("alarmLog:", alarmLog) + continue + } - affected, err := session.Insert(alarmLog) - if err != nil && affected <= 0 { - log.Error("Failed to insert alarm_log:", err) + if v.AlarmStatus == AlarmStatusClear { + // 进行清除 + clearAlarm, err := alarmClear(neInfo, v) + if err != nil { + services.ResponseWithJson(w, 400, resp.ErrMsg(err.Error())) + return } - session.Commit() + groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId) + wsService.NewWSSend.ByGroupID(groupID, clearAlarm) } - if config.GetYamlConfig().Alarm.EmailForward.Enable { - if err = AlarmEmailForward(&alarmData); err != nil { - log.Error("Failed to AlarmEmailForward:", err) - } - } - if config.GetYamlConfig().Alarm.SMSCForward.Enable { - if err = AlarmSMSForward(&alarmData); err != nil { - log.Error("Failed to AlarmSMSForward:", err) + if v.AlarmStatus == AlarmStatusActive { + // 进行新增 + newAlarm, err := alarmNew(neInfo, v) + if err != nil { + services.ResponseWithJson(w, 400, resp.ErrMsg(err.Error())) + return } + groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId) + wsService.NewWSSend.ByGroupID(groupID, newAlarm) } + + // for alarm forward 告警转发 + alarmForward(v) } - services.ResponseStatusOK200Null(w) + services.ResponseStatusOK204NoContent(w) } -type AlarmEvent struct { - AlarmSeq int `json:"alarmSeq"` - AlarmId string `json:"alarmId" xorm:"alarm_id"` - NeId string `json:"neId"` - AlarmCode int `json:"alarmCode"` - AlarmTitle string `json:"alarmTitle"` - EventTime string `json:"eventTime"` - AlarmType string `json:"alarmType"` - OrigSeverity string `json:"origSeverity"` - PVFlag string `json:"pvFlag" xorm:"pv_flag"` - NeName string `json:"neName"` - NeType string `json:"neType"` - ObjectUid string `json:"objectUid" xorm:"object_uid"` - ObjectName string `json:"objectName" xorm:"object_name"` - ObjectType string `json:"objectType" xorm:"object_type"` - LocationInfo string `json:"locationInfo"` - Province string `json:"province"` - SpecificProblem string `json:"specificProblem"` - SpecificProblemID string `json:"specificProblemID" xorm:"specific_problem_id"` - AddInfo string `json:"addInfo"` +// alarmTypeValue 映射值 +func alarmTypeValue(str string) string { + arr := []string{"CommunicationAlarm", "EquipmentAlarm", "ProcessingFailure", "EnvironmentalAlarm", "QualityOfServiceAlarm"} + for k, v := range arr { + if v == str { + return fmt.Sprint(k + 1) + } + } + return str +} + +// origSeverityValue 映射值 +func origSeverityValue(str string) string { + arr := []string{"Critical", "Major", "Minor", "Warning", "Event"} + for k, v := range arr { + if v == str { + return fmt.Sprint(k + 1) + } + } + return str +} + +// alarmNew 清除告警 +func alarmClear(neInfo neModel.NeInfo, v Alarm) (neDataModel.Alarm, error) { + alarmService := neDataService.NewAlarm + // 检查网元告警ID是否唯一 + alarmIdArr := alarmService.Find(neDataModel.Alarm{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + AlarmId: v.AlarmId, + }) + if len(alarmIdArr) != 1 { + return neDataModel.Alarm{}, fmt.Errorf("[%s %s] clear alarm not exists alarmId:%s", neInfo.NeType, neInfo.NeId, v.AlarmId) + } + + // 产生时间 + eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ) + + alarm := neDataModel.Alarm{ + ID: alarmIdArr[0].ID, + NeType: neInfo.NeType, + NeId: neInfo.NeId, + NeName: neInfo.NeName, + Province: neInfo.Province, + PvFlag: neInfo.PvFlag, + AlarmSeq: alarmIdArr[0].AlarmSeq, // seq 告警序号 + AlarmId: v.AlarmId, + AlarmTitle: v.AlarmTitle, + AlarmCode: int64(v.AlarmCode), + EventTime: eventTime.UnixMilli(), + AlarmType: alarmTypeValue(v.AlarmType), + OrigSeverity: origSeverityValue(v.OrigSeverity), + PerceivedSeverity: origSeverityValue(v.PerceivedSeverity), + ObjectUid: v.ObjectUid, + ObjectName: v.ObjectName, + ObjectType: v.ObjectType, + LocationInfo: v.LocationInfo, + AlarmStatus: fmt.Sprint(v.AlarmStatus), + SpecificProblem: v.SpecificProblem, + SpecificProblemId: v.SpecificProblemID, + AddInfo: v.AddInfo, + } + + // 告警清除 + alarm.ClearType = ClearTypeAutoClear + alarm.ClearTime = eventTime.UnixMilli() + alarm.ClearUser = neInfo.NeName + rows := alarmService.Update(alarm) + if rows > 0 { + return alarm, nil + } + return neDataModel.Alarm{}, fmt.Errorf("[%s %s] clear alarm fail", neInfo.NeType, neInfo.NeId) +} + +// alarmNew 新增告警 +func alarmNew(neInfo neModel.NeInfo, v Alarm) (neDataModel.Alarm, error) { + alarmService := neDataService.NewAlarm + // 检查网元告警ID是否唯一 + alarmIdArr := alarmService.Find(neDataModel.Alarm{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + AlarmId: v.AlarmId, + }) + if len(alarmIdArr) > 0 { + return neDataModel.Alarm{}, fmt.Errorf("[%s %s] new alarm already exists alarmId:%s", neInfo.NeType, neInfo.NeId, v.AlarmId) + } + // seq 告警序号 + lastSeq := alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId) + // 产生时间 + eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ) + + alarm := neDataModel.Alarm{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + NeName: neInfo.NeName, + Province: neInfo.Province, + PvFlag: neInfo.PvFlag, + AlarmSeq: lastSeq + 1, + AlarmId: v.AlarmId, + AlarmTitle: v.AlarmTitle, + AlarmCode: int64(v.AlarmCode), + EventTime: eventTime.UnixMilli(), + AlarmType: alarmTypeValue(v.AlarmType), + OrigSeverity: origSeverityValue(v.OrigSeverity), + PerceivedSeverity: origSeverityValue(v.PerceivedSeverity), + ObjectUid: v.ObjectUid, + ObjectName: v.ObjectName, + ObjectType: v.ObjectType, + LocationInfo: v.LocationInfo, + AlarmStatus: fmt.Sprint(v.AlarmStatus), + SpecificProblem: v.SpecificProblem, + SpecificProblemId: v.SpecificProblemID, + AddInfo: v.AddInfo, + } + insertId := alarmService.Insert(alarm) + if insertId > 0 { + alarm.ID = insertId + return alarm, nil + } + return neDataModel.Alarm{}, fmt.Errorf("[%s %s] new alarm fail", neInfo.NeType, neInfo.NeId) +} + +// alarmSaveLog 保存告警日志 +func alarmSaveLog(neInfo neModel.NeInfo, v Alarm) int64 { + alarmLogService := neDataService.NewAlarmLog + eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ) + alarmLog := neDataModel.AlarmLog{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + AlarmSeq: int64(v.AlarmSeq), + AlarmId: v.AlarmId, + AlarmTitle: v.AlarmTitle, + AlarmCode: int64(v.AlarmCode), + AlarmStatus: fmt.Sprint(v.AlarmStatus), + OrigSeverity: origSeverityValue(v.OrigSeverity), + EventTime: eventTime.UnixMilli(), + } + return alarmLogService.Insert(alarmLog) +} + +// alarmForward 告警转发 +func alarmForward(v Alarm) { + if config.GetYamlConfig().Alarm.EmailForward.Enable { + if err := AlarmEmailForward(&v); err != nil { + log.Error("Failed to AlarmEmailForward:", err) + } + } + if config.GetYamlConfig().Alarm.SMSCForward.Enable { + if err := AlarmSMSForward(&v); err != nil { + log.Error("Failed to AlarmSMSForward:", err) + } + } +} + +// alarmEventNew 清除告警事件 +func alarmEventClear(neInfo neModel.NeInfo, v Alarm) (neDataModel.AlarmEvent, error) { + alarmEventService := neDataService.NewAlarmEvent + // 检查网元告警ID是否唯一 + alarmIdArr := alarmEventService.Find(neDataModel.AlarmEvent{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + AlarmId: v.AlarmId, + }) + if len(alarmIdArr) != 1 { + return neDataModel.AlarmEvent{}, fmt.Errorf("[%s %s] clear alarm event not exists alarmId:%s", neInfo.NeType, neInfo.NeId, v.AlarmId) + } + + // 产生时间 + eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ) + + alarmEvent := neDataModel.AlarmEvent{ + ID: alarmIdArr[0].ID, + NeType: neInfo.NeType, + NeId: neInfo.NeId, + AlarmSeq: alarmIdArr[0].AlarmSeq, // seq 告警序号 + AlarmId: v.AlarmId, + AlarmTitle: v.AlarmTitle, + AlarmCode: int64(v.AlarmCode), + EventTime: eventTime.UnixMilli(), + ObjectUid: v.ObjectUid, + ObjectName: v.ObjectName, + ObjectType: v.ObjectType, + LocationInfo: v.LocationInfo, + AlarmStatus: fmt.Sprint(v.AlarmStatus), + SpecificProblem: v.SpecificProblem, + SpecificProblemId: v.SpecificProblemID, + AddInfo: v.AddInfo, + } + + // 告警清除 + alarmEvent.ClearType = ClearTypeAutoClear + alarmEvent.ClearTime = eventTime.UnixMilli() + alarmEvent.ClearUser = neInfo.NeName + rows := alarmEventService.Update(alarmEvent) + if rows > 0 { + return alarmEvent, nil + } + return neDataModel.AlarmEvent{}, fmt.Errorf("[%s %s] clear alarm event fail", neInfo.NeType, neInfo.NeId) +} + +// alarmEventNew 新增告警事件 +func alarmEventNew(neInfo neModel.NeInfo, v Alarm) (neDataModel.AlarmEvent, error) { + alarmEventService := neDataService.NewAlarmEvent + // 检查网元告警ID是否唯一 + alarmIdArr := alarmEventService.Find(neDataModel.AlarmEvent{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + AlarmId: v.AlarmId, + }) + if len(alarmIdArr) > 0 { + return neDataModel.AlarmEvent{}, fmt.Errorf("[%s %s] new alarm event already exists alarmId:%s", neInfo.NeType, neInfo.NeId, v.AlarmId) + } + // seq 告警序号 + lastSeq := alarmEventService.FindAlarmEventSeqLast(neInfo.NeType, neInfo.NeId) + // 产生时间 + eventTime := date.ParseStrToDate(v.EventTime, date.YYYY_MM_DDTHH_MM_SSZ) + + alarmEvent := neDataModel.AlarmEvent{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + AlarmSeq: lastSeq + 1, + AlarmId: v.AlarmId, + AlarmTitle: v.AlarmTitle, + AlarmCode: int64(v.AlarmCode), + EventTime: eventTime.UnixMilli(), + ObjectUid: v.ObjectUid, + ObjectName: v.ObjectName, + ObjectType: v.ObjectType, + LocationInfo: v.LocationInfo, + AlarmStatus: fmt.Sprint(v.AlarmStatus), + SpecificProblem: v.SpecificProblem, + SpecificProblemId: v.SpecificProblemID, + AddInfo: v.AddInfo, + } + insertId := alarmEventService.Insert(alarmEvent) + if insertId > 0 { + alarmEvent.ID = insertId + return alarmEvent, nil + } + return neDataModel.AlarmEvent{}, fmt.Errorf("[%s %s] new alarm event fail", neInfo.NeType, neInfo.NeId) +} + +// mapToAlarm 将 []map[string]any 转换为 []Alarm +func mapToAlarm(data []map[string]any) []Alarm { + var result []Alarm + + // 将 []map[string]any 序列化为 JSON 字符串 + jsonData, err := json.Marshal(data) + if err != nil { + log.Error("Error marshaling data:", err) + return result + } + + // 反序列化到结构体 + err = json.Unmarshal(jsonData, &result) + if err != nil { + log.Error("Error unmarshaling data:", err) + return result + } + return result } // process alarm get from NFs func GetAlarmFromNF(w http.ResponseWriter, r *http.Request) { log.Debug("GetAlarmFromNF processing... ") - - // _, err := services.CheckFrontValidRequest(w, r) - // if err != nil { - // log.Error("Request error:", err) - // return - // } - vars := mux.Vars(r) - neType := vars["elementTypeValue"] + neType := ctx.GetParam(r, "elementTypeValue") neTypeLower := strings.ToLower(neType) // Get alarms from OMC return 204 if neTypeLower == strings.ToLower(config.GetYamlConfig().OMC.NeType) { log.Infof("Return no content alarms from %s", neType) - services.ResponseStatusOK204NoContent(w) + services.ResponseWithJson(w, 200, resp.ErrMsg("omc alarms no content")) return } - //var neInfo *dborm.NeInfo - var nes []dborm.NeInfo - _, err := dborm.XormGetAllNeInfo(&nes) - if err != nil { - log.Error("Failed to get all ne info:", err) - services.ResponseInternalServerError500ProcessError(w, err) - return - } - - for _, ne := range nes { - hostUri := fmt.Sprintf("http://%s:%v", ne.Ip, ne.Port) - apiUri := fmt.Sprintf(UriAlarmsFmt, strings.ToLower(ne.NeType)) - requestURI2NF := fmt.Sprintf("%s%s", hostUri, apiUri) - log.Debug("requestURI2NF: Get ", requestURI2NF) - // client := resty.New() - response, err := client.R(). - EnableTrace(). - SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). - SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). - Get(requestURI2NF) + neInfos := neService.NewNeInfo.Find(neModel.NeInfo{}, false, false) + for _, neInfo := range neInfos { + data, err := neFetchlink.AlarmHistory(neInfo) if err != nil { - log.Error("Failed to Get:", err) - //services.ResponseInternalServerError500ProcessError(w, err) + log.Error("Failed to fetch alarm history:", err) + continue + } + if len(data) == 0 { + log.Infof("Not found sync alarms, neType=%s, neId=%s", neInfo.NeType, neInfo.NeId) continue } - alarmArray := new([]Alarm) - switch response.StatusCode() { - case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: - body := response.Body() - if len(body) == 0 || body == nil { - log.Infof("Empty alarm body from neType=%s, neId=%s", ne.NeType, ne.NeId) - //services.ResponseInternalServerError500ProcessError(w, err) + alarms := mapToAlarm(data) + for _, v := range alarms { + // 补充默认信息 + if v.LocationInfo == "" { + v.LocationInfo = fmt.Sprintf("Remote Host:%s", r.RemoteAddr) + } + if v.AddInfo == "" { + v.AddInfo = fmt.Sprintf("NeInfo:%s", v.NeType) + } + if v.ObjectUid == "" { + v.ObjectUid = neInfo.RmUID + } + if v.ObjectName == "" { + v.ObjectName = neInfo.NeName + } + if v.ObjectType == "" { + v.ObjectType = neInfo.NeType + } + + // 告警事件 + if v.OrigSeverity == "Event" || v.OrigSeverity == "5" { + if v.AlarmStatus == AlarmStatusClear { + // 进行清除 + if _, err := alarmEventClear(neInfo, v); err != nil { + log.Error("Failed to alarmEventClear:", err) + continue + } + } + if v.AlarmStatus == AlarmStatusActive { + // 进行新增 + if _, err := alarmEventNew(neInfo, v); err != nil { + log.Error("Failed to alarmEventNew:", err) + continue + } + } continue } - //log.Debug("Request body:", string(body)) - err = json.Unmarshal(body, &alarmArray) - if err != nil { - log.Error("Failed to Unmarshal:", err) - //services.ResponseInternalServerError500ProcessError(w, err) - continue + if v.AlarmStatus == AlarmStatusClear { + // 进行清除 + if _, err := alarmClear(neInfo, v); err != nil { + log.Error("Failed to alarmClear:", err) + continue + } } - default: - log.Error("Failed to get alarms:", response.Status) - continue - } - - valueJson, err := dborm.XormGetAAConfig() - if err != nil { - log.Error("Failed to XormGetAAConfig:", err) - //services.ResponseInternalServerError500ProcessError(w, err) - continue - } - if alarmArray == nil { - log.Infof("Not found sync alarms, neType=%s, neId=%s", ne.NeType, ne.NeId) - //services.ResponseInternalServerError500ProcessError(w, err) - continue - } - // session := xEngine.NewSession() - // defer session.Close() - var activeAlarmNum int = 0 - for _, alarmData := range *alarmArray { - log.Debug("alarmData:", alarmData) - - session := xEngine.NewSession() - defer session.Close() - // todo: clear alarm .... - if alarmData.AlarmStatus == AlarmStatusClear { - exist, err := session.Table("alarm"). - Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId). - Exist() - if err != nil || !exist { - log.Infof("Not found active alarm: ne_id=%s, alarm_id=%s", alarmData.NeId, alarmData.AlarmId) + if v.AlarmStatus == AlarmStatusActive { + // 进行新增 + if _, err := alarmNew(neInfo, v); err != nil { + log.Error("Failed to alarmNew:", err) continue } - alarmData.ClearType = ClearTypeAutoClear - alarmData.ClearTime.Valid = true - tm, _ := time.Parse(time.RFC3339, alarmData.EventTime) - log.Debugf("EventTime:%s tm:%d tm-datetime:%s", alarmData.EventTime, tm, tm.Local().Format(time.DateTime)) - alarmData.ClearTime.Time = tm - if IsNeedToAckAlarm(valueJson, &alarmData) { - SetAlarmAckInfo(valueJson, &alarmData) - log.Debug("alarmData:", alarmData) - affected, err := session. - Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId). - Cols("alarm_status", "clear_type", "clear_time", "ack_state", "ack_time", "ack_user"). - Update(alarmData) - if err != nil && affected <= 0 { - log.Error("Failed to update alarm data:", err) - //services.ResponseInternalServerError500DatabaseOperationFailed(w) - continue - } - } else { - affected, err := session. - Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId). - Cols("alarm_status", "clear_type", "clear_time"). - Update(alarmData) - if err != nil && affected <= 0 { - log.Error("Failed to update alarm data:", err) - //services.ResponseInternalServerError500DatabaseOperationFailed(w) - continue - } - } - - eventTime := global.GetFmtTimeString(time.RFC3339, alarmData.EventTime, time.DateTime) - alarmLog := new(AlarmLog) - alarmLog.NeType = alarmData.NeType - alarmLog.NeId = alarmData.NeId - alarmLog.AlarmSeq = alarmData.AlarmSeq - alarmLog.AlarmId = alarmData.AlarmId - alarmLog.AlarmCode = alarmData.AlarmCode - alarmLog.AlarmStatus = alarmData.AlarmStatus - alarmLog.EventTime = eventTime - log.Debug("alarmLog:", alarmLog) - - affected, err := session.Insert(alarmLog) - if err != nil && affected <= 0 { - log.Error("Failed to insert alarm_log:", err) - } - - // todo: PerceivedSeverity set color - var severity string - has, err := xEngine.Table("alarm"). - Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime). - //OrderBy("FIELD(orig_severity, 'Critical', 'Major', 'Minor', 'Warning', 'Event') ASC"). - Asc("orig_severity"). - Cols("orig_severity"). - Limit(1). - Get(&severity) - if err != nil { - log.Error("Failed to get alarm:", err) - continue - } - log.Debugf("neType=%s, neId=%s, eventTime=%s, severity=%s", alarmData.NeType, alarmData.NeId, alarmData.EventTime, severity) - - if has && severity > alarmData.OrigSeverity { - // update exist record - _, err := session.Table("alarm"). - Where("ne_type=? and ne_id=? and event_time=?", alarmData.NeType, alarmData.NeId, alarmData.EventTime). - Update(&Alarm{PerceivedSeverity: severity}) - if err != nil { - log.Error("Failed to update alarm:", err) - continue - } - } - session.Commit() - // for alarm forward time format - alarmData.EventTime = eventTime - } else { - activeAlarmNum++ - has, err := xEngine.Table("alarm"). - Where("alarm_id=? and ne_type=? and ne_id=? and alarm_status=1", - alarmData.AlarmId, alarmData.NeType, alarmData.NeId). - Exist() - if err == nil && has { - log.Warn("Exist the same alarm") - continue - } - - var currentSeq string - has, err = xEngine.Table("alarm"). - Where("ne_type=? and ne_id=?", alarmData.NeType, alarmData.NeId). - Desc("alarm_seq"). - //Desc("event_time"). - Cols("alarm_seq"). - Limit(1). - Get(¤tSeq) - if err != nil { - log.Error("Failed to get alarm:", err) - continue - } - log.Debugf("neType=%s, neId=%s, currentSeq=%s, activeAlarmNum=%d", - alarmData.NeType, alarmData.NeId, currentSeq, activeAlarmNum) - - if has { - seq, _ := strconv.Atoi(currentSeq) - alarmData.AlarmSeq = seq + 1 - if alarmData.AlarmSeq > global.MaxInt32Number { - alarmData.AlarmSeq = AlarmSeqBeginNumber - } - } else { - alarmData.AlarmSeq = AlarmSeqBeginNumber - } - - // todo: PerceivedSeverity set color - var severity string - has, err = xEngine.Table("alarm"). - Where("ne_type=? and ne_id=? and event_time=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.EventTime). - //OrderBy("FIELD(orig_severity, 'Critical', 'Major', 'Minor', 'Warning', 'Event') ASC"). - Asc("orig_severity"). - Cols("orig_severity"). - Limit(1). - Get(&severity) - if err != nil { - log.Error("Failed to get alarm:", err) - continue - } - log.Debugf("neType=%s, neId=%s, eventTime=%s, severity=%s", alarmData.NeType, alarmData.NeId, alarmData.EventTime, severity) - - if !has || severity == alarmData.OrigSeverity { - alarmData.PerceivedSeverity = alarmData.OrigSeverity - } else if severity > alarmData.OrigSeverity { - alarmData.PerceivedSeverity = alarmData.OrigSeverity - } else { - alarmData.PerceivedSeverity = severity - // update exist record - _, err := session.Table("alarm"). - Where("ne_type=? and ne_id=? and event_time=?", alarmData.NeType, alarmData.NeId, alarmData.EventTime). - Update(&Alarm{PerceivedSeverity: alarmData.PerceivedSeverity}) - if err != nil { - log.Error("Failed to update alarm:", err) - continue - } - } - - evenTime := global.GetFmtTimeString(time.RFC3339, alarmData.EventTime, time.DateTime) - alarmData.ObjectUid = alarmData.NeId - alarmData.ObjectType = "VNFM" - alarmData.EventTime = evenTime - if IsNeedToAckAlarm(valueJson, &alarmData) { - SetAlarmAckInfo(valueJson, &alarmData) - } - log.Trace("alarmData:", alarmData) - var affected int64 - if (alarmData.OrigSeverity == "Event" || alarmData.OrigSeverity == "5") && config.GetYamlConfig().Alarm.SplitEventAlarm { - affected, err = session.Table("alarm_event").InsertOne(alarmData) - if err != nil && affected <= 0 { - log.Error("Failed to insert alarm_event:", err) - continue - } - } else { - affected, err = session.Table("alarm").Insert(alarmData) - if err != nil && affected <= 0 { - log.Error("Failed to insert alarm:", err) - continue - } - } - if err == nil && affected > 0 { - alarmLog := new(AlarmLog) - alarmLog.NeType = alarmData.NeType - alarmLog.NeId = alarmData.NeId - alarmLog.AlarmSeq = alarmData.AlarmSeq - alarmLog.AlarmId = alarmData.AlarmId - alarmLog.AlarmCode = alarmData.AlarmCode - alarmLog.AlarmStatus = alarmData.AlarmStatus - alarmLog.EventTime = evenTime - log.Trace("alarmLog:", alarmLog) - affected, err = session.Insert(alarmLog) - if err != nil && affected <= 0 { - log.Error("Failed to insert data:", err) - //services.ResponseInternalServerError500DatabaseOperationFailed(w) - continue - } - session.Commit() - if config.GetYamlConfig().Alarm.EmailForward.Enable { - if err = AlarmEmailForward(&alarmData); err != nil { - log.Error("Failed to AlarmEmailForward:", err) - } - } - if config.GetYamlConfig().Alarm.SMSCForward.Enable { - if err = AlarmSMSForward(&alarmData); err != nil { - log.Error("Failed to AlarmSMSForward:", err) - } - } - } - log.Warn("Failed to insert alarm data:", err) } } } diff --git a/features/fm/email.go b/features/fm/email.go index bd4d0c3a..bb00e902 100644 --- a/features/fm/email.go +++ b/features/fm/email.go @@ -6,7 +6,6 @@ import ( "strings" "be.ems/lib/config" - "be.ems/lib/dborm" "be.ems/lib/log" "gopkg.in/gomail.v2" @@ -66,16 +65,6 @@ func AlarmEmailForward(alarmData *Alarm) error { // return err // } emails := strings.Split(config.GetYamlConfig().Alarm.EmailForward.EmailList, ",") - forwardLog := &dborm.AlarmForwardLog{ - NeType: alarmData.NeType, - NeID: alarmData.NeId, - AlarmID: alarmData.AlarmId, - AlarmTitle: alarmData.AlarmTitle, - AlarmSeq: alarmData.AlarmSeq, - EventTime: alarmData.EventTime, - ToUser: config.GetYamlConfig().Alarm.EmailForward.EmailList, - } - m.SetHeader("To", emails...) // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接 //m.SetHeader("To", strings.Join(*emails, " ")) // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接 //m.SetHeader("To", "zhangshuzhong@agrandtech.com", "simonzhangsz@outlook.com") // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接 @@ -107,22 +96,6 @@ func AlarmEmailForward(alarmData *Alarm) error { d.TLSConfig = &tls.Config{InsecureSkipVerify: false} } - if err := d.DialAndSend(m); err != nil { - operResult := fmt.Sprintf("Failed to DialAndSend:%v", err) - log.Error(operResult) - forwardLog.OperResult = operResult - affected, err := dborm.XormInsertAlarmForwardLog(forwardLog) - if err != nil && affected <= 0 { - log.Error("Failed to insert data:", err) - } - return err - } - - forwardLog.OperResult = "Email sent successfully!" - affected, err := dborm.XormInsertAlarmForwardLog(forwardLog) - if err != nil && affected <= 0 { - log.Error("Failed to insert data:", err) - return err - } - return nil + err := d.DialAndSend(m) + return writeLog(alarmData, config.GetYamlConfig().Alarm.EmailForward.EmailList, "EMAIL", err) } diff --git a/features/fm/smsforward.go b/features/fm/smsforward.go index 6ba40eb8..5d15b4f5 100644 --- a/features/fm/smsforward.go +++ b/features/fm/smsforward.go @@ -11,6 +11,10 @@ import ( "be.ems/lib/config" "be.ems/lib/dborm" "be.ems/lib/log" + "be.ems/src/framework/utils/date" + neDataModel "be.ems/src/modules/network_data/model" + neDataService "be.ems/src/modules/network_data/service" + neService "be.ems/src/modules/network_element/service" "github.com/linxGnu/gosmpp" "github.com/linxGnu/gosmpp/data" "github.com/linxGnu/gosmpp/pdu" @@ -167,28 +171,31 @@ func AlarmForwardBySMPP(alarmData *Alarm) (string, error) { } func writeLog(alarmData *Alarm, toUser, forwardBy string, err error) error { - var result string - if err == nil { - result = "SMS sent successfully" - } else { + var result string = fmt.Sprintf("%s Sent Successfully!", forwardBy) + if err != nil { result = err.Error() } - forwardLog := &dborm.AlarmForwardLog{ - NeType: alarmData.NeType, - NeID: alarmData.NeId, - AlarmID: alarmData.AlarmId, - AlarmTitle: alarmData.AlarmTitle, - AlarmSeq: alarmData.AlarmSeq, - EventTime: alarmData.EventTime, - Interface: forwardBy, - ToUser: toUser, - OperResult: result, + neInfo := neService.NewNeInfo.FindByRmuid(alarmData.NeId) + eventTime := date.ParseStrToDate(alarmData.EventTime, date.YYYY_MM_DDTHH_MM_SSZ) + alarmForwardLog := neDataModel.AlarmForwardLog{ + NeType: neInfo.NeType, + NeId: neInfo.NeId, + AlarmSeq: int64(alarmData.AlarmSeq), + AlarmId: alarmData.AlarmId, + AlarmTitle: alarmData.AlarmTitle, + AlarmCode: int64(alarmData.AlarmCode), + AlarmStatus: fmt.Sprint(alarmData.AlarmStatus), + OrigSeverity: origSeverityValue(alarmData.OrigSeverity), + EventTime: eventTime.UnixMilli(), + Type: forwardBy, + Target: toUser, + Result: result, } - affected, err := dborm.XormInsertAlarmForwardLog(forwardLog) - if err != nil && affected <= 0 { - log.Error("Failed to insert data:", err) - return err + // 记录日志 + insertId := neDataService.NewAlarmForwardLog.Insert(alarmForwardLog) + if insertId <= 0 { + return fmt.Errorf("failed to insert data") } return nil } diff --git a/features/lm/file_export/controller.go b/features/lm/file_export/controller.go index 060efa65..020968d8 100644 --- a/features/lm/file_export/controller.go +++ b/features/lm/file_export/controller.go @@ -2,25 +2,21 @@ package file_export import ( "encoding/json" - "fmt" "net/http" "os" "path" "path/filepath" - "time" - - "github.com/jlaffaye/ftp" "be.ems/lib/file" "be.ems/lib/log" "be.ems/lib/services" "be.ems/src/framework/config" - "be.ems/src/framework/datasource" + "be.ems/src/framework/database/db" "be.ems/src/framework/i18n" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" + "be.ems/src/framework/ssh" "be.ems/src/framework/utils/crypto" - "be.ems/src/framework/utils/ctx" - "be.ems/src/framework/utils/ssh" - "be.ems/src/framework/vo/result" systemService "be.ems/src/modules/system/service" "github.com/gin-gonic/gin" ) @@ -45,13 +41,13 @@ type TargetParams struct { func (m *SysJob) GetFileExportTable(c *gin.Context) { var results []SysJob - err := datasource.DefaultDB().Table(m.TableName()).Where("invoke_target=? and status=1", INVOKE_FILE_EXPORT). + err := db.DB("").Table(m.TableName()).Where("invoke_target=? and status=1", INVOKE_FILE_EXPORT). Find(&results).Error if err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var response []SysJobResponse for _, job := range results { var params TargetParams @@ -154,54 +150,54 @@ func (m *FileExport) Delete(c *gin.Context) { // 设置FTP配置 // POST /table/ftp func (m *SysJob) SetFTPConfig(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { Password string `json:"password" ` Username string `json:"username" binding:"required"` ToIp string `json:"toIp" binding:"required"` ToPort int64 `json:"toPort" binding:"required"` - Protocol string `json:"protocol" binding:"required,oneof=ssh ftp"` + Enable bool `json:"enable"` Dir string `json:"dir" binding:"required"` } if err := c.ShouldBindBodyWithJSON(&body); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 获取配置 - cfg := systemService.NewSysConfigImpl.SelectConfigByKey("sys.exportTable") - if cfg.ConfigID != "" { + cfg := systemService.NewSysConfig.FindByKey("sys.exportTable") + if cfg.ConfigId > 0 { // 加密body appKey := config.Get("aes.appKey").(string) byteData, err := json.Marshal(body) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } bodyEn, err := crypto.AESEncryptBase64(string(byteData), appKey) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } // 更新 cfg.ConfigValue = bodyEn - systemService.NewSysConfigImpl.UpdateConfig(cfg) + systemService.NewSysConfig.Update(cfg) } - c.JSON(200, result.Ok(nil)) + c.JSON(200, resp.Ok(nil)) } -// 设置FTP配置 +// 获取FTP配置 // GET /table/ftp func (m *SysJob) GetFTPConfig(c *gin.Context) { // 获取配置 - cfg := systemService.NewSysConfigImpl.SelectConfigByKey("sys.exportTable") - if cfg.ConfigID != "" { + cfg := systemService.NewSysConfig.FindByKey("sys.exportTable") + if cfg.ConfigId > 0 { // 解密body appKey := config.Get("aes.appKey").(string) bodyDe, err := crypto.AESDecryptBase64(cfg.ConfigValue, appKey) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } var body struct { @@ -209,31 +205,31 @@ func (m *SysJob) GetFTPConfig(c *gin.Context) { Username string `json:"username" binding:"required"` ToIp string `json:"toIp" binding:"required"` ToPort int64 `json:"toPort" binding:"required"` - Protocol string `json:"protocol" binding:"required,oneof=ssh ftp"` + Enable bool `json:"enable"` Dir string `json:"dir" binding:"required"` } err = json.Unmarshal([]byte(bodyDe), &body) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } - c.JSON(200, result.OkData(body)) + c.JSON(200, resp.OkData(body)) return } - c.JSON(200, result.Ok(nil)) + c.JSON(200, resp.Ok(nil)) } // FTP发送 // PUT /table/ftp func (m *SysJob) PutFTP(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { FilePath string `json:"filePath" binding:"required"` FileName string `json:"fileName" binding:"required"` } if err := c.ShouldBindBodyWithJSON(&body); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } @@ -241,7 +237,7 @@ func (m *SysJob) PutFTP(c *gin.Context) { // 判断文件是否存在 if _, err := os.Stat(localFilePath); os.IsNotExist(err) { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } @@ -251,88 +247,55 @@ func (m *SysJob) PutFTP(c *gin.Context) { Username string `json:"username" binding:"required"` ToIp string `json:"toIp" binding:"required"` ToPort int64 `json:"toPort" binding:"required"` - Protocol string `json:"protocol" binding:"required,oneof=ssh ftp"` + Enable bool `json:"enable"` Dir string `json:"dir" binding:"required"` } - cfg := systemService.NewSysConfigImpl.SelectConfigByKey("sys.exportTable") - if cfg.ConfigID != "" { + cfg := systemService.NewSysConfig.FindByKey("sys.exportTable") + if cfg.ConfigId > 0 { // 解密body appKey := config.Get("aes.appKey").(string) bodyDe, err := crypto.AESDecryptBase64(cfg.ConfigValue, appKey) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } err = json.Unmarshal([]byte(bodyDe), &cfgData) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } } - - if cfgData.Protocol == "ssh" { - connSSH := ssh.ConnSSH{ - User: cfgData.Username, - Password: cfgData.Password, - Addr: cfgData.ToIp, - Port: cfgData.ToPort, - AuthMode: "0", - } - sshClient, err := connSSH.NewClient() - if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) - return - } - defer sshClient.Close() - // 网元主机的SSH客户端进行文件传输 - sftpClient, err := sshClient.NewClientSFTP() - if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) - return - } - defer sftpClient.Close() - // 远程文件 - remotePath := filepath.Join(cfgData.Dir, path.Base(body.FilePath), body.FileName) - // 复制到远程 - if err = sftpClient.CopyFileLocalToRemote(localFilePath, remotePath); err != nil { - c.JSON(200, result.ErrMsg("error uploading file")) - return - } - c.JSON(200, result.Ok(nil)) + if !cfgData.Enable { + c.JSON(200, resp.ErrMsg("Setting Remote Backup is disabled")) return } - if cfgData.Protocol == "ftp" { - // 连接到 FTP 服务器 - addr := fmt.Sprintf("%s:%d", cfgData.ToIp, cfgData.ToPort) - ftpComm, err := ftp.Dial(addr, ftp.DialWithTimeout(15*time.Second)) - if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) - return - } - // 登录到 FTP 服务器 - err = ftpComm.Login(cfgData.Username, cfgData.Password) - if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) - return - } - defer ftpComm.Quit() - // 打开本地文件 - file, err := os.Open(localFilePath) - if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) - return - } - defer file.Close() - // 远程文件 - remotePath := filepath.Join(cfgData.Dir, path.Base(body.FilePath), body.FileName) - // 上传文件到 FTP 服务器 - err = ftpComm.Stor(remotePath, file) - if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) - return - } + connSSH := ssh.ConnSSH{ + User: cfgData.Username, + Password: cfgData.Password, + Addr: cfgData.ToIp, + Port: cfgData.ToPort, + AuthMode: "0", } - - c.JSON(200, result.Err(nil)) + sshClient, err := connSSH.NewClient() + if err != nil { + c.JSON(200, resp.ErrMsg(err.Error())) + return + } + defer sshClient.Close() + // 网元主机的SSH客户端进行文件传输 + sftpClient, err := sshClient.NewClientSFTP() + if err != nil { + c.JSON(200, resp.ErrMsg(err.Error())) + return + } + defer sftpClient.Close() + // 远程文件 + remotePath := filepath.Join(cfgData.Dir, path.Base(body.FilePath), body.FileName) + // 复制到远程 + if err = sftpClient.CopyFileLocalToRemote(localFilePath, remotePath); err != nil { + c.JSON(200, resp.ErrMsg("error uploading file")) + return + } + c.JSON(200, resp.Ok(nil)) } diff --git a/features/lm/file_export/route.go b/features/lm/file_export/route.go index eb3567c6..d0f618f5 100644 --- a/features/lm/file_export/route.go +++ b/features/lm/file_export/route.go @@ -17,10 +17,12 @@ func Register(r *gin.RouterGroup) { ) lmTable.POST("/ftp", middleware.PreAuthorize(nil), + middleware.CryptoApi(true, false), m.SetFTPConfig, ) lmTable.GET("/ftp", middleware.PreAuthorize(nil), + middleware.CryptoApi(false, true), m.GetFTPConfig, ) lmTable.PUT("/ftp", diff --git a/features/lm/logbak.go b/features/lm/logbak.go index 0efd87fd..99a36ae6 100644 --- a/features/lm/logbak.go +++ b/features/lm/logbak.go @@ -10,9 +10,9 @@ import ( "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/services" + "be.ems/src/framework/database/db" "github.com/gorilla/mux" - "xorm.io/xorm" ) type XormResponse struct { @@ -29,58 +29,12 @@ var ( CustomExtBackupDataUri = config.UriPrefix + "/dataManagement/{apiVersion}/{dataStorage}/{dataObject}/backup" // for external ) -var XEngine *xorm.Engine - -type DatabaseClient struct { - dbType string - dbUrl string - dbConnMaxLifetime time.Duration - dbMaxIdleConns int - dbMaxOpenConns int - IsShowSQL bool - - XEngine *xorm.Engine -} - -var DbClient DatabaseClient - // func init() { // conf := config.GetYamlConfig() // InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password, // conf.Database.Host, conf.Database.Port, conf.Database.Name) // } -func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error { - DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", - dbUser, dbPassword, dbHost, dbPort, dbName, dbParam) - DbClient.dbType = dbType - DbClient.dbConnMaxLifetime = 0 - DbClient.dbMaxIdleConns = 0 - DbClient.dbMaxOpenConns = 0 - if log.GetLevel() == log.LOG_TRACE { - DbClient.IsShowSQL = true - } - log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl) - - var err error - DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl) - if err != nil { - log.Error("Failed to connet database:", err) - return err - } - DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime) - DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns) - DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns) - DbClient.XEngine.DatabaseTZ = time.Local // 必须 - DbClient.XEngine.TZLocation = time.Local // 必须 - if DbClient.IsShowSQL { - DbClient.XEngine.ShowSQL(true) - } - XEngine = DbClient.XEngine - - return nil -} - func ExtDatabaseBackupData(w http.ResponseWriter, r *http.Request) { log.Debug("ExtDatabaseBackupData processing... ") @@ -126,16 +80,15 @@ func ExtDatabaseBackupData(w http.ResponseWriter, r *http.Request) { return } - res, err := DbClient.XEngine.Exec(sql) + affected, err := db.ExecDB("", sql, nil) if err != nil { log.Error("Failed to exec SQL:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return } - affected, _ := res.RowsAffected() - log.Debugf("filePath:%s backup dir:%s", filePath, config.GetYamlConfig().Database.Backup) - cmd := exec.Command("cp", "-rf", filePath, config.GetYamlConfig().Database.Backup) + log.Debugf("filePath:%s backup dir:%s", filePath, config.GetYamlConfig().OMC.Backup) + cmd := exec.Command("cp", "-rf", filePath, config.GetYamlConfig().OMC.Backup) out, err := cmd.CombinedOutput() log.Debugf("Exec output: %v", string(out)) if err != nil { diff --git a/features/mml/mml.go b/features/mml/mml.go index 6878ca71..8c1b07a5 100644 --- a/features/mml/mml.go +++ b/features/mml/mml.go @@ -16,7 +16,7 @@ import ( "be.ems/lib/log" "be.ems/lib/mmlp" "be.ems/lib/services" - tokenConst "be.ems/src/framework/constants/token" + "be.ems/src/framework/constants" neModel "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" ) @@ -83,7 +83,7 @@ func PostMML2ToNF(w http.ResponseWriter, r *http.Request) { } log.Debug("neType:", neType, "neId", neId) - neInfoArr := neService.NewNeInfo.SelectList(neModel.NeInfo{NeType: neType, NeId: neId}, false, true) + neInfoArr := neService.NewNeInfo.Find(neModel.NeInfo{NeType: neType, NeId: neId}, false, true) if len(neInfoArr) < 1 { services.ResponseInternalServerError500DatabaseOperationFailed(w) return @@ -235,7 +235,7 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) { return } - neInfoArr := neService.NewNeInfo.SelectList(neModel.NeInfo{NeType: neType, NeId: neId}, false, true) + neInfoArr := neService.NewNeInfo.Find(neModel.NeInfo{NeType: neType, NeId: neId}, false, true) if len(neInfoArr) < 1 { services.ResponseInternalServerError500DatabaseOperationFailed(w) return @@ -635,7 +635,7 @@ func PostMMLToOMC(w http.ResponseWriter, r *http.Request) { } log.Debug("neType:", neType, "neId", neId) - neInfoArr := neService.NewNeInfo.SelectList(neModel.NeInfo{NeType: neType, NeId: neId}, false, false) + neInfoArr := neService.NewNeInfo.Find(neModel.NeInfo{NeType: neType, NeId: neId}, false, false) if len(neInfoArr) < 1 { services.ResponseInternalServerError500DatabaseOperationFailed(w) return @@ -664,8 +664,8 @@ func PostMMLToOMC(w http.ResponseWriter, r *http.Request) { MmlHome: config.GetYamlConfig().MML.MmlHome, Limit: 50, User: "", - SessionToken: "", // 旧token - Authorization: r.Header.Get(tokenConst.HEADER_KEY), // 请求Token + SessionToken: "", // 旧token + Authorization: r.Header.Get(constants.HEADER_KEY), // 请求Token HttpUri: hostUri, UserAgent: config.GetDefaultUserAgent(), } diff --git a/features/pm/kpi_c_report/controller.go b/features/pm/kpi_c_report/controller.go index e1772f0e..e546217c 100644 --- a/features/pm/kpi_c_report/controller.go +++ b/features/pm/kpi_c_report/controller.go @@ -1,13 +1,15 @@ package kpi_c_report import ( + "encoding/json" "fmt" "net/http" "strconv" "strings" - "be.ems/lib/dborm" "be.ems/lib/services" + "be.ems/src/framework/database/db" + "be.ems/src/framework/utils/parse" "github.com/gin-gonic/gin" ) @@ -31,7 +33,7 @@ func (k *KpiCReport) Get(c *gin.Context) { return } tableName := TableName() + "_" + strings.ToLower(querys.NeType) - dbg := dborm.DefaultDB().Table(tableName) + dbg := db.DB("").Model(&KpiCReport{}).Table(tableName) if querys.NeID != "" { conditions = append(conditions, "rm_uid = (select n.rm_uid from ne_info n where n.ne_type=? and n.ne_id=? and n.status=1)") @@ -69,7 +71,7 @@ func (k *KpiCReport) Get(c *gin.Context) { dbg = dbg.Order(orderBy) } - //err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error + //err := db.DB("").Table(tableName).Where(whereSql, params...).Find(&reports).Error err := dbg.Find(&reports).Error if err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) @@ -98,7 +100,7 @@ func (k *KpiCReport) GetReport2FE(c *gin.Context) { return } tableName := TableName() + "_" + strings.ToLower(querys.NeType) - dbg := dborm.DefaultDB().Table(tableName) + dbg := db.DB("").Model(&KpiCReport{}).Table(tableName) if querys.NeID != "" { conditions = append(conditions, "rm_uid = (select n.rm_uid from ne_info n where n.ne_type=? and n.ne_id=? and n.status=1)") @@ -108,11 +110,11 @@ func (k *KpiCReport) GetReport2FE(c *gin.Context) { return } if querys.StartTime != "" { - conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?") + conditions = append(conditions, "created_at >= ?") params = append(params, querys.StartTime) } if querys.EndTime != "" { - conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?") + conditions = append(conditions, "created_at <= ?") params = append(params, querys.EndTime) } conditions = append(conditions, "kpi_values != 'null'") @@ -136,7 +138,7 @@ func (k *KpiCReport) GetReport2FE(c *gin.Context) { dbg = dbg.Order(orderBy) } - //err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error + //err := db.DB("").Table(tableName).Where(whereSql, params...).Find(&reports).Error err := dbg.Find(&results).Error if err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) @@ -156,14 +158,24 @@ func (k *KpiCReport) GetReport2FE(c *gin.Context) { "createdAt": r.CreatedAt, "granularity": r.Granularity, } + // 解析 JSON 字符串为 map + var kpiValues []map[string]any + err := json.Unmarshal([]byte(r.KpiValues), &kpiValues) + if err != nil { + continue + } - for _, k := range r.KpiValues { - formatted := fmt.Sprintf("%.3f", k.Value) + // 遍历 kpiValues 数组 + for _, k := range kpiValues { + kpiId := fmt.Sprint(k["kpiId"]) + value := parse.Number(k["value"]) + + formatted := fmt.Sprintf("%.3d", value) formattedFloat, err := strconv.ParseFloat(formatted, 64) if err != nil { formattedFloat = 0 } - report[k.KPIID] = formattedFloat + report[kpiId] = formattedFloat } reports = append(reports, report) } @@ -190,14 +202,14 @@ func (k *KpiCReport) GetTotalList(c *gin.Context) { return } tableName := TableName() + "_" + strings.ToLower(querys.NeType) - dbg := dborm.DefaultDB().Table(tableName) + dbg := db.DB("").Model(&KpiCReport{}).Table(tableName) if querys.StartTime != "" { - conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?") + conditions = append(conditions, "created_at >= ?") params = append(params, querys.StartTime) } if querys.EndTime != "" { - conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?") + conditions = append(conditions, "created_at <= ?") params = append(params, querys.EndTime) } conditions = append(conditions, "kpi_values != 'null'") @@ -230,7 +242,7 @@ func (k *KpiCReport) GetTotalList(c *gin.Context) { dbg = dbg.Order(orderBy) } - //err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error + //err := db.DB("").Table(tableName).Where(whereSql, params...).Find(&reports).Error err = dbg.Find(&reports).Error if err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) @@ -259,8 +271,7 @@ func (k *KpiCReport) Total(c *gin.Context) { return } tableName := TableName() + "_" + strings.ToLower(querys.NeType) - dbg := dborm.DefaultDB().Table(tableName) - + dbg := db.DB("").Model(&KpiCReport{}).Table(tableName) if querys.StartTime != "" { conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?") params = append(params, querys.StartTime) @@ -293,7 +304,8 @@ func (k *KpiCReport) Post(c *gin.Context) { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } - if err := dborm.DefaultDB().Create(&report).Error; err != nil { + dbg := db.DB("").Model(&KpiCReport{}) + if err := dbg.Create(&report).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } @@ -303,8 +315,8 @@ func (k *KpiCReport) Post(c *gin.Context) { func (k *KpiCReport) Put(c *gin.Context) { var report KpiCReport id := c.Param("id") - - if err := dborm.DefaultDB().First(&report, id).Error; err != nil { + dbg := db.DB("").Model(&KpiCReport{}) + if err := dbg.First(&report, id).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp("custom indicator report not found")) return } @@ -313,14 +325,14 @@ func (k *KpiCReport) Put(c *gin.Context) { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } - dborm.DefaultDB().Save(&report) + db.DB("").Model(&KpiCReport{}).Save(&report) c.JSON(http.StatusOK, services.DataResp(report)) } func (k *KpiCReport) Delete(c *gin.Context) { id := c.Param("id") - if err := dborm.DefaultDB().Delete(&KpiCReport{}, id).Error; err != nil { + if err := db.DB("").Delete(&KpiCReport{}, id).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp("custom indicator report not found")) return } @@ -330,7 +342,8 @@ func (k *KpiCReport) Delete(c *gin.Context) { func InsertKpiCReport(neType string, report KpiCReport) { tableName := TableName() + "_" + strings.ToLower(neType) - if err := dborm.DefaultDB().Table(tableName).Create(&report).Error; err != nil { + dbg := db.DB("").Model(&KpiCReport{}) + if err := dbg.Table(tableName).Create(&report).Error; err != nil { return } } diff --git a/features/pm/kpi_c_report/model.go b/features/pm/kpi_c_report/model.go index b96b7f01..82a3c505 100644 --- a/features/pm/kpi_c_report/model.go +++ b/features/pm/kpi_c_report/model.go @@ -1,32 +1,17 @@ package kpi_c_report -import ( - "database/sql/driver" - "encoding/json" - "fmt" - "time" -) - -type KpiCVal struct { - KPIID string `json:"kpi_id" gorm:"column:kpi_id"` - Value float64 `json:"value" gorm:"column:value"` - Err string `json:"err" gorm:"column:err"` -} - -type KpiCValues []KpiCVal - type KpiCReport struct { - ID int `gorm:"column:id;primary_key;auto_increment" json:"id"` - NeType *string `gorm:"column:ne_type;default:NULL" json:"neType,omitempty"` - NeName *string `gorm:"column:ne_name;default:" json:"neName,omitempty"` - RmUID *string `gorm:"column:rm_uid;default:NULL" json:"rmUid,omitempty"` - Date string `gorm:"column:date" json:"date"` // time.Time `gorm:"column:date" json:"date"` - StartTime *string `gorm:"column:start_time;default:NULL" json:"startTime,omitempty"` - EndTime *string `gorm:"column:end_time;default:NULL" json:"endTime,omitempty"` - Index int16 `gorm:"column:index" json:"index"` - Granularity *int8 `gorm:"column:granularity;default:60" json:"granularity,omitempty"` //Time granualarity: 5/10/.../60/300 (second) - KpiValues KpiCValues `gorm:"column:kpi_values;type:json" json:"kpiValues,omitempty"` - CreatedAt *time.Time `gorm:"column:created_at;default:current_timestamp()" json:"createdAt,omitempty"` + ID int `gorm:"column:id;primary_key;auto_increment" json:"id"` + NeType *string `gorm:"column:ne_type;default:NULL" json:"neType,omitempty"` + NeName *string `gorm:"column:ne_name;default:" json:"neName,omitempty"` + RmUID *string `gorm:"column:rm_uid;" json:"rmUid,omitempty"` + Date string `gorm:"column:date" json:"date"` // time.Time `gorm:"column:date" json:"date"` + StartTime *string `gorm:"column:start_time" json:"startTime,omitempty"` + EndTime *string `gorm:"column:end_time" json:"endTime,omitempty"` + Index int64 `gorm:"column:index" json:"index"` + Granularity *int64 `gorm:"column:granularity" json:"granularity,omitempty"` //Time granualarity: 5/10/.../60/300 (second) + KpiValues string `gorm:"column:kpi_values" json:"kpiValues,omitempty"` + CreatedAt *int64 `gorm:"column:created_at" json:"createdAt,omitempty"` } type KpiCReportQuery struct { @@ -55,17 +40,3 @@ type KpiCReport2FE struct { func TableName() string { return "kpi_c_report" } - -// 将 KpiCValues 转换为 JSON 字节 -func (k KpiCValues) Value() (driver.Value, error) { - return json.Marshal(k) -} - -// 从字节中扫描 KpiCValues -func (k *KpiCValues) Scan(value interface{}) error { - b, ok := value.([]byte) - if !ok { - return fmt.Errorf("failed to scan value: %v", value) - } - return json.Unmarshal(b, k) -} diff --git a/features/pm/kpi_c_title/controller.go b/features/pm/kpi_c_title/controller.go index 55420ef6..50c2b685 100644 --- a/features/pm/kpi_c_title/controller.go +++ b/features/pm/kpi_c_title/controller.go @@ -4,13 +4,16 @@ import ( "fmt" "net/http" "regexp" + "sort" "strconv" "strings" + "time" - "be.ems/lib/dborm" "be.ems/lib/log" "be.ems/lib/services" - "be.ems/src/framework/utils/ctx" + "be.ems/src/framework/database/db" + "be.ems/src/framework/reqctx" + "github.com/gin-gonic/gin" ) @@ -19,7 +22,7 @@ func (k *KpiCTitle) GetToalList(c *gin.Context) { var titles []KpiCTitle var conditions []string var params []any - i18n := ctx.AcceptLanguage(c) + i18n := reqctx.AcceptLanguage(c) var querys KpiCTitleQuery if err := c.ShouldBindQuery(&querys); err != nil { @@ -27,7 +30,7 @@ func (k *KpiCTitle) GetToalList(c *gin.Context) { return } - dbg := dborm.DefaultDB().Table(k.TableName()) + dbg := db.DB("").Model(&KpiCTitle{}) // construct condition to get if neType := querys.NeType; neType != "" { conditions = append(conditions, "ne_type = ?") @@ -37,7 +40,7 @@ func (k *KpiCTitle) GetToalList(c *gin.Context) { conditions = append(conditions, "status = ?") params = append(params, status) } else { - conditions = append(conditions, "status != 'Deleted'") + conditions = append(conditions, "status != '2'") } whereSql := "" @@ -81,7 +84,7 @@ func (k *KpiCTitle) Get(c *gin.Context) { var titles []KpiCTitle var conditions []string var params []any - i18n := ctx.AcceptLanguage(c) + i18n := reqctx.AcceptLanguage(c) // construct condition to get if neType := c.Query("neType"); neType != "" { @@ -92,14 +95,14 @@ func (k *KpiCTitle) Get(c *gin.Context) { conditions = append(conditions, "status = ?") params = append(params, status) } else { - conditions = append(conditions, "status != 'Deleted'") + conditions = append(conditions, "status != '2'") } whereSql := "" if len(conditions) > 0 { whereSql += strings.Join(conditions, " and ") } - if err := dborm.DefaultDB().Where(whereSql, params...).Find(&titles).Error; err != nil { + if err := db.DB("").Where(whereSql, params...).Find(&titles).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } @@ -126,11 +129,18 @@ func (k *KpiCTitle) expressionAlias(titles []KpiCTitle, i18n string) { } else { sql = fmt.Sprintf("SELECT en_title FROM kpi_title WHERE kpi_id='%s'", match[1]) } - err := dborm.XCoreDB().QueryRow(sql).Scan(&alias) + m, err := db.RawDB("", sql, nil) if err != nil { log.Warn("Failed to QueryRow:", err) continue } + if len(m) > 0 { + if i18n == "zh" { + alias = fmt.Sprintf("%v", m[0]["cn_title"]) + } else { + alias = fmt.Sprintf("%v", m[0]["en_title"]) + } + } title.ExprAlias = regexp.MustCompile(match[1]).ReplaceAllString(title.ExprAlias, alias) } } @@ -149,7 +159,7 @@ func (k *KpiCTitle) Total(c *gin.Context) { conditions = append(conditions, "status = ?") params = append(params, status) } else { - conditions = append(conditions, "status != 'Deleted'") + conditions = append(conditions, "status != '2'") } whereSql := "" @@ -157,7 +167,7 @@ func (k *KpiCTitle) Total(c *gin.Context) { whereSql += strings.Join(conditions, " and ") } var total int64 = 0 - if err := dborm.DefaultDB().Table(k.TableName()).Where(whereSql, params...).Count(&total).Error; err != nil { + if err := db.DB("").Table(k.TableName()).Where(whereSql, params...).Count(&total).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } @@ -166,31 +176,56 @@ func (k *KpiCTitle) Total(c *gin.Context) { } func (k *KpiCTitle) Post(c *gin.Context) { - var title, res KpiCTitle - + var title KpiCTitle if err := c.ShouldBindJSON(&title); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } - userName := ctx.LoginUserToUserName(c) + userName := reqctx.LoginUserToUserName(c) title.CreatedBy = &userName - result := dborm.DefaultDB().Where("ne_type=? and (kpi_id=? or title=?) and status!='Deleted'", title.NeType, title.KpiID, title.Title).First(&title) + tx := db.DB("").Model(&KpiCTitle{}) + result := tx.Where("ne_type=? and (kpi_id=? or title=?) and status!='2'", title.NeType, title.KpiID, title.Title).First(&title) if result.RowsAffected > 0 { c.JSON(http.StatusOK, services.ErrResp("custom indicator already exist")) return } // Regexp match like AMF.C.01 - kpiIDRegexp := "^" + *title.NeType + "\\.C\\.[0-9]{2}$" - ret := dborm.DefaultDB().Table("kpi_c_title"). - Where("ne_type=? and kpi_id REGEXP ? ORDER BY kpi_id DESC LIMIT 1", title.NeType, kpiIDRegexp).Scan(&res) - if err := ret.Error; err != nil { - c.JSON(http.StatusOK, services.ErrResp(err.Error())) - return - } + // kpiIDRegexp := "^" + *title.NeType + "\\.C\\.[0-9]{2}$" + // ret := db.DB("").Table("kpi_c_title"). + // Where("ne_type=? and kpi_id REGEXP ? ORDER BY kpi_id DESC LIMIT 1", title.NeType, kpiIDRegexp).Scan(&res) + // if err := ret.Error; err != nil { + // c.JSON(http.StatusOK, services.ErrResp(err.Error())) + // return + // } + + titles := []KpiCTitle{} + ret := db.DB("").Model(&KpiCTitle{}) + ret = ret.Select("kpi_id").Where("ne_type=?", title.NeType).Find(&titles) + newKpiID := *title.NeType + ".C" + ".01" if ret.RowsAffected != 0 { - maxKpiID := *res.KpiID + suffixInt := 1 + prefixStr := fmt.Sprintf("%s.C.", *title.NeType) + sort.SliceStable(titles, func(i, j int) bool { + vi := *titles[i].KpiID + vj := *titles[j].KpiID + if strings.HasPrefix(vi, prefixStr) && strings.HasPrefix(vj, prefixStr) { + vvi := strings.Replace(vi, prefixStr, "", 1) + vvii, err := strconv.Atoi(vvi) + if err != nil { + return false + } + vvj := strings.Replace(vj, prefixStr, "", 1) + vvjj, err := strconv.Atoi(vvj) + if err != nil { + return false + } + return vvii > vvjj // desc + } + return false + }) + maxKpiID := *titles[0].KpiID prefix := maxKpiID[:len(maxKpiID)-2] suffix := maxKpiID[len(maxKpiID)-2:] suffixInt, err := strconv.Atoi(suffix) @@ -209,25 +244,26 @@ func (k *KpiCTitle) Post(c *gin.Context) { newKpiID = prefix + newSuffix } title.KpiID = &newKpiID - if err := dborm.DefaultDB().Create(&title).Error; err != nil { + txx := db.DB("").Model(&KpiCTitle{}) + if err := txx.Create(&title).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } kpiCReportTable := "kpi_c_report_" + strings.ToLower(*title.NeType) - if !dborm.DefaultDB().Migrator().HasTable(kpiCReportTable) { + if !db.DB("").Migrator().HasTable(kpiCReportTable) { // clone table "kpi_c_report" to "kpi_c_report_{neType}" sql := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s AS SELECT * FROM %s WHERE 1=0", kpiCReportTable, "kpi_c_report") - if _, err := dborm.ExecSQL(sql, nil); err != nil { + if _, err := db.ExecDB("", sql, nil); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } sql = fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,ADD PRIMARY KEY IF NOT EXISTS (`id`)", kpiCReportTable) - if _, err := dborm.ExecSQL(sql, nil); err != nil { + if _, err := db.ExecDB("", sql, nil); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } sql = fmt.Sprintf("ALTER TABLE %s ADD INDEX IF NOT EXISTS `idx_timestamp`(`created_at`) USING BTREE, ADD INDEX IF NOT EXISTS `idx_uid_datetime`(`rm_uid`, `date`, `start_time`) USING BTREE", kpiCReportTable) - if _, err := dborm.ExecSQL(sql, nil); err != nil { + if _, err := db.ExecDB("", sql, nil); err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } @@ -239,7 +275,7 @@ func (k *KpiCTitle) Put(c *gin.Context) { var title KpiCTitle id := c.Param("id") - if err := dborm.DefaultDB().First(&title, id).Error; err != nil { + if err := db.DB("").First(&title, id).Error; err != nil { c.JSON(http.StatusOK, services.ErrResp("custom indicator not found")) return } @@ -248,7 +284,8 @@ func (k *KpiCTitle) Put(c *gin.Context) { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } - dborm.DefaultDB().Save(&title) + title.UpdatedAt = time.Now().UnixMilli() + db.DB("").Save(&title) c.JSON(http.StatusOK, services.DataResp(title)) } @@ -256,7 +293,7 @@ func (k *KpiCTitle) Put(c *gin.Context) { func (k *KpiCTitle) Delete(c *gin.Context) { id := c.Param("id") - if err := dborm.DefaultDB().Table(k.TableName()).Where("id=?", id).Update("status", "Deleted").Error; err != nil { + if err := db.DB("").Table(k.TableName()).Where("id=?", id).Update("status", "2").Error; err != nil { c.JSON(http.StatusOK, services.ErrResp(err.Error())) return } @@ -267,7 +304,7 @@ func (k *KpiCTitle) Delete(c *gin.Context) { func GetActiveKPICList(neType string) []KpiCTitle { k := new([]KpiCTitle) - err := dborm.DefaultDB().Where("`ne_type` = ? and `status` = 'Active'", neType).Find(&k).Error + err := db.DB("").Where("`ne_type` = ? and `status` = '1'", neType).Find(&k).Error if err != nil { return nil } diff --git a/features/pm/kpi_c_title/model.go b/features/pm/kpi_c_title/model.go index cdc2b5cc..05170c4b 100644 --- a/features/pm/kpi_c_title/model.go +++ b/features/pm/kpi_c_title/model.go @@ -1,23 +1,21 @@ package kpi_c_title -import "time" - const ( MAX_KPI_C_ID = 99 ) type KpiCTitle struct { - ID int `gorm:"column:id;primary_key;auto_increment" json:"id"` - NeType *string `gorm:"column:ne_type;default:NULL," json:"neType,omitempty"` - KpiID *string `gorm:"column:kpi_id;default:NULL," json:"kpiId,omitempty"` - Title *string `gorm:"column:title;default:NULL," json:"title,omitempty"` - Expression *string `gorm:"column:expression;default:NULL," json:"expression,omitempty"` - ExprAlias string `gorm:"-" json:"exprAlias"` - Status string `gorm:"column:status;default:'Active'" json:"status"` - Unit *string `gorm:"column:unit" json:"unit,omitempty"` - Description *string `gorm:"column:description;default:NULL," json:"description,omitempty"` - CreatedBy *string `gorm:"column:created_by;default:NULL," json:"createdBy,omitempty"` - UpdatedAt *time.Time `gorm:"column:updated_at;default:current_timestamp()," json:"updatedAt,omitempty"` + ID int `gorm:"column:id;primary_key;auto_increment" json:"id"` + NeType *string `gorm:"column:ne_type" json:"neType,omitempty"` + KpiID *string `gorm:"column:kpi_id" json:"kpiId,omitempty"` + Title *string `gorm:"column:title" json:"title,omitempty"` + Expression *string `gorm:"column:expression" json:"expression,omitempty"` + ExprAlias string `gorm:"-" json:"exprAlias"` + Status string `gorm:"column:status" json:"status"` // 0-Inactive/1-Active/2-Deleted + Unit *string `gorm:"column:unit" json:"unit,omitempty"` + Description *string `gorm:"column:description" json:"description,omitempty"` + CreatedBy *string `gorm:"column:created_by" json:"createdBy,omitempty"` + UpdatedAt int64 `gorm:"column:updated_at" json:"updatedAt,omitempty"` } type KpiCTitleQuery struct { diff --git a/features/pm/performance.go b/features/pm/performance.go index 9dc4b9dd..bd690c0e 100644 --- a/features/pm/performance.go +++ b/features/pm/performance.go @@ -13,18 +13,22 @@ import ( "be.ems/features/pm/kpi_c_report" "be.ems/features/pm/kpi_c_title" "be.ems/lib/config" + "be.ems/lib/core/ctx" "be.ems/lib/dborm" evaluate "be.ems/lib/eval" "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/services" - + "be.ems/src/framework/database/db" + "be.ems/src/framework/utils/date" + "be.ems/src/framework/utils/parse" + neDataModel "be.ems/src/modules/network_data/model" + neDataService "be.ems/src/modules/network_data/service" neService "be.ems/src/modules/network_element/service" wsService "be.ems/src/modules/ws/service" + "github.com/go-resty/resty/v2" - _ "github.com/go-sql-driver/mysql" "github.com/gorilla/mux" - "xorm.io/xorm" ) type Response struct { @@ -76,7 +80,7 @@ type KpiData struct { StartTime string `json:"startTime" xorm:"start_time"` EndTime string `json:"endTime" xorm:"end_time"` Index int `json:"index" xorm:"index"` - Granularity int8 `json:"granularity" xorm:"granularity"` + Granularity int64 `json:"granularity" xorm:"granularity"` KPIValues []KPIVal `json:"kpiValues" xorm:"json 'kpi_values'"` //CreatedAt int64 `json:"createdAt" xorm:"created 'created_at'"` CreatedAt int64 `json:"createdAt" xorm:"'created_at'"` @@ -105,84 +109,6 @@ var ( CustomUriMeasureTask = config.UriPrefix + "/performanceManagement/{apiVersion}/measureTask/{netype}" ) -var xEngine *xorm.Engine - -type DatabaseClient struct { - dbType string - dbUrl string - dbConnMaxLifetime time.Duration - dbMaxIdleConns int - dbMaxOpenConns int - IsShowSQL bool - - XEngine *xorm.Engine -} - -var DbClient DatabaseClient - -func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error { - DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", - dbUser, dbPassword, dbHost, dbPort, dbName, dbParam) - DbClient.dbType = dbType - DbClient.dbConnMaxLifetime = 0 - DbClient.dbMaxIdleConns = 0 - DbClient.dbMaxOpenConns = 0 - if log.GetLevel() == log.LOG_TRACE { - DbClient.IsShowSQL = true - } - log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl) - - var err error - DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl) - if err != nil { - log.Error("Failed to connet database:", err) - return err - } - DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime) - DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns) - DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns) - DbClient.XEngine.DatabaseTZ = time.Local // 必须 - DbClient.XEngine.TZLocation = time.Local // 必须 - if DbClient.IsShowSQL { - DbClient.XEngine.ShowSQL(true) - } - xEngine = DbClient.XEngine - - // exist, err := xEngine.IsTableExist("kpi_report") - // if err != nil { - // log.Error("Failed to IsTableExist:", err) - // return err - // } - // if exist { - // // 复制表结构到新表 - // sql := fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` AS SELECT * FROM kpi_report WHERE 1=0", "kpi_report_amf") - // _, err := xEngine.Exec(sql) - // if err != nil { - // log.Error("Failed to Exec:", err) - // return err - // } - // } - - return nil -} - -func XormConnectDatabase(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) (*xorm.Engine, error) { - sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local", - dbUser, dbPassword, dbHost, dbPort, dbName) - log.Debugf("dbType:%s Connect to:%s:******@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local", - dbType, dbUser, dbHost, dbPort, dbName) - var err error - xEngine, err = xorm.NewEngine(dbType, sqlStr) //1、Create xorm engine - if err != nil { - log.Error("Failed to connect database:", err) - return nil, err - } - if log.GetLevel() == log.LOG_TRACE { - xEngine.ShowSQL(true) - } - return xEngine, nil -} - func GetDateFromTimeString(fmtString string, timeString string) string { t, _ := time.ParseInLocation(fmtString, timeString, time.Local) return t.Format("2006-01-02") @@ -197,6 +123,167 @@ func GetDateTimeFromTimeString(fmtString string, timeString string) string { func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) { log.Debug("PostKPIReportFromNF processing... ") + apiVer := ctx.GetParam(r, "apiVersion") + if apiVer != global.ApiVersionV1 { + log.Error("Uri api version is invalid. apiVersion:", apiVer) + services.ResponseNotFound404UriNotExist(w, r) + return + } + + var kpiReport KpiReport + if err := ctx.ShouldBindJSON(r, &kpiReport); err != nil { + services.ResponseInternalServerError500ProcessError(w, err) + return + } + + kpiIndexStr := ctx.GetParam(r, "index") + + // insert kpi_report table, no session + saveKPIData(kpiReport, parse.Number(kpiIndexStr)) + saveKPIDataC(kpiReport, parse.Number(kpiIndexStr)) + + services.ResponseStatusOK204NoContent(w) +} + +// saveKPIData 存储KPI数据并推送到ws订阅组 +func saveKPIData(kpiReport KpiReport, index int64) int64 { + timestamp := kpiReport.Timestamp + taskPeriod := kpiReport.Task.Period + taskNe := kpiReport.Task.NE + taskNeKPIs := kpiReport.Task.NE.KPIs + // 时间数据处理 + receiverTime := date.ParseStrToDate(timestamp, date.YYYY_MM_DDTHH_MM_SSZ) + startTime := date.ParseStrToDate(taskPeriod.StartTime, date.YYYY_MM_DDTHH_MM_SSZ) + endTime := date.ParseStrToDate(taskPeriod.EndTime, date.YYYY_MM_DDTHH_MM_SSZ) + granularity := parse.Number(endTime.Sub(startTime).Seconds()) + // kpi data数据json + KpiValues := make([]map[string]any, 0) + for _, v := range taskNeKPIs { + KpiValues = append(KpiValues, map[string]any{ + "kpiId": v.KPIID, + "value": v.Value, + "err": v.Err, + }) + } + KpiValuesByte, _ := json.Marshal(KpiValues) + kpiData := neDataModel.KpiReport{ + NeType: taskNe.NeType, + NeName: taskNe.NEName, + RmUid: taskNe.RmUID, + Date: date.ParseDateToStr(receiverTime, "2006-01-02"), + StartTime: date.ParseDateToStr(startTime, "15:04:05"), + EndTime: date.ParseDateToStr(endTime, "15:04:05"), + Index: index, + Granularity: granularity, + KpiValues: string(KpiValuesByte), + CreatedAt: receiverTime.UnixMilli(), // 时间戳毫秒实际记录到秒 + } + insertId := neDataService.NewKpiReport.Insert(kpiData) + if insertId > 0 { + // 指标事件对象 + kpiEvent := map[string]any{ + "neType": kpiData.NeType, + "neName": kpiData.NeName, + "rmUID": kpiData.RmUid, + "startIndex": kpiData.Index, + "timeGroup": kpiData.CreatedAt, + // kip_id ... + } + for _, v := range taskNeKPIs { + kpiEvent[v.KPIID] = v.Value + } + + // 发送到匹配的网元 + neInfo := neService.NewNeInfo.FindByRmuid(kpiData.RmUid) + if neInfo.RmUID == kpiData.RmUid { + // 推送到ws订阅组 + wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%s_%s", wsService.GROUP_KPI, neInfo.NeType, neInfo.NeId), kpiEvent) + if neInfo.NeType == "UPF" { + wsService.NewWSSend.ByGroupID(wsService.GROUP_KPI_UPF+neInfo.NeId, kpiEvent) + } + } + } + return insertId +} + +// saveKPIDataC 存储自定义KPI数据并推送到ws订阅组 +func saveKPIDataC(kpiReport KpiReport, index int64) int64 { + timestamp := kpiReport.Timestamp + taskPeriod := kpiReport.Task.Period + taskNe := kpiReport.Task.NE + taskNeKPIs := kpiReport.Task.NE.KPIs + // 时间数据处理 + receiverTime := date.ParseStrToDate(timestamp, date.YYYY_MM_DDTHH_MM_SSZ) + startTime := date.ParseStrToDate(taskPeriod.StartTime, date.YYYY_MM_DDTHH_MM_SSZ) + endTime := date.ParseStrToDate(taskPeriod.EndTime, date.YYYY_MM_DDTHH_MM_SSZ) + granularity := parse.Number(endTime.Sub(startTime).Seconds()) + // kpi data数据 + KpiValues := make([]map[string]any, 0) + kpiValMap := map[string]any{} + for _, v := range taskNeKPIs { + kpiValMap[v.KPIID] = v.Value + } + // 自定义kpiId数据 + cTitles := kpi_c_title.GetActiveKPICList(taskNe.NeType) + for _, v := range cTitles { + item := map[string]any{ + "kpiId": *v.KpiID, + "value": 0, + "err": "", + } + // 计算结果 + result, err := evaluate.CalcExpr(*v.Expression, kpiValMap) + if err != nil { + item["value"] = 0 + item["err"] = err.Error() + } else { + item["value"] = result + } + KpiValues = append(KpiValues, item) + } + + KpiValuesByte, _ := json.Marshal(KpiValues) + kpiData := neDataModel.KpiCReport{ + NeType: taskNe.NeType, + NeName: taskNe.NEName, + RmUid: taskNe.RmUID, + Date: date.ParseDateToStr(receiverTime, "2006-01-02"), + StartTime: date.ParseDateToStr(startTime, "15:04:05"), + EndTime: date.ParseDateToStr(endTime, "15:04:05"), + Index: index, + Granularity: granularity, + KpiValues: string(KpiValuesByte), + CreatedAt: receiverTime.UnixMilli(), // 时间戳毫秒实际记录到秒 + } + insertId := neDataService.NewKpiCReport.Insert(kpiData) + if insertId > 0 { + // 指标事件对象 + kpiEvent := map[string]any{ + "neType": kpiData.NeType, + "neName": kpiData.NeName, + "rmUID": kpiData.RmUid, + "startIndex": kpiData.Index, + "timeGroup": kpiData.CreatedAt, + // kip_id ... + } + for _, v := range KpiValues { + kpiEvent[fmt.Sprint(v["kpiId"])] = v["value"] + } + + // 发送到匹配的网元 + neInfo := neService.NewNeInfo.FindByRmuid(kpiData.RmUid) + if neInfo.RmUID == kpiData.RmUid { + // 推送自定义KPI到ws订阅组 + wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%s_%s", wsService.GROUP_KPI_C, neInfo.NeType, neInfo.NeId), kpiEvent) + } + } + return insertId +} + +// process KPI report post message from NFs 旧版 +func PostKPIReportFromNFOld(w http.ResponseWriter, r *http.Request) { + log.Debug("PostKPIReportFromNF processing... ") + vars := mux.Vars(r) apiVer := vars["apiVersion"] if apiVer != global.ApiVersionV1 { @@ -224,9 +311,9 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) { endTime := global.GetFmtTimeString(layout, kpiReport.Task.Period.EndTime, time.DateTime) // get time granularity from startTime and endTime seconds, _ := global.GetSecondDuration(startTime, endTime) - var granularity int8 = 60 + var granularity int64 = 60 if seconds != 0 && seconds <= math.MaxInt8 && seconds >= math.MinInt8 { - granularity = int8(seconds) + granularity = int64(seconds) } // insert into new kpi_report_xxx table @@ -269,8 +356,9 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) { // insert kpi_report table, no session tableName := "kpi_report_" + strings.ToLower(kpiReport.Task.NE.NeType) - affected, err := xEngine.Table(tableName).Insert(kpiData) - if err != nil && affected <= 0 { + // affected, err := xEngine.Table(tableName).Insert(kpiData) + tx := db.DB("").Table(tableName).Create(kpiData) + if tx.Error != nil && tx.RowsAffected <= 0 { log.Errorf("Failed to insert %s:%v", tableName, err) services.ResponseInternalServerError500ProcessError(w, err) return @@ -283,12 +371,12 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) { Date: kpiData.Date, StartTime: &kpiData.StartTime, EndTime: &kpiData.EndTime, - Index: int16(kpiData.Index), + Index: int64(kpiData.Index), Granularity: &kpiData.Granularity, } // 发送到匹配的网元 - neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(kpiData.RmUid) + neInfo := neService.NewNeInfo.FindByRmuid(kpiData.RmUid) // custom kpi report to FE kpiCEvent := map[string]any{ // kip_id ... @@ -301,23 +389,23 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) { "createdAt": kpiData.CreatedAt, "granularity": kpiData.Granularity, } - kpiCList := kpi_c_title.GetActiveKPICList(kpiData.NEType) - for _, k := range kpiCList { - result, err := evaluate.CalcExpr(*k.Expression, kpiValMap) - kpiCVal := new(kpi_c_report.KpiCVal) - kpiCVal.KPIID = *k.KpiID - if err != nil { - kpiCVal.Value = 0.0 - kpiCVal.Err = err.Error() - } else { - kpiCVal.Value = result - } + // kpiCList := kpi_c_title.GetActiveKPICList(kpiData.NEType) + // for _, k := range kpiCList { + // result, err := evaluate.CalcExpr(*k.Expression, kpiValMap) + // kpiCVal := new(kpi_c_report.KpiCVal) + // kpiCVal.KPIID = *k.KpiID + // if err != nil { + // kpiCVal.Value = 0.0 + // kpiCVal.Err = err.Error() + // } else { + // kpiCVal.Value = result + // } - report.KpiValues = append(report.KpiValues, *kpiCVal) + // report.KpiValues = append(report.KpiValues, *kpiCVal) - // set KPIC event kpiid and value - kpiCEvent[kpiCVal.KPIID] = kpiCVal.Value - } + // // set KPIC event kpiid and value + // kpiCEvent[kpiCVal.KPIID] = kpiCVal.Value + // } // KPI自定义指标入库 kpi_c_report.InsertKpiCReport(kpiData.NEType, report) @@ -335,11 +423,19 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) { services.ResponseStatusOK204NoContent(w) } -type MeasureTask struct { - Tasks []Task `json:"Tasks"` - NotifyUrl string `json:"NotifyUrl"` /* "http://xEngine.xEngine.xEngine.x:xxxx/api/rest/performanceManagement/v1/elementType/smf/objectType/measureReport */ +// type MeasureTask struct { +// Tasks []Task `json:"Tasks"` +// NotifyUrl string `json:"NotifyUrl"` /* "http://xEngine.xEngine.xEngine.x:xxxx/api/rest/performanceManagement/v1/elementType/smf/objectType/measureReport */ +// } +type ScheduleJ struct { + Type string `json:"Type"` + Days []int `json:"Days"` } +type Period struct { + Start string `json:"Start"` + End string `json:"End"` +} type Task struct { Id int `json:"Id"` @@ -347,9 +443,9 @@ type Task struct { EndTime string `json:"EndTime"` Schedule struct { - Type string `json:"Type"` // 计划类型:Weekly/Monthly, 如果type为"", 则任务以StartTime和EndTime为条件进行统计, 否则以Shedule方式进行 - Days []int `json:"Days"` // Weekly: [0,1,...,5,6] 星期日为0, Monthly: [1,2,3,...,30,31] - Periods []dborm.Period `json:"Periods"` + Type string `json:"Type"` // 计划类型:Weekly/Monthly, 如果type为"", 则任务以StartTime和EndTime为条件进行统计, 否则以Shedule方式进行 + Days []int `json:"Days"` // Weekly: [0,1,...,5,6] 星期日为0, Monthly: [1,2,3,...,30,31] + Periods []Period `json:"Periods"` /* Periods []struct { Start string `json:"Start"` // 零点或者零点加测量粒度的整数倍 @@ -358,8 +454,8 @@ type Task struct { */ } `json:"Schedule"` - GranulOption string `json:"GranulOption"` // 测量粒度选项:15M/30M/60M/24H - KPISet []dborm.KpiSetJ `json:"KPISet"` + GranulOption string `json:"GranulOption"` // 测量粒度选项:15M/30M/60M/24H + KPISet []KpiSetJ `json:"KPISet"` /* KPISet []struct { Code string `json:"Code"` // 统计编码 如:SMFHA01 @@ -367,7 +463,31 @@ type Task struct { } `json:"KPISet"` */ } +type KpiSetJ struct { + Code string `json:"Code"` // 统计编码 如:SMFHA01 + KPIs []string `json:"KPIs` // 指标项集合 ["SMF.AttCreatePduSession", "SMF.AttCreatePduSession._Dnn"] +} +type MeasureTask struct { + Id int `json:"id" xorm:"pk 'id' autoincr"` + NeType string `json:"neType" xorm:"ne_type"` + NeIds []string `json:"neIds" xorm:"ne_ids"` + KpiSet []KpiSetJ `json:"KPISet" xorm:"kpi_set"` + StartTime string `json:"startTime" xorm:"start_time"` + EndTime string `json:"endTime" xorm:"end_time"` + Periods []Period `json:"Periods" xorm:"periods` + Schedule []ScheduleJ `json:"Schedule" xorm:"schedule"` + GranulOption string `json:"granulOption" xorm:"granul_option"` + Status string `json:"status" xorm:"status"` + AccountID string `json:"accountId" xorm:"account_id"` + Comment string `json:"comment" xorm:"comment"` + CreateTime string `json:"createTime" xorm:"create_time"` + UpdateTime string `json:"updateTime" xorm:"update_time"` + DeleteTime string `json:"deleteTime xorm:"delete_time"` + + Tasks []Task `json:"Tasks"` + NotifyUrl string `json:"NotifyUrl"` /* "http://xEngine.xEngine.xEngine.x:xxxx/api/rest/performanceManagement/v1/elementType/smf/objectType/measureReport */ +} type MeasureReport struct { Id int `json:"Id"` TimeStamp string `json:"TimeStamp"` @@ -394,6 +514,33 @@ type MeasureReport struct { } `json:"Report"` } +func GetMeasureTask(taskId int) (*MeasureTask, error) { + log.Debug("GetMeasureTask processing... ") + + measureTask := new(MeasureTask) + tx := db.DB("").Table("measure_task").Where("id=?", taskId).Find(measureTask) + if tx.Error != nil { + log.Error("Failed to get table measure_task from database:", tx.Error) + + return nil, tx.Error + } + + log.Debug("Measure Task:", measureTask) + return measureTask, nil +} + +func XormGetActiveMeasureTask(measureTasks *[]MeasureTask) (*[]MeasureTask, error) { + log.Debug("XormGetActiveMeasureTask processing... ") + tx := db.DB("").Table("measure_task").Where("status='Active'").Find(measureTasks) + if tx.Error != nil { + log.Error("Failed to get table measure_task:", tx.Error) + return nil, tx.Error + } + + log.Debug("measureTasks:", measureTasks) + return measureTasks, nil +} + type MeasureData struct { // Id int `json:"id" xorm:"pk 'id' autoincr"` Id int `json:"id" xorm:"-"` @@ -438,8 +585,6 @@ func PostMeasureReportFromNF(w http.ResponseWriter, r *http.Request) { _ = json.Unmarshal(body, &measureReport) log.Debug("measureReport:", measureReport) - session := xEngine.NewSession() - defer session.Close() measureData := new(MeasureData) layout := global.DateTime measureData.Date = GetDateFromTimeString(layout, measureReport.Report.Period.StartTime) @@ -469,8 +614,8 @@ func PostMeasureReportFromNF(w http.ResponseWriter, r *http.Request) { measureData.Value = v.Value log.Debug("measureData:", measureData) - affected, err := session.Insert(measureData) - if err != nil && affected <= 0 { + err := db.DB("").Create(measureData).Error + if err != nil { log.Error("Failed to insert measure_data:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return @@ -480,8 +625,8 @@ func PostMeasureReportFromNF(w http.ResponseWriter, r *http.Request) { measureData.Value = 0 log.Debug("measureData:", measureData) - affected, err := session.Insert(measureData) - if err != nil && affected <= 0 { + err := db.DB("").Create(measureData).Error + if err != nil { log.Error("Failed to insert measure_data:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return @@ -514,7 +659,7 @@ func PostMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { measureTask.Tasks = make([]Task, 1) for _, taskId := range taskIds { id, _ := strconv.Atoi(taskId) - task, err := dborm.GetMeasureTask(id) + task, err := GetMeasureTask(id) if err != nil { log.Error("Failed to connect database: ", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) @@ -634,7 +779,7 @@ func PostMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { log.Debug("StatusCode: ", response.StatusCode()) switch response.StatusCode() { case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: - taskInfo := new(dborm.MeasureTask) + taskInfo := new(MeasureTask) taskInfo.Status = dborm.MeasureTaskStatusActive taskInfo.CreateTime = time.Now().Format(time.DateTime) affected, err := dborm.XormUpdateTableById(id, dborm.TableNameMeasureTask, taskInfo) @@ -688,7 +833,7 @@ func DeleteMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { respMsg := make(map[string]interface{}) for _, taskId := range taskIds { id, _ := strconv.Atoi(taskId) - task, err := dborm.GetMeasureTask(id) + task, err := GetMeasureTask(id) if err != nil { log.Error("Failed to connect database: ", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) @@ -711,7 +856,7 @@ func DeleteMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { log.Debug("neIds:", task.NeIds) if len(task.NeIds) == 0 { log.Warn("Not found target NE in the measure task") - taskInfo := new(dborm.MeasureTask) + taskInfo := new(MeasureTask) taskInfo.Status = dborm.MeasureTaskStatusDeleted affected, err := dborm.XormUpdateTableById(id, dborm.TableNameMeasureTask, taskInfo) if err != nil { @@ -745,7 +890,7 @@ func DeleteMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { if err != nil { // to avoid can't delete the task for abnormal NF log.Error("Failed to resty delete:", err) - taskInfo := new(dborm.MeasureTask) + taskInfo := new(MeasureTask) taskInfo.Status = dborm.MeasureTaskStatusDeleted affected, err := dborm.XormUpdateTableById(id, dborm.TableNameMeasureTask, taskInfo) if err != nil { @@ -762,7 +907,7 @@ func DeleteMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { log.Info("StatusCode: ", response.StatusCode()) switch response.StatusCode() { case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: - taskInfo := new(dborm.MeasureTask) + taskInfo := new(MeasureTask) taskInfo.Status = dborm.MeasureTaskStatusDeleted affected, err := dborm.XormUpdateTableById(id, dborm.TableNameMeasureTask, taskInfo) if err != nil { @@ -781,7 +926,7 @@ func DeleteMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { respMsg["error"] = body } } else { - taskInfo := new(dborm.MeasureTask) + taskInfo := new(MeasureTask) taskInfo.Status = dborm.MeasureTaskStatusDeleted affected, err := dborm.XormUpdateTableById(id, dborm.TableNameMeasureTask, taskInfo) if err != nil { @@ -819,7 +964,7 @@ func PatchMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { respMsg := make(map[string]interface{}) for _, taskId := range taskIds { id, _ := strconv.Atoi(taskId) - task, err := dborm.GetMeasureTask(id) + task, err := GetMeasureTask(id) if err != nil { log.Error("Failed to connect database: ", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) @@ -842,7 +987,7 @@ func PatchMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { } if len(task.NeIds) == 0 { - taskInfo := new(dborm.MeasureTask) + taskInfo := new(MeasureTask) taskInfo.Status = dborm.MeasureTaskStatusInactive affected, err := dborm.XormUpdateTableById(id, dborm.TableNameMeasureTask, taskInfo) if err != nil { @@ -865,7 +1010,7 @@ func PatchMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { return } if neInfo == nil { - taskInfo := new(dborm.MeasureTask) + taskInfo := new(MeasureTask) taskInfo.Status = dborm.MeasureTaskStatusInactive affected, err := dborm.XormUpdateTableById(id, dborm.TableNameMeasureTask, taskInfo) if err != nil { @@ -897,7 +1042,7 @@ func PatchMeasureTaskToNF(w http.ResponseWriter, r *http.Request) { log.Debug("StatusCode: ", response.StatusCode()) switch response.StatusCode() { case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: - taskInfo := new(dborm.MeasureTask) + taskInfo := new(MeasureTask) taskInfo.Status = dborm.MeasureTaskStatusInactive affected, err := dborm.XormUpdateTableById(id, dborm.TableNameMeasureTask, taskInfo) if err != nil { @@ -975,15 +1120,12 @@ func PostMeasurementFromNF(w http.ResponseWriter, r *http.Request) { _ = json.Unmarshal(body, &measurement) log.Debug("measurement:", measurement) - session := dborm.DbClient.XEngine.NewSession() - defer session.Close() - // layout := global.DateTime layout := time.RFC3339 measurement.Date = GetDateFromTimeString(layout, measurement.StartTime) measurement.StartTime = GetDateTimeFromTimeString(layout, measurement.StartTime) - affected, err := session.Table("nbi_pm").Insert(measurement) - if err != nil && affected <= 0 { + tx := db.DB("").Table("nbi_pm").Create(measurement) + if tx.Error != nil && tx.RowsAffected <= 0 { log.Error("Failed to insert nbi_pm:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return @@ -1059,14 +1201,11 @@ func GetMeasurementFromNF(w http.ResponseWriter, r *http.Request) { _ = json.Unmarshal(response.Body(), &measurement) log.Debug("measurement:", measurement) - session := dborm.DbClient.XEngine.NewSession() - defer session.Close() - layout := time.RFC3339 measurement.Date = GetDateFromTimeString(layout, measurement.StartTime) measurement.StartTime = GetDateTimeFromTimeString(layout, measurement.StartTime) - affected, err := session.Table("nbi_pm").Insert(measurement) - if err != nil && affected <= 0 { + tx := db.DB("").Table("nbi_pm").Create(measurement) + if tx.Error != nil && tx.RowsAffected <= 0 { log.Error("Failed to insert nbi_pm:", err) services.ResponseInternalServerError500DatabaseOperationFailed(w) return diff --git a/features/sm/backup.go b/features/sm/backup.go index 84028f40..6795c10c 100644 --- a/features/sm/backup.go +++ b/features/sm/backup.go @@ -1,11 +1,7 @@ package sm import ( - "database/sql" - "fmt" "net/http" - "os" - "os/exec" "time" "be.ems/lib/config" @@ -47,99 +43,3 @@ func GetOMCLocalTime(w http.ResponseWriter, r *http.Request) { } services.ResponseWithJson(w, http.StatusOK, response) } - -var dbConfig = config.GetYamlConfig().Database - -func DatabaseWhoreBackup() { - // MySQL数据库连接信息 - sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local", - dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Name) - db, err := sql.Open("mysql", sqlStr) - if err != nil { - log.Error("Failed to connect to database:", err) - return - } - defer db.Close() - - // 备份SQL文件路径 - backupFile := dbConfig.Backup + "/" + "whore_backup_" + dbConfig.Name + ".sql" - - // 执行mysqldump命令进行备份 - cmd := exec.Command("mysqldump", "-u", dbConfig.User, "-p"+dbConfig.Password, "-h", dbConfig.Host, dbConfig.Name) - output, err := cmd.Output() - if err != nil { - log.Error("Failed to execute mysqldump command:", err) - return - } - - // 将备份结果写入SQL文件 - file, err := os.Create(backupFile) - if err != nil { - log.Error("Failed to create backup file:", err) - return - } - defer file.Close() - - _, err = file.Write(output) - if err != nil { - log.Error("Failed to write backup file:", err) - return - } - - log.Info("Backup completed successfully.") -} - -func DatabaseIncrementalBackup() { - // MySQL数据库连接信息 - sqlStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local", - dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Name) - db, err := sql.Open("mysql", sqlStr) - if err != nil { - log.Error("Failed to connect to database:", err) - return - } - defer db.Close() - - // 备份SQL文件路径 - backupFile := dbConfig.Backup + "/" + "incremental_backup_" + dbConfig.Name + ".sql" - - // 上次备份的时间点 - lastBackupTime := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.Local) - - // 构建增量备份SQL语句 - query := fmt.Sprintf("SELECT * FROM table WHERE modified_at > '%s'", lastBackupTime.Format("2006-01-02 15:04:05")) - - // 执行查询 - rows, err := db.Query(query) - if err != nil { - log.Error("Failed to execute query:", err) - return - } - defer rows.Close() - - // 创建增量备份SQL文件 - file, err := os.Create(backupFile) - if err != nil { - log.Error("Failed to create backup file:", err) - return - } - defer file.Close() - - // 将查询结果写入SQL文件 - for rows.Next() { - var data string - err := rows.Scan(&data) - if err != nil { - log.Error("Failed to scan row:", err) - return - } - - _, err = file.WriteString(data + "\n") - if err != nil { - log.Error("Failed to write backup file:", err) - return - } - } - - log.Info("Incremental backup completed successfully.") -} diff --git a/features/state/getstate.go b/features/state/getstate.go index ebde9f5a..d07c33e2 100644 --- a/features/state/getstate.go +++ b/features/state/getstate.go @@ -9,17 +9,16 @@ import ( "strings" "time" - "github.com/shirou/gopsutil/v4/net" - "github.com/go-resty/resty/v2" "github.com/gorilla/mux" + "github.com/shirou/gopsutil/v4/net" "be.ems/lib/config" "be.ems/lib/dborm" "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/services" - tokenConst "be.ems/src/framework/constants/token" + "be.ems/src/framework/constants" ) type CpuUsage struct { @@ -246,7 +245,7 @@ func GetOneLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -362,7 +361,7 @@ func GetAllLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) { resp, err := client.SetTimeout(time.Duration(1 * time.Second)).R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -488,7 +487,7 @@ func GetOneSysinfoFromNF(w http.ResponseWriter, r *http.Request) { resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -633,7 +632,7 @@ func GetAllSysinfoFromNF(w http.ResponseWriter, r *http.Request) { resp, err := client.SetTimeout(time.Duration(1 * time.Second)).R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -756,7 +755,7 @@ func GetStateFromNF(w http.ResponseWriter, r *http.Request) { result["ipAddress"] = ne.Ip resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). //SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -846,136 +845,6 @@ func GetStateFromNF(w http.ResponseWriter, r *http.Request) { // services.ResponseWithJson(w, http.StatusOK, response) } -// GetStateFromNF 旧函数 -// Get system state from NF/NFs -func GetStateFromNFOld(w http.ResponseWriter, r *http.Request) { - log.Debug("GetStateFromNF processing... ") - - data := make([]map[string]interface{}, 0) - - vars := mux.Vars(r) - neType := vars["elementTypeValue"] - - var neList []dborm.NeInfo - if neType == "" { - services.ResponseNotFound404UriNotExist(w, r) - return - } - // token, err := services.CheckFrontValidRequest(w, r) - // if err != nil { - // log.Error("Request error:", err) - // return - // } - // log.Debug("AccessToken:", token) - - switch strings.ToLower(neType) { - case "all": - // query all NFs - // create rest client - - restHostPort := config.GetOMCHostUrl() - getNeInfoPattern := fmt.Sprintf(config.DefaultUriPrefix+"/databaseManagement/v1/elementType/%s/objectType/ne_info", - config.GetYamlConfig().Database.Name) - getNeInfoURI := restHostPort + getNeInfoPattern + "?WHERE=status+in+('0','3')" - log.Debug("getNeInfoPattern:", getNeInfoPattern) - - resp, err := client.R(). - EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). - // SetHeaders(map[string]string{"AccessToken": token}). - SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). - SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). - Get(getNeInfoURI) - if err != nil { - log.Error("Get ne_info from DB is failed:", err) - services.ResponseInternalServerError500NFConnectRefused(w) - return - } - - neList, _ = dborm.XormParseResult(resp.Body()) - default: - restHostPort := config.GetOMCHostUrl() - getNeInfoPattern := fmt.Sprintf(config.DefaultUriPrefix+"/databaseManagement/v1/elementType/%s/objectType/ne_info", - config.GetYamlConfig().Database.Name) - getNeInfoURI := restHostPort + getNeInfoPattern - neId := services.GetUriParamString(r, "ne_id", ",", true, true) - if neId == "" { - getNeInfoURI = getNeInfoURI + fmt.Sprintf("?WHERE=status+in+('0','3')+and+ne_type='%s'", neType) - } else { - getNeInfoURI = getNeInfoURI + fmt.Sprintf("?WHERE=status+in+('0','3')+and+ne_type='%v'+and+ne_id+in+%v", neType, neId) - } - log.Debug("getNeInfoURI:", getNeInfoURI) - - resp, err := client.R(). - EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). - // SetHeaders(map[string]string{"accessToken": token}). - SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). - SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). - Get(getNeInfoURI) - if err != nil { - log.Error("Get ne_info from DB is failed:", err) - services.ResponseInternalServerError500NFConnectRefused(w) - return - } - - neList, _ = dborm.XormParseResult(resp.Body()) - } - omcNeTypeLower := "omc" - if config.GetYamlConfig().OMC.NeType != "" { - omcNeTypeLower = strings.ToLower(config.GetYamlConfig().OMC.NeType) - } - for _, ne := range neList { - result := make(map[string]interface{}) - log.Debugf("r.RemoteAddr: %s omcNeTypeLower: %s", r.RemoteAddr, omcNeTypeLower) - log.Trace("ne: ", ne) - //if strings.ToLower(ne.NeType) != omcNeTypeLower || !strings.Contains(r.RemoteAddr, ne.Ip) { - if strings.ToLower(ne.NeType) != omcNeTypeLower { - hostUri := fmt.Sprintf("http://%s:%v", ne.Ip, ne.Port) - requestURI2NF := fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState", - hostUri, ne.NeType) - log.Debug("requestURI2NF:", requestURI2NF) - - result["ipAddress"] = ne.Ip - resp, err := client.R(). - EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). - // SetHeaders(map[string]string{"accessToken": token}). - SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). - SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). - Get(requestURI2NF) - if err != nil { - log.Error("Get system state from NF is failed:", err) - errorMessage := services.ErrorMessage{ - ErrorCode: "1", ErrorInfo: "Internal server error, NF connnect refused", - } - result["error"] = errorMessage - SN, Version, _ := dborm.XormGetNEStateInfo(ne.NeType, ne.NeId) - result["serialNum"] = SN - result["version"] = Version - } else { - systemState := make(map[string]interface{}) - _ = json.Unmarshal(resp.Body(), &systemState) - result["systemState"] = systemState - } - } else { - result["ipAddress"] = ne.Ip - emsState := GetEMSState(ne.Ip) - result["systemState"] = emsState - } - neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId - mapState := make(map[string]interface{}) - mapState[neItem] = result - - data = append(data, mapState) - log.Trace("data:", data) - } - - var response Response - response.Data = data - services.ResponseWithJson(w, http.StatusOK, response) -} - func GetEMSState(ip string) *SysState { log.Debug("GetEMSState processing... ") diff --git a/features/state/state_linux.go b/features/state/state_linux.go index a0944a1a..30ed20d8 100644 --- a/features/state/state_linux.go +++ b/features/state/state_linux.go @@ -126,10 +126,10 @@ func GetSysInfo(sysInfo *SysInfo) error { return nil } -func getProcess() process.Process { +func getProcess() *process.Process { checkPid := os.Getpid() ret, _ := process.NewProcess(int32(checkPid)) - return *ret + return ret } func GetSystemCpuInfo() { diff --git a/features/state/state_windows.go b/features/state/state_windows.go index 3ddf4844..cbb027ee 100644 --- a/features/state/state_windows.go +++ b/features/state/state_windows.go @@ -125,10 +125,10 @@ func GetSysInfo(sysInfo *SysInfo) error { return nil } -func getProcess() process.Process { +func getProcess() *process.Process { checkPid := os.Getpid() ret, _ := process.NewProcess(int32(checkPid)) - return *ret + return ret } func GetSystemCpuInfo() { diff --git a/features/trace/trace.go b/features/trace/trace.go index 252f47e3..78ff36cf 100644 --- a/features/trace/trace.go +++ b/features/trace/trace.go @@ -2,29 +2,23 @@ package trace import ( "encoding/json" - "errors" "fmt" "io" "net/http" - "strconv" "strings" "github.com/go-resty/resty/v2" - "github.com/gorilla/mux" "be.ems/lib/config" "be.ems/lib/dborm" "be.ems/lib/global" "be.ems/lib/log" - "be.ems/lib/run" "be.ems/lib/services" ) var ( UriTraceTaskV1 = config.DefaultUriPrefix + "/traceManagement/v1/subscriptions" UriTraceTask = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/subscriptions" - UriTraceRawMsg = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/rawMessage/{id}" - UriTraceDecMsg = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/decMessage/{id}" // decode message api CustomUriTraceTaskV1 = config.UriPrefix + "/traceManagement/v1/subscriptions" CustomUriTraceTask = config.UriPrefix + "/traceManagement/{apiVersion}/subscriptions" @@ -387,51 +381,3 @@ func GetRawMessage(w http.ResponseWriter, r *http.Request) { log.Debug("GetRawMessage processing... ") } - -func ParseRawMsg2Html(w http.ResponseWriter, r *http.Request) { - log.Debug("ParseRawMsg2Html processing... ") - - vars := mux.Vars(r) - idStr := vars["id"] - id, _ := strconv.Atoi(idStr) - - traceData, err := dborm.XormGetTraceData(id) - if err != nil { - log.Error("Failed to dborm.XormGetTraceRawMsg:", err) - services.ResponseInternalServerError500ProcessError(w, err) - return - } - log.Trace("traceData:", traceData) - filePath := traceData.DecMsg - if traceData.DecMsg == "" { - htmlFile := fmt.Sprintf("traceDecMessage-%d-%d.html", traceData.TaskID, traceData.ID) - filePath = config.GetYamlConfig().OMC.FrontTraceDir + "/" + htmlFile - command := fmt.Sprintf("/usr/local/omc/bin/data2html -f %s -t %d -i N%d -d %x", filePath, traceData.Timestamp, traceData.IfType, traceData.RawMsg) - out, err := run.ExecCmd(command, "/") - log.Tracef("Exec output: %v", string(out)) - if err != nil { - log.Errorf("Faile to ipdate2html:", err) - services.ResponseInternalServerError500ProcessError(w, err) - return - } - exist, err := global.FilePathExists(filePath) - if err != nil { - log.Errorf("Failed to stat:", err) - services.ResponseInternalServerError500ProcessError(w, err) - return - } - if !exist { - err = errors.New(string(strings.ReplaceAll(string(out), "\n", ""))) - services.ResponseInternalServerError500ProcessError(w, err) - return - } - traceData.DecMsg = filePath - _, err = dborm.XormUpdateTraceData(id, traceData) - if err != nil { - log.Errorf("Faile to XormUpdateTraceData:", err) - services.ResponseInternalServerError500ProcessError(w, err) - return - } - } - services.ResponseHtmlContent(w, http.StatusOK, filePath) -} diff --git a/features/ue/ue.go b/features/ue/ue.go index 7f940bb4..4c4ebb9a 100644 --- a/features/ue/ue.go +++ b/features/ue/ue.go @@ -14,10 +14,11 @@ import ( "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/services" - tokenConst "be.ems/src/framework/constants/token" + "be.ems/src/framework/constants" neDataModel "be.ems/src/modules/network_data/model" neDataService "be.ems/src/modules/network_data/service" neService "be.ems/src/modules/network_element/service" + "github.com/go-resty/resty/v2" "github.com/gorilla/mux" ) @@ -164,7 +165,7 @@ func GetAvailableAMFsFromNSSF(w http.ResponseWriter, r *http.Request) { resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -228,7 +229,7 @@ func GetSubscriptionsFromNSSF(w http.ResponseWriter, r *http.Request) { resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -257,7 +258,7 @@ func GetUEInfoFromNF(w http.ResponseWriter, r *http.Request) { return } - neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId) + neInfo := neService.NewNeInfo.FindByNeTypeAndNeID(neType, neId) var response services.MapResponse if neInfo.NeId == neId && neInfo.NeId != "" { @@ -336,7 +337,7 @@ func PostPCFUserInfo(w http.ResponseWriter, r *http.Request) { client.SetTimeout(1 * time.Minute) resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). //SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -409,7 +410,7 @@ func PutPCFUserInfo(w http.ResponseWriter, r *http.Request) { client.SetTimeout(1 * time.Minute) resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). //SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -475,7 +476,7 @@ func DeletePCFUserInfo(w http.ResponseWriter, r *http.Request) { resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). //SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -541,7 +542,7 @@ func GetUENumFromNF(w http.ResponseWriter, r *http.Request) { resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -605,7 +606,7 @@ func GetNBInfoFromNF(w http.ResponseWriter, r *http.Request) { resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -651,7 +652,7 @@ func PostNBInfoFromNF(w http.ResponseWriter, r *http.Request) { return } - neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(body.RmUID) + neInfo := neService.NewNeInfo.FindByRmuid(body.RmUID) if neInfo.RmUID != body.RmUID { services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element rmUID")) return @@ -739,7 +740,7 @@ func GetNBInfoAllFromNF(w http.ResponseWriter, r *http.Request) { resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). //SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -812,7 +813,7 @@ func GetUEInfoFileExportNF(w http.ResponseWriter, r *http.Request) { client.SetTimeout(3 * time.Minute) resp, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}). + SetHeaders(map[string]string{constants.HEADER_KEY: r.Header.Get(constants.HEADER_KEY)}). // SetHeaders(map[string]string{"accessToken": token}). SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). diff --git a/lib/config/config.go b/lib/config/config.go index 9b81433d..31656d7f 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -53,7 +53,7 @@ type YamlConfig struct { } `yaml:"listen"` } `yaml:"webServer"` - Database DbConfig `yaml:"database"` + // Database DbConfig `yaml:"database"` OMC struct { UriPrefix string `yaml:"uriPrefix"` @@ -139,16 +139,16 @@ type RestParam struct { KeyFile string `yaml:"keyFile"` } -type DbConfig struct { - Type string `yaml:"type"` - User string `yaml:"user"` - Password string `yaml:"password"` - Host string `yaml:"host"` - Port string `yaml:"port"` - Name string `yaml:"name"` - ConnParam string `yaml:"connParam,omitempty"` - Backup string `yaml:"backup"` -} +// type DbConfig struct { +// Type string `yaml:"type"` +// User string `yaml:"user"` +// Password string `yaml:"password"` +// Host string `yaml:"host"` +// Port string `yaml:"port"` +// Name string `yaml:"name"` +// ConnParam string `yaml:"connParam,omitempty"` +// Backup string `yaml:"backup"` +// } type AlarmConfig struct { SplitEventAlarm bool `yaml:"splitEventAlarm"` @@ -238,10 +238,10 @@ var YamlConfigInfo YamlConfigFile = YamlConfigFile{ // set default value for yaml config func NewYamlConfig() YamlConfig { return YamlConfig{ - Database: DbConfig{ - Type: "mysql", - ConnParam: "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True", - }, + // Database: DbConfig{ + // Type: "mysql", + // ConnParam: "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True", + // }, MML: MMLParam{ SizeRow: 200, SizeCol: 120, diff --git a/lib/core/ctx/ctx.go b/lib/core/ctx/ctx.go index 723dd808..0bbf3c1f 100644 --- a/lib/core/ctx/ctx.go +++ b/lib/core/ctx/ctx.go @@ -10,9 +10,8 @@ import ( "path/filepath" "strings" - "be.ems/src/framework/constants/token" - tokenUtils "be.ems/src/framework/utils/token" - "be.ems/src/framework/vo" + "be.ems/src/framework/constants" + "be.ems/src/framework/token" "github.com/gorilla/mux" "golang.org/x/text/language" ) @@ -123,25 +122,25 @@ func SaveUploadedFile(r *http.Request, dst string) error { // Authorization 解析请求头 func Authorization(r *http.Request) string { // Query请求查询 - if authQuery := r.URL.Query().Get(token.ACCESS_TOKEN); authQuery != "" { + if authQuery := r.URL.Query().Get(constants.ACCESS_TOKEN); authQuery != "" { return authQuery } // Header请求头 - if authHeader := r.Header.Get(token.ACCESS_TOKEN); authHeader != "" { + if authHeader := r.Header.Get(constants.ACCESS_TOKEN); authHeader != "" { return authHeader } // Query请求查询 - if authQuery := r.URL.Query().Get(token.RESPONSE_FIELD); authQuery != "" { + if authQuery := r.URL.Query().Get(constants.ACCESS_TOKEN_QUERY); authQuery != "" { return authQuery } // Header请求头 - authHeader := r.Header.Get(token.HEADER_KEY) + authHeader := r.Header.Get(constants.HEADER_KEY) if authHeader == "" { return "" } // 拆分 Authorization 请求头,提取 JWT 令牌部分 - arr := strings.Split(authHeader, token.HEADER_PREFIX) + arr := strings.Split(authHeader, constants.HEADER_PREFIX) if len(arr) == 2 && arr[1] == "" { return "" } @@ -177,34 +176,34 @@ func AcceptLanguage(r *http.Request) string { type ContextKey string // LoginUser 登录用户信息需要Authorize中间件 -func LoginUser(r *http.Request) (vo.LoginUser, error) { +func LoginUser(r *http.Request) (token.TokenInfo, error) { // 获取请求头标识信息 tokenStr := Authorization(r) if tokenStr == "" { - return vo.LoginUser{}, fmt.Errorf("not token info") + return token.TokenInfo{}, fmt.Errorf("not token info") } // 验证令牌 - claims, err := tokenUtils.Verify(tokenStr) + claims, err := token.Verify(tokenStr) if err != nil { - return vo.LoginUser{}, fmt.Errorf("token verify fail") + return token.TokenInfo{}, fmt.Errorf("token verify fail") } // 获取缓存的用户信息 - loginUser := tokenUtils.LoginUser(claims) - if loginUser.UserID == "" { - return vo.LoginUser{}, fmt.Errorf("not user info") + loginUser := token.Info(claims) + if loginUser.UserId <= 0 { + return token.TokenInfo{}, fmt.Errorf("not user info") } return loginUser, nil } // LoginUserToUserID 登录用户信息-用户ID -func LoginUserToUserID(r *http.Request) string { +func LoginUserToUserID(r *http.Request) int64 { loginUser, err := LoginUser(r) if err != nil { - return "" + return 0 } - return loginUser.UserID + return loginUser.UserId } // LoginUserToUserName 登录用户信息-用户名称 diff --git a/lib/dborm/dbgorm.go b/lib/dborm/dbgorm.go deleted file mode 100644 index 30ff7c62..00000000 --- a/lib/dborm/dbgorm.go +++ /dev/null @@ -1,167 +0,0 @@ -package dborm - -import ( - "database/sql" - "fmt" - "log" - "os" - "regexp" - "time" - - "gorm.io/driver/mysql" - "gorm.io/gorm" - "gorm.io/gorm/logger" -) - -// 数据库连接实例 -var dbgEngine *gorm.DB - -// 载入连接日志配置 -func loadLogger() logger.Interface { - newLogger := logger.New( - log.New(os.Stdout, "[GORM] ", log.LstdFlags), // 将日志输出到控制台 - logger.Config{ - SlowThreshold: time.Second, // Slow SQL 阈值 - LogLevel: logger.Info, // 日志级别 Silent不输出任何日志 - ParameterizedQueries: false, // 参数化查询SQL 用实际值带入?的执行语句 - Colorful: false, // 彩色日志输出 - }, - ) - return newLogger -} - -// 连接数据库实例 -func InitGormConnect(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam, dbLogging any) error { - var dialector gorm.Dialector - switch dbType { - case "mysql": - dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", - dbUser, - dbPassword, - dbHost, - dbPort, - dbName, - dbParam, - ) - dialector = mysql.Open(dsn) - default: - err := fmt.Errorf("invalid type: %s", dbType) - return err - } - opts := &gorm.Config{} - // 是否需要日志输出 - if dbLogging.(bool) { - opts.Logger = loadLogger() - } - // 创建连接 - db, err := gorm.Open(dialector, opts) - if err != nil { - log.Fatalf("failed to open: %s", err) - return err - } - // 获取底层 SQL 数据库连接 - sqlDB, err := db.DB() - if err != nil { - log.Fatalf("failed to connect DB pool: %v", err) - return err - } - // 测试数据库连接 - err = sqlDB.Ping() - if err != nil { - log.Fatalf("failed to ping database: %v", err) - return err - } - dbgEngine = db - return nil -} - -// 关闭数据库实例 -func Close() { - sqlDB, err := dbgEngine.DB() - if err != nil { - log.Fatalf("failed to connect pool: %s", err) - } - if err := sqlDB.Close(); err != nil { - log.Fatalf("failed to close: %s", err) - } -} - -// default gorm DB -func DefaultDB() *gorm.DB { - return dbgEngine -} - -// get sql DB -func GCoreDB() (*sql.DB, error) { - return dbgEngine.DB() -} - -// RawSQL 原生查询语句 -func RawSQL(sql string, parameters []any) ([]map[string]any, error) { - // 数据源 - db := DefaultDB() - - // 使用正则表达式替换连续的空白字符为单个空格 - fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ") - - // logger.Infof("sql=> %v", fmtSql) - // logger.Infof("parameters=> %v", parameters) - - // 查询结果 - var rows []map[string]any - res := db.Raw(fmtSql, parameters...).Scan(&rows) - if res.Error != nil { - return nil, res.Error - } - return rows, nil -} - -// ExecSQL 原生执行语句 -func ExecSQL(sql string, parameters []any) (int64, error) { - // 数据源 - db := DefaultDB() - - // 使用正则表达式替换连续的空白字符为单个空格 - fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ") - // 执行结果 - res := db.Exec(fmtSql, parameters...) - if res.Error != nil { - return 0, res.Error - } - return res.RowsAffected, nil -} - -func CloneTable(srcTable, dstTable string) error { - // 获取表 A 的结构信息 - var columns []gorm.ColumnType - dbMigrator := dbgEngine.Migrator() - columns, err := dbMigrator.ColumnTypes(srcTable) - if err != nil { - return fmt.Errorf("failed to ColumnTypes, %v", err) - } - - // 创建表 destination table - err = dbMigrator.CreateTable(dstTable) - if err != nil { - return fmt.Errorf("failed to CreateTable, %v", err) - } - // 复制表 src 的字段到表 dst - for _, column := range columns { - err = dbMigrator.AddColumn(dstTable, column.Name()) - if err != nil { - return fmt.Errorf("failed to AddColumn, %v", err) - } - } - - // 复制表 src 的主键和索引到表 dst - err = dbMigrator.CreateConstraint(dstTable, "PRIMARY") - if err != nil { - return fmt.Errorf("failed to AddColumn, %v", err) - } - - err = dbMigrator.CreateConstraint(dstTable, "INDEX") - if err != nil { - return fmt.Errorf("failed to AddColumn, %v", err) - } - return nil -} diff --git a/lib/dborm/dborm.go b/lib/dborm/dborm.go index 1bd598c4..a239afe7 100644 --- a/lib/dborm/dborm.go +++ b/lib/dborm/dborm.go @@ -518,66 +518,6 @@ type Period struct { End string `json:"End"` } -type KpiSetJ struct { - Code string `json:"Code"` // 统计编码 如:SMFHA01 - KPIs []string `json:"KPIs` // 指标项集合 ["SMF.AttCreatePduSession", "SMF.AttCreatePduSession._Dnn"] -} - -type MeasureTask struct { - Id int `json:"id" xorm:"pk 'id' autoincr"` - NeType string `json:"neType" xorm:"ne_type"` - NeIds []string `json:"neIds" xorm:"ne_ids"` - KpiSet []KpiSetJ `json:"KPISet" xorm:"kpi_set"` - StartTime string `json:"startTime" xorm:"start_time"` - EndTime string `json:"endTime" xorm:"end_time"` - Periods []Period `json:"Periods" xorm:"periods` - Schedule []ScheduleJ `json:"Schedule" xorm:"schedule"` - GranulOption string `json:"granulOption" xorm:"granul_option"` - Status string `json:"status" xorm:"status"` - AccountID string `json:"accountId" xorm:"account_id"` - Comment string `json:"comment" xorm:"comment"` - CreateTime string `json:"createTime" xorm:"create_time"` - UpdateTime string `json:"updateTime" xorm:"update_time"` - DeleteTime string `json:"deleteTime xorm:"delete_time"` -} - -func GetMeasureTask(taskId int) (*MeasureTask, error) { - log.Debug("GetMeasureTask processing... ") - - measureTask := new(MeasureTask) - has, err := xEngine.Table("measure_task").Where("id=?", taskId).Get(measureTask) - if err != nil || !has { - log.Error("Failed to get table measure_task from database:", err) - - return nil, err - } - - log.Debug("Measure Task:", measureTask) - return measureTask, nil -} - -func XormGetActiveMeasureTask(measureTasks *[]MeasureTask) (*[]MeasureTask, error) { - log.Debug("XormGetActiveMeasureTask processing... ") - - measureTask := new(MeasureTask) - rows, err := xEngine.Table("measure_task").Where("status='Active'").Rows(measureTask) - if err != nil { - log.Error("Failed to get table measure_task:", err) - return nil, err - } - defer rows.Close() - for rows.Next() { - err := rows.Scan(measureTask) - if err != nil { - log.Error("Failed to get table measure_task from database:", err) - return nil, err - } - *measureTasks = append(*measureTasks, *measureTask) - } - log.Debug("measureTasks:", measureTasks) - return measureTasks, nil -} - func GetTableByWhere(whereCondition string, tableName string) (*[]interface{}, error) { log.Debug("GetTableByWhere processing... ") diff --git a/lib/file/file_linux.go b/lib/file/file_linux.go index 4d934618..e8936bb9 100644 --- a/lib/file/file_linux.go +++ b/lib/file/file_linux.go @@ -8,21 +8,19 @@ import ( "os" "os/user" "path/filepath" - "strings" "syscall" - - "github.com/dustin/go-humanize" ) type FileInfo struct { - FileType string `json:"fileType"` // 文件类型 - FileMode string `json:"fileMode"` // 文件的权限 - LinkCount int64 `json:"linkCount"` // 硬链接数目 - Owner string `json:"owner"` // 所属用户 - Group string `json:"group"` // 所属组 - Size string `json:"size"` // 文件的大小 - ModifiedTime int64 `json:"modifiedTime"` // 最后修改时间,单位为秒 - FileName string `json:"fileName"` // 文件的名称 + FileType string `json:"fileType"` // file type: file/directory + FileMode string `json:"fileMode"` // file mode + LinkCount int64 `json:"linkCount"` // link count + Owner string `json:"owner"` // owner + Group string `json:"group"` // group + Size int64 `json:"size"` // size: xx byte + ModifiedTime int64 `json:"modifiedTime"` // last modified time:seconds + FilePath string `json:"filePath"` // file path + FileName string `json:"fileName"` // file name } func GetFileInfo(dir, suffix string) ([]FileInfo, error) { @@ -58,15 +56,15 @@ func GetFileInfo(dir, suffix string) ([]FileInfo, error) { if err != nil { return err } - humanReadableSize := humanize.Bytes(uint64(info.Size())) fileInfo := FileInfo{ FileType: fileType, FileMode: info.Mode().String(), LinkCount: int64(info.Sys().(*syscall.Stat_t).Nlink), Owner: userInfo.Username, Group: groupInfo.Name, - Size: strings.ToUpper(humanReadableSize), + Size: info.Size(), ModifiedTime: info.ModTime().Unix(), + FilePath: dir, FileName: info.Name(), } files = append(files, fileInfo) diff --git a/lib/midware/midhandle.go b/lib/midware/midhandle.go index ca7e3666..3e79cebf 100644 --- a/lib/midware/midhandle.go +++ b/lib/midware/midhandle.go @@ -6,7 +6,8 @@ import ( "be.ems/lib/log" "be.ems/lib/services" - tokenConst "be.ems/src/framework/constants/token" + "be.ems/src/framework/constants" + "github.com/gorilla/mux" ) @@ -23,7 +24,7 @@ func LoggerTrace(next http.Handler) http.Handler { log.Trace(" User-Agent:", r.Header.Get("User-Agent")) log.Trace(" Content-Type:", r.Header.Get("Content-Type")) log.Trace(" AccessToken:", r.Header.Get("AccessToken")) - log.Trace(" Authorization:", r.Header.Get(tokenConst.HEADER_KEY)) + log.Trace(" Authorization:", r.Header.Get(constants.HEADER_KEY)) log.Trace("Trace End=====") //body, _ := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) // nop-close to ready r.Body !!! diff --git a/lib/midware/mml_log.go b/lib/midware/mml_log.go index c63ac730..190e9629 100644 --- a/lib/midware/mml_log.go +++ b/lib/midware/mml_log.go @@ -11,7 +11,7 @@ import ( "be.ems/lib/core/ctx" "be.ems/lib/log" - "be.ems/src/framework/datasource" + "be.ems/src/framework/database/db" "be.ems/src/framework/utils/date" ) @@ -52,7 +52,7 @@ func LogMML(next http.Handler) http.Handler { username := ctx.LoginUserToUserName(r) // 执行插入 sql := "insert into mml_log (user,ip,ne_type,ne_id,mml,result,log_time)values(?,?,?,?,?,?,?)" - _, sqlerr := datasource.ExecDB("", sql, []any{username, ipAddr, neType, neId, mmlCmd, resultStr, timeStr}) + _, sqlerr := db.ExecDB("", sql, []any{username, ipAddr, neType, neId, mmlCmd, resultStr, timeStr}) if sqlerr != nil { log.Errorf("insert row : %v", sqlerr.Error()) } diff --git a/lib/midware/operate_log.go b/lib/midware/operate_log.go index a2647281..dd028b2b 100644 --- a/lib/midware/operate_log.go +++ b/lib/midware/operate_log.go @@ -12,9 +12,9 @@ import ( "time" "be.ems/lib/core/ctx" - "be.ems/src/framework/constants/common" + "be.ems/src/framework/constants" + "be.ems/src/framework/ip2region" "be.ems/src/framework/middleware/collectlogs" - "be.ems/src/framework/utils/ip2region" "be.ems/src/framework/utils/parse" "be.ems/src/modules/system/model" "be.ems/src/modules/system/service" @@ -52,19 +52,17 @@ func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler { // 解析ip地址 ip := strings.Split(r.RemoteAddr, ":")[0] ipaddr := ip2region.ClientIP(ip) - location := ip2region.RealAddressByIp(ipaddr) + location := "-" //ip2region.RealAddressByIp(ipaddr) // 操作日志记录 operLog := model.SysLogOperate{ - Title: options.Title, - BusinessType: options.BusinessType, - OperatorType: collectlogs.OPERATOR_TYPE_MANAGE, - Method: funcName, - OperURL: r.RequestURI, - RequestMethod: r.Method, - OperIP: ipaddr, - OperLocation: location, - OperName: username, - DeptName: "", + Title: options.Title, + BusinessType: options.BusinessType, + OperaMethod: funcName, + OperaUrl: r.RequestURI, + OperaUrlMethod: r.Method, + OperaIp: ipaddr, + OperaLocation: location, + OperaBy: username, } // 是否需要保存request,参数和值 @@ -97,7 +95,7 @@ func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler { if len(paramsStr) > 2000 { paramsStr = paramsStr[:2000] } - operLog.OperParam = paramsStr + operLog.OperaParam = paramsStr } next.ServeHTTP(w, r) @@ -110,9 +108,9 @@ func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler { // 响应状态 if status == "200" || status == "204" { - operLog.Status = common.STATUS_YES + operLog.StatusFlag = constants.STATUS_YES } else { - operLog.Status = common.STATUS_NO + operLog.StatusFlag = constants.STATUS_NO } // 是否需要保存response,参数和值 @@ -121,16 +119,16 @@ func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler { contentType := w.Header().Get("Content-Type") content := contentType + contentDisposition msg := fmt.Sprintf(`{"status":"%s","size":"%s","content-type":"%s"}`, status, size, content) - operLog.OperMsg = msg + operLog.OperaMsg = msg } // 日志记录时间 duration := time.Since(startTime) operLog.CostTime = duration.Milliseconds() - operLog.OperTime = time.Now().UnixMilli() + operLog.OperaTime = time.Now().UnixMilli() // 保存操作记录到数据库 - service.NewSysLogOperateImpl.InsertSysLogOperate(operLog) + service.NewSysLogOperate.Insert(operLog) }) } diff --git a/lib/mmlp/parse.go b/lib/mmlp/parse.go index e24230e8..02408cec 100644 --- a/lib/mmlp/parse.go +++ b/lib/mmlp/parse.go @@ -15,7 +15,8 @@ import ( "be.ems/lib/global" "be.ems/lib/log" "be.ems/lib/run" - tokenConst "be.ems/src/framework/constants/token" + "be.ems/src/framework/constants" + "github.com/go-resty/resty/v2" ) @@ -507,7 +508,7 @@ func TransMml2HttpReq(omcMmlVar *MmlVar, mml *MmlCommand) (*[]byte, error) { log.Debugf("method: Get requestURI: %s", requestURI) response, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: omcMmlVar.Authorization}). + SetHeaders(map[string]string{constants.HEADER_KEY: omcMmlVar.Authorization}). // SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}). SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -524,7 +525,7 @@ func TransMml2HttpReq(omcMmlVar *MmlVar, mml *MmlCommand) (*[]byte, error) { log.Debugf("method: Post requestURI: %s", requestURI) response, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: omcMmlVar.Authorization}). + SetHeaders(map[string]string{constants.HEADER_KEY: omcMmlVar.Authorization}). // SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}). SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -558,7 +559,7 @@ func TransMml2HttpReq(omcMmlVar *MmlVar, mml *MmlCommand) (*[]byte, error) { body := ParseInputBody(inputJson, mml) response, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: omcMmlVar.Authorization}). + SetHeaders(map[string]string{constants.HEADER_KEY: omcMmlVar.Authorization}). // SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}). SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -575,7 +576,7 @@ func TransMml2HttpReq(omcMmlVar *MmlVar, mml *MmlCommand) (*[]byte, error) { log.Debugf("method: Delete requestURI: %s", requestURI) response, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: omcMmlVar.Authorization}). + SetHeaders(map[string]string{constants.HEADER_KEY: omcMmlVar.Authorization}). // SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}). SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). @@ -591,7 +592,7 @@ func TransMml2HttpReq(omcMmlVar *MmlVar, mml *MmlCommand) (*[]byte, error) { log.Debugf("method: patch requestURI: %s", requestURI) response, err := client.R(). EnableTrace(). - SetHeaders(map[string]string{tokenConst.HEADER_KEY: omcMmlVar.Authorization}). + SetHeaders(map[string]string{constants.HEADER_KEY: omcMmlVar.Authorization}). // SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}). SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}). SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}). diff --git a/lib/routes/routes.go b/lib/routes/routes.go index 1a3d6081..1b91d233 100644 --- a/lib/routes/routes.go +++ b/lib/routes/routes.go @@ -211,7 +211,6 @@ func init() { Register("POST", trace.UriTraceTask, trace.PostTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("Trace Task", collectlogs.BUSINESS_TYPE_INSERT))) Register("PUT", trace.UriTraceTask, trace.PutTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("Trace Task", collectlogs.BUSINESS_TYPE_UPDATE))) Register("DELETE", trace.UriTraceTask, trace.DeleteTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("Trace Task", collectlogs.BUSINESS_TYPE_DELETE))) - Register("GET", trace.UriTraceDecMsg, trace.ParseRawMsg2Html, nil) Register("POST", trace.CustomUriTraceTask, trace.PostTraceTaskToNF, nil) Register("PUT", trace.CustomUriTraceTask, trace.PutTraceTaskToNF, nil) diff --git a/lib/services/response.go b/lib/services/response.go index 0c5ce1ac..a7d9e73e 100644 --- a/lib/services/response.go +++ b/lib/services/response.go @@ -22,7 +22,9 @@ func TotalResp(total int64) map[string]any { } func TotalDataResp(data any, total any) map[string]any { - return map[string]any{"code": CODE_SUCC, "data": data, "total": total} + return map[string]any{"code": CODE_SUCC, "data": map[string]any{ + "rows": data, "total": total, + }, "msg": "success"} } func SuccResp(va map[string]any) map[string]any {