ptest.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "regexp"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "go-common/app/admin/ep/melloi/conf"
  12. "go-common/app/admin/ep/melloi/model"
  13. "go-common/library/log"
  14. )
  15. //DoPtest do post
  16. func (s *Service) DoPtest(c context.Context, ptestParam model.DoPtestParam) (resp model.DoPtestResp, err error) {
  17. var (
  18. testNameNick string
  19. testNameNicks []string
  20. )
  21. if ptestParam.TestNameNick == "" {
  22. tim := strconv.FormatInt(time.Now().Unix(), 10)
  23. for _, testName := range ptestParam.TestNames {
  24. testNameNick = testName + tim
  25. testNameNicks = append(testNameNicks, testNameNick)
  26. }
  27. }
  28. return s.DoPtestByJmeter(c, ptestParam, testNameNicks)
  29. }
  30. //StopPtest stop test
  31. func (s *Service) StopPtest(c context.Context, ptestJob model.PtestJob) (err error) {
  32. var (
  33. jobNames []string
  34. ptestJobs []*model.PtestJob
  35. )
  36. ptestJob.Active = 1
  37. if ptestJobs, err = s.dao.QueryPtestJob(&ptestJob); err != nil {
  38. log.Error("s.dao.QueryPtestJob err :(%v)", err)
  39. return
  40. }
  41. for _, ptestJob := range ptestJobs {
  42. jobNames = append(jobNames, ptestJob.JobName)
  43. }
  44. for _, jobName := range jobNames {
  45. s.DeleteJob(context.TODO(), jobName)
  46. }
  47. return
  48. }
  49. //ReducePtest reduce ptest
  50. func (s *Service) ReducePtest(c context.Context, reducePtest model.ReducePtest) (message string, err error) {
  51. if reducePtest.JobName == "" {
  52. message = "请输入 jobName"
  53. return
  54. }
  55. if _, err = s.DeleteJob(c, reducePtest.JobName); err != nil {
  56. message = "调用删除 job 接口失败"
  57. log.Error("s.DeleteJob err :(%v)", err)
  58. return
  59. }
  60. if err = s.dao.DeletePtestJob(reducePtest.ID); err != nil {
  61. message = "sql 执行失败"
  62. log.Error("s.dao.DeletePtestJob err :(%v)", err)
  63. return
  64. }
  65. message = "success"
  66. return
  67. }
  68. //QueryAllJobFree Query AllJob Free
  69. func (s *Service) QueryAllJobFree(c context.Context, ptesJob *model.PtestJob) ([]*model.PtestJob, error) {
  70. return s.dao.QueryPtestJob(ptesJob)
  71. }
  72. //QueryOrStopAllPtestByJobName query or stop all test by job name
  73. func (s *Service) QueryOrStopAllPtestByJobName(c context.Context, reportSuID int, IsDelete bool, testStatus int) (ptestjobsd []*model.PtestJob, err error) {
  74. // 删除所有正在允许此接口的容器
  75. ptestJobd := model.PtestJob{ReportSuID: reportSuID, Active: 1}
  76. if ptestjobsd, err = s.dao.QueryPtestJob(&ptestJobd); err != nil {
  77. log.Error("s.dao.QueryPtestJob err (%v)", err)
  78. return
  79. }
  80. if IsDelete {
  81. for _, ptestJob := range ptestjobsd {
  82. if _, err = s.DeleteJob(context.TODO(), ptestJob.JobName); err != nil {
  83. log.Error("s.DeleteJob err :(%v)", err)
  84. return
  85. }
  86. if err = s.dao.DeletePtestJob(ptestJob.ID); err != nil {
  87. log.Error("s.dao.DeletePtestJob err (%v)", err)
  88. return
  89. }
  90. if err = s.dao.UpdateReportStatusByID(reportSuID, testStatus); err != nil {
  91. log.Error("s.UpdateReportStatusByID err :(%v)", err)
  92. return
  93. }
  94. }
  95. }
  96. return
  97. }
  98. //DoAddPtest doadd test stress
  99. func (s *Service) DoAddPtest(c context.Context, ptestAdd model.PtestAdd) (status string, err error) {
  100. status = "fail"
  101. var (
  102. resp model.DoPtestResp
  103. grpc *model.GRPC
  104. scripts []*model.Script
  105. resportSumm []*model.ReportSummary
  106. )
  107. ptestParam := model.DoPtestParam{}
  108. // 此处 ScriptType 取自 reportSummary , 0-http 1-grpc 2-scene
  109. if ptestAdd.ScriptType == model.PROTOCOL_GRPC {
  110. if grpc, err = s.QueryGrpcById(ptestAdd.ScriptID); err != nil {
  111. log.Error("Query GRPC err: (%v)", err)
  112. return status, err
  113. }
  114. ptestParam = model.DoPtestParam{
  115. UserName: grpc.UpdateBy, // 用户名
  116. LoadTime: grpc.LoadTime, //运行时间
  117. TestNames: StringToSlice(grpc.TaskName), //接口名转数组
  118. FileName: grpc.JmxPath, // jmx文件
  119. ResJtl: ptestAdd.ResJtl, // jtl时间戳
  120. JmeterLog: ptestAdd.JmeterLog, // jmeterlog时间戳
  121. Department: grpc.Department,
  122. Project: grpc.Project,
  123. IsDebug: false,
  124. APP: grpc.APP,
  125. ScriptID: grpc.ID,
  126. Cookie: "", // 用不到
  127. URL: grpc.ServiceName, // 用于微信通知
  128. LabelIDs: nil,
  129. Domain: grpc.HostName, // 微信通知Domain
  130. FileSplit: false, // 文件切割
  131. SplitNum: 0, // 切割数量
  132. JarPath: grpc.JarPath,
  133. Type: model.PROTOCOL_GRPC, //grpc
  134. AddPtest: true, // 加压
  135. }
  136. }
  137. if ptestAdd.ScriptType == model.PROTOCOL_SCENE {
  138. ptestScene := model.DoPtestSceneParam{
  139. SceneID: ptestAdd.SceneId,
  140. UserName: ptestAdd.UserName,
  141. }
  142. if resp, err = s.DoScenePtest(c, ptestScene, true, ""); err != nil {
  143. log.Error("s.DoScenePtest err :(%v)", err)
  144. return status, err
  145. }
  146. }
  147. if ptestAdd.ScriptType == model.PROTOCOL_HTTP {
  148. script := model.Script{ID: ptestAdd.ScriptID}
  149. if scripts, err = s.QueryScripts(&script, 1, 5); err != nil {
  150. log.Error("QueryScripts err :(%v)", err)
  151. return status, err
  152. }
  153. if len(scripts) > 0 {
  154. // http 模板
  155. ptestParam = model.DoPtestParam{
  156. UserName: script.UpdateBy,
  157. TestNames: QueryTestNamesByJmfile(scripts[0].SavePath),
  158. FileName: scripts[0].SavePath,
  159. LoadTime: 1800,
  160. Upload: scripts[0].Upload,
  161. ProjectName: scripts[0].ProjectName,
  162. ResJtl: ptestAdd.ResJtl,
  163. JmeterLog: ptestAdd.JmeterLog,
  164. Department: scripts[0].Department,
  165. Project: scripts[0].Project,
  166. APP: scripts[0].App,
  167. ScriptID: scripts[0].ID,
  168. AddPtest: true,
  169. Domain: scripts[0].Domain,
  170. FileSplit: scripts[0].FileSplit,
  171. SplitNum: scripts[0].SplitNum,
  172. DockerSum: ptestAdd.DockerSum,
  173. Type: model.PROTOCOL_HTTP,
  174. APIHeader: scripts[0].APIHeader,
  175. }
  176. }
  177. }
  178. if ptestAdd.ScriptType != model.PROTOCOL_SCENE {
  179. if resp, err = s.DoPtestByJmeter(c, ptestParam, nil); err != nil {
  180. log.Error("DoPtestByJmeter err: (%v)", err)
  181. return
  182. }
  183. log.Info("add ---jobName:(%s)", resp.JobName)
  184. }
  185. status = "success"
  186. // 更新reportSummary数据表
  187. reportSu := model.ReportSummary{ID: ptestAdd.ReportSuID}
  188. if resportSumm, err = s.dao.QueryReportSurys(&reportSu); err != nil {
  189. return
  190. }
  191. ptestJob := model.PtestJob{JobName: resp.JobName, ScriptID: ptestAdd.ScriptID, ReportSuID: ptestAdd.ReportSuID, Active: 1, ExecuteID: ptestAdd.ExecuteID, HostIP: resp.HostIP}
  192. log.Info("add ---jobName:(%s)", resp.JobName)
  193. if _, err = s.dao.AddPtestJob(&ptestJob); err != nil {
  194. log.Error("s.dao.AddPtestJob err (%v)", err)
  195. return
  196. }
  197. DockerSum := resportSumm[0].DockerSum + 1
  198. if err = s.dao.UpdateReportDockByID(resportSumm[0].ID, DockerSum); err != nil {
  199. log.Error("s.dao.UpdateReportDockByID err (%v)", err)
  200. return
  201. }
  202. return
  203. }
  204. //AddPtest add ptest
  205. func (s *Service) AddPtest(c context.Context, ptestAdd model.PtestAdd) (err error) {
  206. go s.DoAddPtestWithSleep(c, ptestAdd)
  207. return
  208. }
  209. //DoAddPtestWithSleep Do AddPtestWith Sleep
  210. func (s *Service) DoAddPtestWithSleep(c context.Context, ptestAdd model.PtestAdd) (err error) {
  211. var ptestJobs []*model.PtestJob
  212. if ptestAdd.DockerNum == 0 {
  213. ptestAdd.DockerNum = 1
  214. }
  215. if ptestAdd.SleepTime == 0 {
  216. ptestAdd.SleepTime = 1
  217. }
  218. for i := 1; i <= ptestAdd.DockerNum; i++ {
  219. time.Sleep(time.Duration(ptestAdd.SleepTime) * time.Second)
  220. // 判断主容器状态,主容器被删除,则不再添加新的容器
  221. ptestJob := model.PtestJob{JobName: ptestAdd.JobName}
  222. if ptestJobs, err = s.dao.QueryPtestJob(&ptestJob); err != nil {
  223. log.Error("s.dao.QueryPtestJob err :(%v)", err)
  224. }
  225. if len(ptestJobs) > 0 {
  226. if ptestJobs[0].Active != -1 {
  227. go s.DoAddPtest(context.TODO(), ptestAdd)
  228. }
  229. }
  230. }
  231. return
  232. }
  233. //DoPtestByFile do test by file
  234. func (s *Service) DoPtestByFile(c context.Context, script model.Script, resJtl, jmeterLog string) (resp model.DoPtestResp, err error) {
  235. var scripts []*model.Script
  236. if scripts, err = s.QueryScripts(&script, 1, 5); err != nil {
  237. log.Error("QueryScripts err :(%v)", err)
  238. return
  239. }
  240. scriptID := scripts[0].ID
  241. testNames := QueryTestNamesByJmfile(scripts[0].SavePath)
  242. ptestParam := model.DoPtestParam{
  243. UserName: script.UpdateBy,
  244. TestNames: testNames,
  245. FileName: scripts[0].SavePath,
  246. LoadTime: 1800,
  247. Upload: scripts[0].Upload,
  248. ProjectName: scripts[0].ProjectName,
  249. ResJtl: resJtl,
  250. JmeterLog: jmeterLog,
  251. Department: scripts[0].Department,
  252. Project: scripts[0].Project,
  253. APP: scripts[0].App,
  254. ScriptID: scripts[0].ID,
  255. Fusing: scripts[0].Fusing,
  256. UseBusinessStop: scripts[0].UseBusinessStop,
  257. BusinessStopPercent: scripts[0].BusinessStopPercent,
  258. }
  259. if resp, err = s.DoPtest(context.TODO(), ptestParam); err != nil {
  260. log.Error("DoPtest error :(%v)", err)
  261. return
  262. }
  263. resp.ScriptID = scriptID
  264. return
  265. }
  266. //DoPtestArr QueryScriptsInID
  267. func (s *Service) DoPtestArr(c context.Context, PtestBatch model.PtestBatch, cookie string) (status string, err error) {
  268. var scripts []*model.Script
  269. if scripts, err = s.dao.QueryScriptsInID(PtestBatch.IDArr); err != nil {
  270. status = "fail"
  271. log.Error("QueryScriptsInID err --- :(%v) ", err)
  272. return status, err
  273. }
  274. for _, script := range scripts {
  275. JmeterLog := script.JmeterLog + strconv.FormatInt(time.Now().Unix(), 10)
  276. ResJtl := script.ResJtl + strconv.FormatInt(time.Now().Unix(), 10)
  277. ptestParam := model.DoPtestParam{
  278. UserName: PtestBatch.UserName,
  279. FileName: script.SavePath,
  280. ProjectName: script.ProjectName,
  281. Upload: script.Upload,
  282. ResJtl: ResJtl,
  283. JmeterLog: JmeterLog,
  284. Department: script.Department,
  285. Project: script.Project,
  286. APP: script.App,
  287. ScriptID: script.ID,
  288. URL: script.URL,
  289. Cookie: cookie,
  290. Domain: script.Domain,
  291. FileSplit: script.FileSplit,
  292. SplitNum: script.SplitNum,
  293. Fusing: script.Fusing,
  294. APIHeader: script.APIHeader,
  295. }
  296. if script.Upload {
  297. ptestParam.LoadTime = 1800
  298. ptestParam.TestNames = QueryTestNamesByJmfile(script.SavePath)
  299. } else {
  300. ptestParam.LoadTime = script.LoadTime
  301. ptestParam.TestNames = StringToSlice(script.TestName)
  302. }
  303. go s.DoPtest(context.TODO(), ptestParam)
  304. }
  305. status = "success"
  306. return
  307. }
  308. //DoPtestByScriptId do ptest by scriptid
  309. func (s *Service) DoPtestByScriptId(c context.Context, script *model.Script, cookie, executor string) (resp model.DoPtestResp, err error) {
  310. var scripts []*model.Script
  311. if scripts, err = s.QueryScripts(script, 1, 5); err != nil {
  312. log.Error("QueryScripts err :(%v)", err)
  313. return
  314. }
  315. ptestParam := model.DoPtestParam{
  316. TestNames: StringToSlice(scripts[0].TestName),
  317. ProjectName: scripts[0].ProjectName,
  318. FileName: scripts[0].SavePath,
  319. LoadTime: scripts[0].LoadTime,
  320. ResJtl: scripts[0].ResJtl,
  321. JmeterLog: scripts[0].JmeterLog,
  322. UserName: executor,
  323. Department: scripts[0].Department,
  324. Project: scripts[0].Project,
  325. APP: scripts[0].App,
  326. ScriptID: scripts[0].ID,
  327. URL: scripts[0].URL,
  328. Cookie: cookie,
  329. Domain: scripts[0].Domain,
  330. FileSplit: scripts[0].FileSplit,
  331. SplitNum: scripts[0].SplitNum,
  332. Fusing: scripts[0].Fusing,
  333. APIHeader: scripts[0].APIHeader,
  334. Upload: scripts[0].Upload,
  335. UseBusinessStop: scripts[0].UseBusinessStop,
  336. BusinessStopPercent: scripts[0].BusinessStopPercent,
  337. }
  338. if ptestParam.Upload {
  339. ptestParam.TestNames = QueryTestNamesByJmfile(scripts[0].SavePath)
  340. }
  341. return s.DoPtest(c, ptestParam)
  342. }
  343. //DoPtestByJmeter do ptest by jmeter
  344. func (s *Service) DoPtestByJmeter(c context.Context, ptestParam model.DoPtestParam, testNameNicks []string) (resp model.DoPtestResp, err error) {
  345. var (
  346. du string
  347. Debug int
  348. CPUCore int
  349. reportSuID int
  350. scriptSnapIDs []int
  351. beginTime string
  352. token string
  353. Index = 0
  354. btm time.Time
  355. dus time.Duration
  356. tempRes *model.PaasJobQueryStatus
  357. hostIP string
  358. command string
  359. )
  360. lay := "2006-01-02 15:04:05"
  361. executeID := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
  362. if !ptestParam.AddPtest {
  363. // 不加压,增加新的 log
  364. ptestParam.ResJtl = fmt.Sprintf("%s%s", ptestParam.ResJtl, executeID)
  365. ptestParam.JmeterLog = fmt.Sprintf("%s%s", ptestParam.JmeterLog, executeID)
  366. }
  367. jobNamed := executeID + "run"
  368. jobName := string([]rune(jobNamed)[10:])
  369. // add filesplit messages to env variables
  370. if !ptestParam.AddPtest {
  371. Index = 1
  372. } else {
  373. Index = ptestParam.DockerSum + 1
  374. }
  375. ptestParam.EnvInfo = "FileSplit:" + strconv.FormatBool(ptestParam.FileSplit) + ",SplitNum:" + strconv.Itoa(ptestParam.SplitNum) +
  376. ",Index:" + strconv.Itoa(Index)
  377. // 为压测容器绑定host
  378. if ptestParam.Upload {
  379. HostInfoByUploadSc(ptestParam.Domain)
  380. } else {
  381. if ptestParam.Type == model.PROTOCOL_HTTP {
  382. HostInfo(ptestParam.Domain, ptestParam.APIHeader)
  383. } else if ptestParam.Type == model.PROTOCOL_SCENE {
  384. HostInfoList(ptestParam.Scripts)
  385. }
  386. }
  387. if _, _, err = CreateResJtlAndJmeterLog(ptestParam); err != nil {
  388. log.Info("create resjtl or jmeterlog err :(%v)", err)
  389. return
  390. }
  391. //获取 Debug,CPUCore,command
  392. Debug, CPUCore, command = s.CreateCommand(ptestParam)
  393. jobInfo := model.Job{FileName: ptestParam.FileName, CPU: CPUCore, Memory: 8096, Parallelism: 1, Name: jobName, ResJtl: ptestParam.ResJtl,
  394. JmeterLog: ptestParam.JmeterLog, EnvInfo: ptestParam.EnvInfo, JarPath: ptestParam.JarPath, Command: command}
  395. beginTime = time.Now().Format(lay)
  396. if btm, err = time.Parse(lay, beginTime); err != nil {
  397. return
  398. }
  399. resd := int(btm.Unix()) % 5
  400. du = "-" + strconv.Itoa(resd) + "s"
  401. if dus, err = time.ParseDuration(du); err != nil {
  402. return
  403. }
  404. beginTime = btm.Add(dus).Format(lay)
  405. res := make(chan interface{}, 10000)
  406. resHostIp := make(chan interface{}, 10000)
  407. tm := time.Now()
  408. for i := 0; i <= ptestParam.LoadTime+10; i += 5 {
  409. tm = tm.Add(time.Second * 5)
  410. }
  411. timeout := time.After(time.Until(tm))
  412. log.Info("job set timeout util --- :(%s) ", time.Until(tm))
  413. if ptestParam.ExecuDockerSum == 0 {
  414. ptestParam.ExecuDockerSum = 1
  415. }
  416. if _, err = s.AddJob(context.TODO(), jobInfo); err != nil {
  417. log.Error("add ptest job err:(%v)", err)
  418. return
  419. }
  420. if token, err = s.RmToken(c); err != nil {
  421. log.Error("get token err:(%v)", err)
  422. return
  423. }
  424. //获取物理机ip
  425. if tempRes, err = s.Job(c, jobName); err != nil {
  426. hostIP = ""
  427. }
  428. if len(tempRes.Data.Pods) > 0 {
  429. hostIP = tempRes.Data.Pods[0].HostIP
  430. }
  431. // 如果不是增加容器,生成一份快照
  432. if !ptestParam.AddPtest {
  433. if scriptSnapIDs, err = s.AddSnap(c, ptestParam, executeID, jobName, jobNamed); err != nil || len(scriptSnapIDs) == 0 {
  434. s.DeleteJob(context.TODO(), jobName)
  435. return
  436. }
  437. // 从页面上直接输入参数生成的单场景脚本,testNames 和 testNameNicks 长度都是 1,reportSummary 测试计划为空
  438. if reportSuID, err = s.AddReSummaryByPtest(ptestParam, jobName, jobNamed, testNameNicks, scriptSnapIDs[0], Debug); err != nil {
  439. log.Error("s.dao.AddReportSummary err :(%v)", err)
  440. s.DeleteJob(context.TODO(), jobName)
  441. return
  442. }
  443. //容器写入 ptest_job 表
  444. ptestJob := model.PtestJob{ScriptID: ptestParam.ScriptID, ReportSuID: reportSuID, JobName: jobName, Active: 1, ExecuteID: jobNamed, HostIP: hostIP}
  445. if _, err = s.dao.AddPtestJob(&ptestJob); err != nil {
  446. log.Error("s.dao.AddPtestJob err :(%v)", err)
  447. s.DeleteJob(context.TODO(), jobName)
  448. return
  449. }
  450. //获取场景中每个接口的熔断成功率的值
  451. fusingList := make([]int, len(ptestParam.Scripts))
  452. useBusiStopList := make([]bool, len(ptestParam.Scripts))
  453. busiStopPercentList := make([]int, len(ptestParam.Scripts))
  454. for index, script := range ptestParam.Scripts {
  455. fusingList[index] = script.Fusing
  456. useBusiStopList[index] = script.UseBusinessStop
  457. busiStopPercentList[index] = script.BusinessStopPercent
  458. }
  459. AddReGraphTimer := model.AddReGraphTimer{
  460. ScriptID: ptestParam.ScriptID,
  461. JobName: jobName,
  462. BeginTime: beginTime,
  463. Token: token,
  464. TestNames: ptestParam.TestNames,
  465. TestNameNicks: testNameNicks,
  466. ReportSuID: reportSuID,
  467. Fusing: ptestParam.Fusing,
  468. FusingList: fusingList,
  469. TestType: ptestParam.Type,
  470. UseBusinessStop: ptestParam.UseBusinessStop,
  471. BusinessStopPercent: ptestParam.BusinessStopPercent,
  472. UseBusiStopList: useBusiStopList,
  473. BusiStopPercentList: busiStopPercentList,
  474. }
  475. //场景脚本的逻辑,可能存在多个test_name
  476. if ptestParam.Type == model.PROTOCOL_SCENE && ptestParam.TestNameNick != "" {
  477. AddReGraphTimer.TestNameNicks = ptestParam.TestNameNicks
  478. AddReGraphTimer.TestNames = ptestParam.TestNames
  479. }
  480. //数据同步job
  481. log.Info("-------开始执行数据同步job,loadTime :(%v)", ptestParam.LoadTime)
  482. go s.addReGraphTimer(context.TODO(), AddReGraphTimer, res, timeout)
  483. //查询容器hostIp
  484. go s.addPtestJobHostIp(context.TODO(), AddReGraphTimer, resHostIp, timeout)
  485. //增加label
  486. if len(ptestParam.LabelIDs) > 0 && !ptestParam.IsDebug {
  487. for _, lableID := range ptestParam.LabelIDs {
  488. lrl := model.LabelRelation{LabelID: int64(lableID), Type: model.ScriptType, TargetID: int64(ptestParam.ScriptID)}
  489. s.AddLabelRelation(&lrl)
  490. lrll := model.LabelRelation{LabelID: int64(lableID), Type: model.ReportType, TargetID: int64(reportSuID)}
  491. s.AddLabelRelation(&lrll)
  492. }
  493. }
  494. //如果不是debug ,且配置发生通知为true,则发送微信通知
  495. if !ptestParam.IsDebug && conf.Conf.Wechat.SendMessage {
  496. serviceName := ptestParam.Department + "." + ptestParam.Project + "." + ptestParam.APP
  497. var userService map[string][]string
  498. if userService, err = s.QueryDependServiceAdmins(c, serviceName, s.getSessionInCookie(ptestParam.Cookie)); err != nil {
  499. log.Error("query depend service admin error(%v)", err)
  500. return
  501. }
  502. // 发送群通知
  503. content := AddWechatContent(ptestParam, reportSuID, jobName, userService)
  504. go s.AddWechatSend(context.TODO(), ptestParam.Cookie, content)
  505. // 发送依赖服务通知
  506. for user := range userService {
  507. toUser := StringToSlice(user)
  508. content = AddWechatDependServiceContent(ptestParam, userService, reportSuID, user)
  509. go s.dao.PushWechatMsgToPerson(context.TODO(), ptestParam.Cookie, toUser, content)
  510. }
  511. }
  512. }
  513. resp = model.DoPtestResp{BeginTime: beginTime, ReportSuID: reportSuID, JobName: jobName, ScriptSnapIDs: scriptSnapIDs,
  514. JmeterLog: ptestParam.JmeterLog, JtlLog: ptestParam.ResJtl, JmxFile: ptestParam.FileName, LoadTime: ptestParam.LoadTime, HostIP: hostIP}
  515. return
  516. }
  517. //QueryTestNameNick query test nick name
  518. func QueryTestNameNick(TestName string, testNameNicks []string) (testNameNick string) {
  519. for _, testNameNickd := range testNameNicks {
  520. if strings.Contains(testNameNickd, TestName) {
  521. testNameNick = testNameNickd
  522. break
  523. }
  524. }
  525. return testNameNick
  526. }
  527. //IsUniqObject check whether object is unique
  528. func IsUniqObject(aa []string) (t bool) {
  529. for _, a := range aa {
  530. if a == aa[0] {
  531. t = true
  532. continue
  533. }
  534. if a != aa[0] {
  535. t = false
  536. break
  537. }
  538. }
  539. return t
  540. }
  541. //StringToSlice convert string to string slice
  542. func StringToSlice(str string) (strs []string) {
  543. strs = append(strs, str)
  544. return
  545. }
  546. //RemoveRepByMap 去除切片钟的重复元素
  547. func RemoveRepByMap(slc []string) (result []string) {
  548. tempMap := map[string]byte{} // 存放不重复主键
  549. for _, e := range slc {
  550. l := len(tempMap)
  551. tempMap[e] = 0
  552. if len(tempMap) != l { // 加入map后,map长度变化,则元素不重复
  553. result = append(result, e)
  554. }
  555. }
  556. return result
  557. }
  558. //SliceToString join slice elements to string
  559. func SliceToString(strs []string, inter string) (result string) {
  560. for _, str := range strs {
  561. result = result + inter + str
  562. }
  563. return string([]rune(result)[1:])
  564. }
  565. //QueryTestNamesByJmfile query test names by jmeter file
  566. func QueryTestNamesByJmfile(fileName string) (testNames []string) {
  567. var (
  568. buff []byte
  569. err error
  570. )
  571. if buff, err = ioutil.ReadFile(fileName); err != nil {
  572. log.Error("open script file failed! error %v", err)
  573. return
  574. }
  575. reg := regexp.MustCompile("SampleGui\"(.*)\" enabled=\"true")
  576. reg2 := regexp.MustCompile("testname=\"(.*)\" enabled=\"true")
  577. results := reg.FindAllString(string(buff), -1)
  578. for _, res := range results {
  579. resd := reg2.FindString(res)
  580. resdd := strings.Replace(resd, "\" enabled=\"true", "", -1)
  581. resddd := strings.Replace(resdd, "testname=\"", "", -1)
  582. testNames = append(testNames, resddd)
  583. }
  584. return
  585. }
  586. //ExistsInSlice check whether the string in the slice
  587. func ExistsInSlice(str string, strs []string) bool {
  588. for _, st := range strs {
  589. if st == str {
  590. return true
  591. }
  592. }
  593. return false
  594. }
  595. //PingDomain ping domain
  596. func PingDomain(ptestParam model.DoPtestParam) (pingString string) {
  597. var pingStrings []string
  598. if ptestParam.Type == model.PROTOCOL_HTTP {
  599. pingString = " ping -c 1 " + ptestParam.Domain + " |tee -a " + ptestParam.JmeterLog
  600. } else if ptestParam.Type == model.PROTOCOL_SCENE {
  601. for _, script := range ptestParam.Scripts {
  602. pingStrings = append(pingStrings, " ping -c 1 "+script.Domain+" |tee -a "+ptestParam.JmeterLog)
  603. }
  604. pingString = SliceToString(pingStrings, "&")
  605. }
  606. return
  607. }
  608. //CreateResJtlAndJmeterLog Create ResJt lAnd JmeterLog
  609. func CreateResJtlAndJmeterLog(ptestParam model.DoPtestParam) (ResJtlFile, JmeterLogFile *os.File, err error) {
  610. if ptestParam.ResJtl != "" {
  611. if ResJtlFile, err = os.Create(ptestParam.ResJtl); err != nil {
  612. log.Error("create ResJtl error :(%v)", err)
  613. return
  614. }
  615. ResJtlFile.WriteString("此处显示 err 日志")
  616. defer ResJtlFile.Close()
  617. }
  618. if ptestParam.JmeterLog != "" {
  619. if JmeterLogFile, err = os.Create(ptestParam.JmeterLog); err != nil {
  620. log.Error("create JmeterLog error :(%v)", err)
  621. return
  622. }
  623. JmeterLogFile.WriteString("此处显示启动日志,执行debug 则显示debug 日志")
  624. defer JmeterLogFile.Close()
  625. }
  626. return
  627. }
  628. //CreateCommand Create Command
  629. func (s *Service) CreateCommand(ptestParam model.DoPtestParam) (debug, CPUCore int, command string) {
  630. // ping 所有接口的 domain
  631. pingString := PingDomain(ptestParam)
  632. cpJar := ""
  633. if ptestParam.JarPath != "" {
  634. cpJar = fmt.Sprintf("cp %s %s & ", ptestParam.JarPath, s.c.Jmeter.JmeterExtLibPathContainer)
  635. }
  636. // 调试逻辑
  637. if ptestParam.IsDebug {
  638. CPUCore = s.c.Paas.CPUCoreDebug
  639. debug = 1
  640. command = cpJar + " mkdir /data/jmeter-log & jmeter -n -t " + ptestParam.FileName + " -j " + ptestParam.JmeterLog + " -l " + ptestParam.ResJtl + " -F ;" + pingString
  641. } else {
  642. CPUCore = s.c.Paas.CPUCore
  643. debug = -1
  644. command = cpJar + " mkdir /data/jmeter-log & jmeter -n -t " + ptestParam.FileName + " -j " + ptestParam.JmeterLog + " -l " + ptestParam.ResJtl + " -F"
  645. }
  646. return
  647. }