123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- package service
- import (
- "context"
- "encoding/json"
- "html/template"
- "io"
- "os"
- "sort"
- "strconv"
- "strings"
- "time"
- "go-common/app/admin/ep/melloi/conf"
- "go-common/app/admin/ep/melloi/model"
- "go-common/library/log"
- )
- // QueryDraft Query Draft
- func (s *Service) QueryDraft(scene *model.Scene) (*model.QueryDraft, error) {
- return s.dao.QueryDraft(scene)
- }
- // UpdateScene Update Scene
- func (s *Service) UpdateScene(scene *model.Scene) (fusing int, err error) {
- scriptIDList := make([]int, len(scene.Scripts))
- for index, script := range scene.Scripts {
- scriptIDList[index] = script.ID
- }
- fusing, err = s.dao.UpdateScene(scene, scriptIDList)
- return
- }
- // AddScene Add Scene
- func (s *Service) AddScene(scene *model.Scene) (id int, err error) {
- id, err = s.dao.AddScene(scene)
- return
- }
- // QueryAPI Query API
- func (s *Service) QueryAPI(scene *model.Scene) (*model.QueryAPIs, error) {
- return s.dao.QueryAPI(scene)
- }
- // AddConfig Add Config
- func (s *Service) AddConfig(script *model.Script) error {
- return s.dao.AddConfig(script)
- }
- // QueryTree Query Tree
- func (s *Service) QueryTree(script *model.Script) (*model.ShowTree, error) {
- return s.dao.QueryTree(script)
- }
- // QueryScenesByPage Query Scene By Page
- func (s *Service) QueryScenesByPage(c context.Context, sessionID string, qsrq *model.QuerySceneRequest) (rsp *model.QuerySceneResponse, err error) {
- // 获取服务树节点
- var (
- treeNodes []string
- treeNodesd []string
- )
- if treeNodesd, err = s.QueryUserRoleNode(c, sessionID); err != nil {
- log.Error("QueryUserRoleNode err (%v):", err)
- }
- treeNodes = append(treeNodesd, "")
- if ExistsInSlice(qsrq.Executor, conf.Conf.Melloi.Executor) {
- if rsp, err = s.dao.QueryScenesByPageWhiteName(&qsrq.Scene, qsrq.PageNum, qsrq.PageSize); err != nil {
- return
- }
- } else {
- if rsp, err = s.dao.QueryScenesByPage(&qsrq.Scene, qsrq.PageNum, qsrq.PageSize, treeNodes); err != nil {
- return
- }
- }
- return
- }
- //AddAndExecuScene AddSceneAuto add scene auto
- func (s *Service) AddAndExecuScene(c context.Context, scene model.Scene, cookie string) (resp model.DoPtestResp, err error) {
- var (
- buff *template.Template
- file *os.File
- scrThreadGroup model.ScrThreadGroup
- fileName string
- testNames []string
- testNameNicks []string
- loadTimes []int
- scripts []*model.Script
- jmeterLog string
- resJtl string
- sceneID int
- threadGroup string
- )
- // id 不是0 ,说明是输入接口创建的场景,根据sceneID 查询到接口列表,再根据接口列表生成jmx
- // 不是前端 quick-start 页的批量选择,走如下逻辑
- if scene.ID != 0 && !scene.IsBatch {
- script := model.Script{SceneID: scene.ID}
- if scripts, err = s.dao.QueryScripts(&script, 1, 200); err != nil {
- log.Error("s.dao.QueryScripts err :(%v)", err)
- return
- }
- scene.Scripts = scripts
- }
- if scene.IsDebug {
- for _, script := range scene.Scripts {
- script.ThreadsSum = 1
- script.Loops = 5
- script.TestName = script.TestName + "_perf_debug"
- }
- scene.SceneName = scene.SceneName + "_perf_debug"
- }
- // 非 quick-start 页面的批量选择,走如下逻辑,即 quick-start 页面的批量选择,不生成 scene.jmx 文件
- sceneSuffix := strconv.FormatInt(time.Now().Unix(), 10)
- if !scene.IsBatch {
- scrThreadGroup.Scripts = scene.Scripts
- if threadGroup, err = s.GetThreadGroup(scrThreadGroup); err != nil {
- log.Error("s.dao.GetThreadGroup (%v)", err)
- return
- }
- scene.ThreadGroup = unescaped(threadGroup)
- if buff, err = template.ParseFiles(s.c.Jmeter.JmeterSceneTmp); err != nil {
- log.Error("file is not exists (%v)", err)
- return
- }
- scene.ScriptPath = "/data/jmeter-log/" + scene.Department + "/" + scene.Project + "/" + scene.APP + "/" + "scene" + "/" + sceneSuffix + "/"
- if err = os.MkdirAll(scene.ScriptPath, 0755); err != nil {
- log.Error("Create SavePath Err (%v)", err)
- return
- }
- // 创建脚本文件 脚本路径+场景名+后缀.jmx
- if file, err = os.Create(scene.ScriptPath + sceneSuffix + ".jmx"); err != nil {
- log.Error("os.Create file err :(%v)", err)
- return
- }
- defer file.Close()
- buff = buff.Funcs(template.FuncMap{"unescaped": unescaped})
- buff.Execute(io.Writer(file), scene)
- fileName = file.Name()
- jmeterLog = scene.ScriptPath + "jmg" + sceneSuffix
- resJtl = scene.ScriptPath + "jtl" + sceneSuffix
- }
- scene.JmeterLog = jmeterLog
- scene.JmeterFilePath = fileName
- scene.ResJtl = resJtl
- sceneID = scene.ID
- // 批量选择脚本执行场景压测,则走如下逻辑,写 script 表
- if scene.ID == 0 || scene.IsBatch {
- //前端传入的scene 有 scripts , sceneId 没有传,走如下逻辑,写入scene 表
- if !scene.IsBatch {
- scene.SceneType = 1
- if sceneID, err = s.AddScene(&scene); err != nil {
- log.Error("s.AddScene err :(%v)", err)
- return
- }
- scene.ID = sceneID
- }
- for _, script := range scene.Scripts {
- script.IsSave = true
- script.SceneID = sceneID
- script.ID = 0
- script.TestType = model.SCENE_SCRIPT_TYPE
- //脚本落库
- if resp, err = s.AddAndExcuScript(c, script, "", &scene, false, true); err != nil {
- log.Error("s.AddAndExcuScript err :(%v)", err)
- return
- }
- script.ID = resp.ScriptID
- scripts = append(scripts, script)
- }
- scene.Scripts = scripts
- }
- // 有id,需要更新数据库
- if scene.ID != 0 && !scene.IsDebug {
- if _, err = s.UpdateScene(&scene); err != nil {
- log.Error("s.UpdateScene error :(%v)", err)
- return
- }
- }
- //获取 testNames testNameNicks loadTimes
- for _, script := range scene.Scripts {
- testNames = append(testNames, script.TestName)
- testNameNicks = append(testNameNicks, script.TestName+sceneSuffix)
- loadTimes = append(loadTimes, script.LoadTime)
- }
- sort.Ints(loadTimes)
- //执行压测
- if scene.IsExecute && len(scene.Scripts) > 0 {
- ptestParam := model.DoPtestParam{
- TestNames: testNames,
- SceneName: scene.SceneName,
- UserName: scene.UserName,
- LoadTime: loadTimes[len(loadTimes)-1],
- FileName: fileName,
- Upload: false,
- ProjectName: scene.SceneName,
- JmeterLog: scene.JmeterLog,
- ResJtl: scene.ResJtl,
- Department: scene.Department,
- Project: scene.Project,
- APP: scene.APP,
- ScriptID: 0,
- DockerSum: 1,
- TestNameNick: SliceToString(testNameNicks, ","),
- TestNameNicks: testNameNicks,
- Scripts: scene.Scripts,
- SceneID: sceneID,
- Type: model.PROTOCOL_SCENE, // 场景
- IsDebug: scene.IsDebug,
- Cookie: cookie,
- Fusing: scene.Fusing,
- }
- if resp, err = s.DoPtest(c, ptestParam); err != nil {
- log.Error("s.DoPtest err :(%v)", err)
- return
- }
- //临时写法
- resp.ScriptID = sceneID
- }
- return
- }
- // SaveScene Save Scene
- func (s *Service) SaveScene(scene *model.Scene) error {
- return s.dao.SaveScene(scene)
- }
- // SaveOrder Save Order
- func (s *Service) SaveOrder(req model.SaveOrderReq, scene *model.Scene) error {
- var (
- flag = 1
- length = len(req.GroupOrderList)
- index = length - 1
- bak int
- )
- if scene.SceneType == 1 {
- for i := 0; i < length; i++ {
- bak = req.GroupOrderList[i].GroupID
- req.GroupOrderList[i].GroupID = flag
- //防止越界
- if i == index {
- break
- }
- if bak != req.GroupOrderList[i+1].GroupID {
- flag++
- }
- }
- } else {
- for i := 0; i < length; i++ {
- bak = req.GroupOrderList[i].RunOrder
- req.GroupOrderList[i].RunOrder = flag
- //防止越界
- if i == index {
- break
- }
- if bak != req.GroupOrderList[i+1].RunOrder {
- flag++
- }
- }
- }
- return s.dao.SaveOrder(req.GroupOrderList, scene)
- }
- // QueryRelation Query Relation
- func (s *Service) QueryRelation(script *model.Script) (*model.QueryRelation, error) {
- var (
- groupId int
- err error
- )
- if _, groupId, err = s.dao.QueryGroupId(script); err != nil {
- log.Error("s.dao.QueryGroupId err :(%v)", err)
- return nil, err
- }
- return s.dao.QueryRelation(groupId, script)
- }
- // DeleteAPI Delete API
- func (s *Service) DeleteAPI(script *model.Script) error {
- return s.dao.DeleteAPI(script)
- }
- // DoScenePtest Do Scene Ptest
- func (s *Service) DoScenePtest(c context.Context, ptestScene model.DoPtestSceneParam, addPtest bool, cookie string) (resp model.DoPtestResp, err error) {
- var (
- scenes []*model.Scene
- scripts []*model.Script
- )
- scene := model.Scene{ID: ptestScene.SceneID}
- if scenes, err = s.dao.QueryScenes(&scene, 1, 1); err != nil {
- log.Error("s.dao.QueryScenes err :(%v)", err)
- return
- }
- script := model.Script{SceneID: ptestScene.SceneID}
- if scripts, err = s.dao.QueryScripts(&script, 1, 300); err != nil {
- log.Error("s.dao.QueryScripts err :(%v)", err)
- return
- }
- scenes[0].Scripts = scripts
- if len(scenes) > 0 {
- sceneInfo := GetSceneInfo(scenes[0])
- ptestParam := model.DoPtestParam{
- TestNames: sceneInfo.TestNames,
- SceneName: sceneInfo.SceneName,
- UserName: ptestScene.UserName,
- LoadTime: sceneInfo.MaxLoadTime,
- FileName: scenes[0].JmeterFilePath,
- Upload: false,
- ProjectName: sceneInfo.SceneName,
- ResJtl: sceneInfo.ResJtl,
- JmeterLog: sceneInfo.JmeterLog,
- Department: scenes[0].Department,
- Project: scenes[0].Project,
- APP: scenes[0].APP,
- ScriptID: 0,
- DockerSum: 1,
- TestNameNick: SliceToString(sceneInfo.TestNameNicks, ","),
- TestNameNicks: sceneInfo.TestNameNicks,
- Scripts: sceneInfo.Scripts,
- SceneID: ptestScene.SceneID,
- Type: model.PROTOCOL_SCENE, // 场景
- AddPtest: addPtest,
- Cookie: cookie,
- }
- return s.DoPtest(c, ptestParam)
- }
- return
- }
- //DoScenePtestBatch dosceneptest batch
- func (s *Service) DoScenePtestBatch(c context.Context, ptestScenes model.DoPtestSceneParams, cookie string) (err error) {
- for _, SceneID := range ptestScenes.SceneIDs {
- ptestScene := model.DoPtestSceneParam{SceneID: SceneID, UserName: ptestScenes.UserName}
- go s.DoScenePtest(context.TODO(), ptestScene, false, cookie)
- }
- return
- }
- //GetSceneInfo get sceneInfo
- func GetSceneInfo(scene *model.Scene) (sceneInfo model.SceneInfo) {
- var (
- loadTimes []int
- testNames []string
- testNameNicks []string
- scripts []*model.Script
- )
- if scene == nil {
- return
- }
- sceneSuffix := strconv.FormatInt(time.Now().Unix(), 10)
- for _, script := range scene.Scripts {
- loadTimes = append(loadTimes, script.LoadTime)
- testNames = append(testNames, script.TestName)
- testNameNicks = append(testNameNicks, script.TestName+sceneSuffix)
- scripts = append(scripts, script)
- }
- sort.Ints(loadTimes)
- sceneInfo = model.SceneInfo{
- MaxLoadTime: loadTimes[len(loadTimes)-1],
- JmeterLog: scene.JmeterLog + sceneSuffix,
- ResJtl: scene.ResJtl + sceneSuffix,
- LoadTimes: loadTimes,
- TestNames: testNames,
- TestNameNicks: testNameNicks,
- SceneName: scene.SceneName,
- Scripts: scripts,
- }
- return
- }
- // QueryExistAPI Query Exist API
- func (s *Service) QueryExistAPI(c context.Context, sessionID string, req *model.APIInfoRequest) (res *model.APIInfoList, err error) {
- // 获取服务树节点
- var (
- treeNodes []string
- treeNodesd []string
- )
- if treeNodesd, err = s.QueryUserRoleNode(c, sessionID); err != nil {
- log.Error("QueryUserRoleNode err (%v):", err)
- }
- treeNodes = append(treeNodesd, "")
- if res, err = s.dao.QueryExistAPI(&req.Script, req.PageNum, req.PageSize, req.SceneID, treeNodes); err != nil {
- return
- }
- for _, script := range res.ScriptList {
- if script.APIHeader != "" {
- if err = json.Unmarshal([]byte(script.APIHeader), &script.Headers); err != nil {
- log.Error("get script header err : (%v),scriptId:(%d)", err, script.ID)
- }
- }
- if script.ArgumentString != "" {
- if err = json.Unmarshal([]byte(script.ArgumentString), &script.ArgumentsMap); err != nil {
- log.Error("get script argument err: (%v), scriptId:(%d)", err, script.ID)
- }
- }
- if script.OutputParams != "" {
- if err = json.Unmarshal([]byte(script.OutputParams), &script.OutputParamsMap); err != nil {
- log.Error("get script OutputParams err: (%v),scriptId:(%d)", err, script.ID)
- }
- }
- }
- return
- }
- // QueryPreview Query Preview
- func (s *Service) QueryPreview(req *model.Script) (preRes *model.PreviewInfoList, err error) {
- var (
- list *model.GroupList
- preList *model.PreviewList
- preResd model.PreviewInfoList
- )
- if list, err = s.dao.QueryGroup(req.SceneID); err != nil {
- return
- }
- for i := 0; i < len(list.GroupList); i++ {
- // 或者使用var preInfo = &model.PreviewInfo{}
- preInfo := new(model.PreviewInfo)
- groupId := list.GroupList[i].GroupID
- threadsSum := list.GroupList[i].ThreadsSum
- loadTime := list.GroupList[i].LoadTime
- readyTime := list.GroupList[i].ReadyTime
- if preList, err = s.dao.QueryPreview(req.SceneID, groupId); err != nil {
- return
- }
- preInfo.GroupID = groupId
- preInfo.ThreadsSum = threadsSum
- preInfo.LoadTime = loadTime
- preInfo.ReadyTime = readyTime
- preInfo.InfoList = preList.PreList
- preResd.PreviewInfoList = append(preResd.PreviewInfoList, preInfo)
- preRes = &preResd
- }
- return
- }
- // QueryParams Query Params
- func (s *Service) QueryParams(req *model.Script) (res *model.UsefulParamsList, tempRes *model.UsefulParamsList, err error) {
- //var paramList []string
- var (
- uParam *model.UsefulParams
- )
- res = &model.UsefulParamsList{}
- if tempRes, err = s.dao.QueryUsefulParams(req.SceneID); err != nil {
- return
- }
- if len(tempRes.ParamsList) > 0 {
- for _, tempParam := range tempRes.ParamsList {
- if strings.Contains(tempParam.OutputParams, ",") {
- tempParamList := strings.Split(tempParam.OutputParams, ",")
- for _, param := range tempParamList {
- uParam = &model.UsefulParams{}
- uParam.OutputParams = strings.Split(strings.Split(param, "\":\"")[0], "\"")[1]
- res.ParamsList = append(res.ParamsList, uParam)
- }
- } else {
- uParam = &model.UsefulParams{}
- uParam.OutputParams = strings.Split(strings.Split(tempParam.OutputParams, "\":\"")[0], "\"")[1]
- res.ParamsList = append(res.ParamsList, uParam)
- }
- }
- } else {
- // 赋值空数组
- res.ParamsList = []*model.UsefulParams{}
- }
- return
- }
- // UpdateBindScene Update Bind Scene
- func (s *Service) UpdateBindScene(bindScene *model.BindScene) (err error) {
- return s.dao.UpdateBindScene(bindScene)
- }
- // QueryDrawRelation Query Draw Relation
- func (s *Service) QueryDrawRelation(scene *model.Scene) (res model.DrawRelationList, tempRes *model.SaveOrderReq, err error) {
- var (
- //relationList model.DrawRelationList
- edges []*model.Edge
- edge *model.Edge
- tempEdge *model.Edge
- //nodes []*model.Node
- node *model.Node
- )
- if tempRes, err = s.dao.QueryDrawRelation(scene); err != nil {
- return
- }
- for k := 0; k < len(tempRes.GroupOrderList); k++ {
- node = &model.Node{}
- node.ID = tempRes.GroupOrderList[k].ID
- node.Name = tempRes.GroupOrderList[k].TestName
- res.Nodes = append(res.Nodes, node)
- }
- for i := 0; i < len(tempRes.GroupOrderList)-1; i++ {
- edge = &model.Edge{}
- tempEdge = &model.Edge{}
- if tempRes.GroupOrderList[i].GroupID == tempRes.GroupOrderList[i+1].GroupID && tempRes.GroupOrderList[i].RunOrder == tempRes.GroupOrderList[i+1].RunOrder {
- edge.Source = tempRes.GroupOrderList[i].TestName
- edges = append(edges, edge)
- if len(edges) > 0 {
- //edges[i+1].Source =
- tempEdge.Source = edges[i-1].Source
- tempEdge.Target = tempRes.GroupOrderList[i+1].TestName
- edges = append(edges, tempEdge)
- }
- } else if tempRes.GroupOrderList[i].GroupID == tempRes.GroupOrderList[i+1].GroupID && tempRes.GroupOrderList[i].RunOrder != tempRes.GroupOrderList[i+1].RunOrder {
- edge.Source = tempRes.GroupOrderList[i].TestName
- edge.Target = tempRes.GroupOrderList[i+1].TestName
- edges = append(edges, edge)
- } else if tempRes.GroupOrderList[i].GroupID != tempRes.GroupOrderList[i+1].GroupID {
- edge.Source = tempRes.GroupOrderList[i].TestName
- edges = append(edges, edge)
- }
- }
- for j := 0; j < len(edges); j++ {
- if edges[j].Target != "" {
- //relationList.Edges = append(relationList.Edges, edges[j])
- res.Edges = append(res.Edges, edges[j])
- }
- }
- return
- }
- // DeleteDraft Delete Draft
- func (s *Service) DeleteDraft(scene *model.Scene) error {
- return s.dao.DeleteDraft(scene)
- }
- // QueryConfig Query Config
- func (s *Service) QueryConfig(script *model.Script) (*model.GroupInfo, error) {
- return s.dao.QueryConfig(script)
- }
- // DeleteScene Delete Scene
- func (s *Service) DeleteScene(scene *model.Scene) error {
- return s.dao.DeleteScene(scene)
- }
- //CopyScene copy scene
- func (s *Service) CopyScene(c context.Context, scene *model.Scene, cookie string) (addScene model.AddScene, err error) {
- var (
- scripts []*model.Script
- scenes []*model.Scene
- sceneID int
- resp model.DoPtestResp
- )
- script := model.Script{SceneID: scene.ID}
- scened := model.Scene{ID: scene.ID}
- //先根据 scene.ID 查询 scenes 和 scripts
- if scenes, err = s.dao.QueryScenes(&scened, 1, 10); err != nil {
- log.Error("s.dao.QueryScenes err :(%v)", err)
- return
- }
- if scripts, err = s.dao.QueryScripts(&script, 1, 200); err != nil {
- log.Error("s.dao.QueryScripts err :(%v)", err)
- return
- }
- if len(scenes) != 0 {
- scenes[0].ID = 0
- scenes[0].UserName = scene.UserName
- scenes[0].SceneName = scene.SceneName
- //将新的scene 写入 数据库,并返回 sceneID
- if sceneID, err = s.dao.AddScene(scenes[0]); err != nil {
- log.Error("s.dao.AddScene err :(%v)", err)
- return
- }
- // 将新的 script 写入 script 表
- for _, sctd := range scripts {
- sctd.SceneID = sceneID
- sctd.ID = 0
- if _, _, _, err = s.dao.AddScript(sctd); err != nil {
- return
- }
- }
- sce := model.Scene{
- APP: scenes[0].APP,
- Department: scenes[0].Department,
- Project: scenes[0].Project,
- ID: sceneID,
- IsDebug: false,
- IsExecute: false,
- UserName: scene.UserName,
- SceneName: scene.SceneName,
- }
- if resp, err = s.AddAndExecuScene(c, sce, cookie); err != nil {
- log.Error("s.AddAndExecuScene err :(%v), (%v)", err, resp)
- return
- }
- addScene.SceneID = sceneID
- addScene.UserName = scene.UserName
- }
- return
- }
- // QueryFusing Query Fusing
- func (s *Service) QueryFusing(script *model.Script) (res *model.FusingInfoList, err error) {
- res, err = s.dao.QueryFusing(script)
- for i := 0; i < len(res.FusingList)-1; i++ {
- if res.FusingList[i] != res.FusingList[i+1] {
- res.SetNull = true
- return
- }
- }
- return
- }
|