From 8e7b4495d3c4f36884f8e8d3b9e37404f979190e Mon Sep 17 00:00:00 2001 From: zhanghan2021 Date: Fri, 26 Jan 2024 15:04:04 +0800 Subject: [PATCH] Analyze and process the tuning results into objects --- server/controller/runresult.go | 12 +++ server/controller/tune.go | 5 ++ server/dao/resultanalysis.go | 20 +++++ server/dao/runresultdao.go | 6 ++ server/db/db.go | 1 + server/model/common.go | 19 +++++ server/router/router.go | 1 + server/service/resultanalysis.go | 133 +++++++++++++++++++++++++++++++ server/service/resultservice.go | 26 +++--- server/service/taskservice.go | 1 + 10 files changed, 211 insertions(+), 13 deletions(-) create mode 100644 server/dao/resultanalysis.go create mode 100644 server/service/resultanalysis.go diff --git a/server/controller/runresult.go b/server/controller/runresult.go index c08d3bf..72133f4 100644 --- a/server/controller/runresult.go +++ b/server/controller/runresult.go @@ -32,3 +32,15 @@ func DeleteResult(c *gin.Context) { } response.Success(c, nil, "已删除") } + +func QueryTuneResults(c *gin.Context) { + taskId := c.Query("taskId") + machine_uuid := c.Query("uuid") + + data, err := service.GetResultAnalisis(taskId, machine_uuid) + if err != nil { + response.Fail(c, nil, err.Error()) + return + } + response.Success(c, data, "获取到调优分析详情") +} diff --git a/server/controller/tune.go b/server/controller/tune.go index 7a40188..aa31a40 100644 --- a/server/controller/tune.go +++ b/server/controller/tune.go @@ -76,6 +76,11 @@ func SaveTune(c *gin.Context) { return } + authToken := c.Request.Header.Get("Admin-Token") + if err := service.Upload(authToken, "./template/tar", t.TuneName+".tar.gz"); err != nil { + response.Fail(c, nil, err.Error()) + return + } if err := service.SaveTune(t); err != nil { response.Fail(c, nil, err.Error()) return diff --git a/server/dao/resultanalysis.go b/server/dao/resultanalysis.go new file mode 100644 index 0000000..7c8ceb4 --- /dev/null +++ b/server/dao/resultanalysis.go @@ -0,0 +1,20 @@ +package dao + +import ( + "openeuler.org/PilotGo/atune-plugin/db" + "openeuler.org/PilotGo/atune-plugin/model" +) + +func SaveResultAnalysis(ra *model.TuningResults) error { + if err := db.MySQL().Create(&ra).Error; err != nil { + return err + } + return nil +} +func GetResultAnalisis(taskId, machine_uuid string) (model.TuningResults, error) { + var result model.TuningResults + if err := db.MySQL().Where("task_id = ? AND machine_uuid = ?", taskId, machine_uuid).Find(&result).Error; err != nil { + return model.TuningResults{}, nil + } + return result, nil +} diff --git a/server/dao/runresultdao.go b/server/dao/runresultdao.go index e6c85f2..085298f 100644 --- a/server/dao/runresultdao.go +++ b/server/dao/runresultdao.go @@ -59,3 +59,9 @@ func GetResultUUIDByTaskId(taskId string) ([]string, error) { err := db.MySQL().Model(&model.RunResult{}).Distinct("machine_uuid").Where("task_id = ?", taskId).Pluck("machine_uuid", &uuids).Error return uuids, err } + +func GetResultByTaskIdAndUUID(taskId int, machine_uuid string, commandType string) (string, error) { + var r model.RunResult + err := db.MySQL().Where("task_id = ? AND machine_uuid = ? AND command_type = ?", taskId, machine_uuid, commandType).Find(&r).Error + return r.Stdout, err +} diff --git a/server/db/db.go b/server/db/db.go index 3a145d0..1331878 100644 --- a/server/db/db.go +++ b/server/db/db.go @@ -45,6 +45,7 @@ func MysqldbInit(conf *config.MysqlDBInfo) error { MySQL().AutoMigrate(&model.RunResult{}) MySQL().AutoMigrate(&model.Tasks{}) MySQL().AutoMigrate(&model.AtuneClient{}) + MySQL().AutoMigrate(&model.TuningResults{}) return nil } diff --git a/server/model/common.go b/server/model/common.go index 2c7dac8..396e985 100644 --- a/server/model/common.go +++ b/server/model/common.go @@ -59,3 +59,22 @@ type Results struct { OS string `json:"os"` Result []*RunResult `json:"result"` } + +// TuningIteration 是用于存储每次迭代结果的结构体 +type TuningIterResult struct { + TuningStep string `json:"step"` + RecommandParameters interface{} `json:"recommand_parameters"` + EvaluationValue interface{} `json:"evaluation_value"` + PerformanceImprovement string `json:"performance_improvement"` +} + +// TuningResult 是用于存储调优结果的结构体 +type TuningResults struct { + ID int `gorm:"primary_key;AUTO_INCREMENT" json:"id"` + TaskID int `json:"task_id"` + MachineUUID string `json:"machine_uuid"` + TuningResult string `json:"tuning_result"` + FinalOptimizationResult string `json:"final_optimization_result"` + FinalEvaluationValue string `json:"final_evaluation_value"` + BaselinePerformance string `json:"baseline_performance"` +} diff --git a/server/router/router.go b/server/router/router.go index fb3ac62..6b2ce66 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -71,6 +71,7 @@ func registerAPIs(router *gin.Engine) { restune := router.Group("/plugin/" + plugin.GlobalClient.PluginInfo.Name) { restune.GET("result", controller.QueryResults) + restune.GET("tune_result", controller.QueryTuneResults) restune.DELETE("result_delete", controller.DeleteResult) } } diff --git a/server/service/resultanalysis.go b/server/service/resultanalysis.go new file mode 100644 index 0000000..9802bad --- /dev/null +++ b/server/service/resultanalysis.go @@ -0,0 +1,133 @@ +package service + +import ( + "encoding/json" + "regexp" + "strings" + + "gitee.com/openeuler/PilotGo/sdk/logger" + "openeuler.org/PilotGo/atune-plugin/dao" + "openeuler.org/PilotGo/atune-plugin/model" +) + +func ResultAnalysis(taskId int, machine_uuid string) error { + result, err := dao.GetResultByTaskIdAndUUID(taskId, machine_uuid, CommandTypeTune) + if err != nil { + return err + } + + var iterResult model.TuningIterResult + var iterResults []model.TuningIterResult + var ( + finalOptimizationResult interface{} + finalEvaluationValue interface{} + baselinePerformance interface{} + ) + for _, line := range strings.Split(result, "\n") { + // 检查日志中是否包含调优结果信息 + if strings.Contains(line, "Current Tuning Progress") { + // 迭代轮次 + reTuningStep := regexp.MustCompile(`\((\d+)/\d+\)`) + matches := reTuningStep.FindStringSubmatch(line) + if len(matches) > 0 { + iterResult.TuningStep = matches[1] + } + } else if strings.Contains(line, "recommand parameters") { + // 推荐参数 + reRecommandParams := regexp.MustCompile(`The \d+th recommand parameters is: (.+)`) + matches := reRecommandParams.FindStringSubmatch(line) + if len(matches) > 0 { + iterResult.RecommandParameters = extractKeyValue(matches[1]) + } + } else if strings.Contains(line, "th evaluation value") { + reEvaluationValue := regexp.MustCompile(`evaluation value: ([^\n]+)`) + matches := reEvaluationValue.FindStringSubmatch(line) + if len(matches) > 0 { + re := regexp.MustCompile(`\(([^)]+)\)\(([^)]+)\)`) + m := re.FindStringSubmatch(matches[1]) + // 本轮评估值 + iterResult.EvaluationValue = extractKeyValue(m[1]) + // 性能提升 + iterResult.PerformanceImprovement = m[2] + iterResults = append(iterResults, iterResult) + } + } else if strings.Contains(line, "The final optimization result") { + // 最终优化结果 + reFinalOptimization := regexp.MustCompile(`The final optimization result is: ([^\n]+)`) + matches := reFinalOptimization.FindStringSubmatch(line) + if len(matches) > 0 { + finalOptimizationResult = extractKeyValue(matches[1]) + } + } else if strings.Contains(line, "The final evaluation value") { + // 最终评估值 + reFinalEvaluationValue := regexp.MustCompile(`The final evaluation value is: (.+)`) + matches := reFinalEvaluationValue.FindStringSubmatch(line) + if len(matches) > 0 { + finalEvaluationValue = extractKeyValue(matches[1]) + } + } else if strings.Contains(line, "Baseline Performance is:") { + // 基准性能 + reBaselinePerformance := regexp.MustCompile(`Baseline Performance is: \(([^)]+)\)`) + matches := reBaselinePerformance.FindStringSubmatch(line) + if len(matches) > 0 { + baselinePerformance = extractKeyValue(matches[1]) + } + } + } + + tuningResult := &model.TuningResults{ + TaskID: taskId, + MachineUUID: machine_uuid, + TuningResult: jsonToString(iterResults), + FinalOptimizationResult: jsonToString(finalOptimizationResult), + FinalEvaluationValue: jsonToString(finalEvaluationValue), + BaselinePerformance: jsonToString(baselinePerformance), + } + if err = dao.SaveResultAnalysis(tuningResult); err != nil { + return err + } + return nil +} + +func GetResultAnalisis(taskId, machine_uuid string) (interface{}, error) { + tune_result, err := dao.GetResultAnalisis(taskId, machine_uuid) + if err != nil { + return nil, err + } + result := make(map[string]interface{}) + result["id"] = tune_result.ID + result["task_id"] = tune_result.TaskID + result["machine_uuid"] = tune_result.MachineUUID + result["tuning_result"] = jsonStringToObject(tune_result.TuningResult) + result["final_optimization_result"] = jsonStringToObject(tune_result.FinalOptimizationResult) + result["final_evaluation_value"] = jsonStringToObject(tune_result.FinalEvaluationValue) + result["baseline_performance"] = jsonStringToObject(tune_result.BaselinePerformance) + return result, err +} + +func extractKeyValue(input string) map[string]string { + result := make(map[string]string) + re := regexp.MustCompile(`(\w+)=(\w+)`) + matches := re.FindAllStringSubmatch(input, -1) + for _, match := range matches { + result[match[1]] = match[2] + } + return result +} + +func jsonStringToObject(input string) interface{} { + var jsonString interface{} + if err := json.Unmarshal([]byte(input), &jsonString); err != nil { + return nil + } + return jsonString +} + +func jsonToString(input interface{}) string { + results, err := json.Marshal(input) + if err != nil { + logger.Error("序列化失败:%v", err.Error()) + return "" + } + return string(results) +} diff --git a/server/service/resultservice.go b/server/service/resultservice.go index 4f73a45..aa2b57c 100644 --- a/server/service/resultservice.go +++ b/server/service/resultservice.go @@ -27,19 +27,6 @@ const ( CommandTypeRestore = "restore" ) -func DeleteResult(resultId []int) error { - if len(resultId) == 0 { - return errors.New("请输入删除的ID") - } - - for _, rid := range resultId { - if err := dao.DeleteResult(rid); err != nil { - logger.Error("%v", strconv.Itoa(rid)+"未删除成功") - } - } - return nil -} - func processResult(dbtaskid int, res *common.CmdResult, commandType string) (string, error) { var commandResultStatus string if res.RetCode == 0 { @@ -60,6 +47,19 @@ func processResult(dbtaskid int, res *common.CmdResult, commandType string) (str return commandResultStatus, nil } +func DeleteResult(resultId []int) error { + if len(resultId) == 0 { + return errors.New("请输入删除的ID") + } + + for _, rid := range resultId { + if err := dao.DeleteResult(rid); err != nil { + logger.Error("%v", strconv.Itoa(rid)+"未删除成功") + } + } + return nil +} + func UpdateResultStatusToRunning(dbtaskid int, uuid string, commandType string) error { result := &model.RunResult{ IsSuccess: IsSuccess_running, diff --git a/server/service/taskservice.go b/server/service/taskservice.go index 0c63faf..941daad 100644 --- a/server/service/taskservice.go +++ b/server/service/taskservice.go @@ -53,6 +53,7 @@ func RunTask(dbtaskId int, tuneId int, commands map[int]model.TaskCommand, machi return } UpdateResultStatus(dbtaskId, uuid, CommandTypeRestore, IsSuccess_success) + ResultAnalysis(dbtaskId, uuid) }(uuid) } -- Gitee