report.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "math"
  6. "sort"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "go-common/app/admin/ep/melloi/conf"
  11. "go-common/app/admin/ep/melloi/model"
  12. "go-common/library/log"
  13. )
  14. // QueryReportSummarys query report summary
  15. func (s *Service) QueryReportSummarys(c context.Context, sessionID string, qrsr *model.QueryReportSuRequest) (qrs *model.QueryReportSuResponse, err error) {
  16. // 获取服务树节点
  17. var treeNodes, treeNodesd []string
  18. if treeNodesd, err = s.QueryUserRoleNode(c, sessionID); err != nil {
  19. log.Error("QueryUserRoleNode (%v): ", err)
  20. return
  21. }
  22. treeNodes = append(treeNodesd, "")
  23. if ExistsInSlice(qrsr.Executor, conf.Conf.Melloi.Executor) {
  24. if qrs, err = s.dao.QueryReportSummarysWhiteName(&qrsr.ReportSummary, qrsr.SearchAll, qrsr.PageNum, qrsr.PageSize); err != nil {
  25. return
  26. }
  27. } else {
  28. if qrs, err = s.dao.QueryReportSummarys(&qrsr.ReportSummary, qrsr.SearchAll, qrsr.PageNum, qrsr.PageSize, treeNodes); err != nil {
  29. return
  30. }
  31. }
  32. // 获取label
  33. for _, report := range qrs.ReportSummarys {
  34. lr := model.LabelRelation{Type: model.ReportType, TargetID: int64(report.ID)}
  35. if report.Labels, err = s.dao.QueryLabelRelation(&lr); err != nil {
  36. return
  37. }
  38. }
  39. return
  40. }
  41. // QueryReportByID Query Report By ID
  42. func (s *Service) QueryReportByID(id int) (summary *model.ReportSummary, err error) {
  43. return s.dao.QueryReportSuryByID(id)
  44. }
  45. // CountQueryReportSummarys count query report summarys
  46. func (s *Service) CountQueryReportSummarys(reportSummary *model.ReportSummary) (int, error) {
  47. return s.dao.CountQueryReportSummarys(reportSummary)
  48. }
  49. // UpdateReportSummary update report summary
  50. func (s *Service) UpdateReportSummary(reportSummary *model.ReportSummary) (status string, err error) {
  51. if err = s.dao.UpdateReportSummary(reportSummary); err != nil {
  52. status = "update fail"
  53. return
  54. }
  55. status = "success"
  56. return
  57. }
  58. // UpdateReportStatus update report summary status
  59. func (s *Service) UpdateReportStatus(status int) error {
  60. return s.dao.UpdateReportStatus(status)
  61. }
  62. // AddReSummaryByPtest Add ReSummary By Ptest
  63. func (s *Service) AddReSummaryByPtest(ptestParam model.DoPtestParam, jobName, executeID string, testNameNicks []string, snapID, Debug int) (reportSuID int, err error) {
  64. reportSummary := model.ReportSummary{
  65. JobName: jobName,
  66. TestStatus: 2,
  67. UserName: ptestParam.UserName,
  68. ResJtl: ptestParam.ResJtl,
  69. JmeterLog: ptestParam.JmeterLog,
  70. Department: ptestParam.Department,
  71. Project: ptestParam.Project,
  72. APP: ptestParam.APP,
  73. ScriptID: ptestParam.ScriptID,
  74. DockerSum: 1,
  75. Active: 1,
  76. Debug: Debug,
  77. ScriptSnapID: snapID,
  78. ExecuteID: executeID,
  79. SceneID: ptestParam.SceneID,
  80. Type: ptestParam.Type,
  81. LoadTime: ptestParam.LoadTime,
  82. }
  83. //Upload==true,这里表示从前端上传的脚本,testNames 和 testNameNicks 长度可能大于1,需要遍历,写入 reportSummary
  84. if ptestParam.Upload {
  85. reportSummary.TestNameNick = SliceToString(testNameNicks, ",")
  86. reportSummary.TestName = ptestParam.ProjectName
  87. reportSummary.Type = model.PROTOCOL_SCENE
  88. }
  89. // 从页面上直接输入参数生成的单场景脚本,testNames 和 testNameNicks 长度都是 1
  90. // 生成的场景脚本,ptestParam.TestNameNick 不为空
  91. if !ptestParam.Upload {
  92. for _, testName := range ptestParam.TestNames {
  93. reportSummary.TestNameNick = QueryTestNameNick(testName, testNameNicks)
  94. reportSummary.TestName = testName
  95. }
  96. //场景脚本的 reportSummary 逻辑
  97. if ptestParam.Type == model.PROTOCOL_SCENE && ptestParam.TestNameNick != "" {
  98. reportSummary.TestNameNick = ptestParam.TestNameNick
  99. reportSummary.TestName = ptestParam.SceneName
  100. }
  101. }
  102. if reportSuID, err = s.dao.AddReportSummary(&reportSummary); err != nil {
  103. log.Error("s.dao.AddReportSummary err :(%v)", err)
  104. return
  105. }
  106. return
  107. }
  108. // AddReportSummary add report summary
  109. func (s *Service) AddReportSummary(reportSummary *model.ReportSummary) (status string, reportSuID int, err error) {
  110. var total int
  111. if total, err = s.dao.CountQueryReportSummarys(reportSummary); err != nil {
  112. log.Error("CountQueryReportSummarys error:(%v)", err)
  113. status = "fail"
  114. return
  115. }
  116. if (total == 1) || (reportSummary.TestName == "") {
  117. status = "数据已存在或者无接口名"
  118. } else {
  119. if reportSuID, err = s.dao.AddReportSummary(reportSummary); err != nil {
  120. status = "fail"
  121. return
  122. }
  123. status = "success"
  124. }
  125. return
  126. }
  127. // QueryReGraph query reGraph
  128. func (s *Service) QueryReGraph(testNameNicks []string) (reportGraphssd [][]model.ReportGraph, err error) {
  129. var (
  130. TestNames []string
  131. reportGraphss []model.ReportGraph
  132. reportGraphs []model.ReportGraph
  133. )
  134. if reportGraphs, err = s.dao.QueryReportGraph(testNameNicks); err != nil {
  135. log.Error("dao.QueryReportGraph error:(%v)", err)
  136. return
  137. }
  138. if len(reportGraphs) > 0 {
  139. for _, reportGraph := range reportGraphs {
  140. TestNames = append(TestNames, reportGraph.TestName)
  141. }
  142. TestNamesd := RemoveRepByMap(TestNames)
  143. for _, testName := range TestNamesd {
  144. for _, reportGraph := range reportGraphs {
  145. if reportGraph.TestName == testName {
  146. reportGraphss = append(reportGraphss, reportGraph)
  147. }
  148. }
  149. reportGraphssd = append(reportGraphssd, reportGraphss)
  150. reportGraphss = []model.ReportGraph{}
  151. }
  152. }
  153. return
  154. }
  155. // QueryClientMoni query client moni
  156. func (s *Service) QueryClientMoni(cli *model.ClientMoni) (clientMonisd [][]*model.ClientMoni, err error) {
  157. var (
  158. jobNames []string
  159. clientMoniss []*model.ClientMoni
  160. clientMonis []*model.ClientMoni
  161. )
  162. if clientMonis, err = s.dao.QueryClientMoni(cli); err != nil {
  163. log.Error("dao.QueryClientMoni error:(%v)", err)
  164. return
  165. }
  166. if len(clientMonis) > 0 {
  167. for _, clientMoni := range clientMonis {
  168. jobNames = append(jobNames, clientMoni.JobName)
  169. }
  170. jobNamesd := RemoveRepByMap(jobNames)
  171. for _, jobNamed := range jobNamesd {
  172. for _, clientMoni := range clientMonis {
  173. if clientMoni.JobName == jobNamed {
  174. clientMoniss = append(clientMoniss, clientMoni)
  175. }
  176. }
  177. clientMonisd = append(clientMonisd, clientMoniss)
  178. clientMoniss = []*model.ClientMoni{}
  179. }
  180. }
  181. return
  182. }
  183. //QueryReGraphAvg query reGraph
  184. func (s *Service) QueryReGraphAvg(testNameNicks []string) (reportGraphAvgs []model.ReportGraph, err error) {
  185. var reportGraphssd [][]model.ReportGraph
  186. if reportGraphssd, err = s.QueryReGraph(testNameNicks); err != nil {
  187. log.Error("QueryReGraph error :(%s)", err)
  188. return
  189. }
  190. for _, reportGraphsd := range reportGraphssd {
  191. reportGraph := ReportGraphAvg(reportGraphsd)
  192. reportGraphAvgs = append(reportGraphAvgs, reportGraph)
  193. }
  194. return
  195. }
  196. //ReportGraphAvg report graph avg
  197. func ReportGraphAvg(reportGraphs []model.ReportGraph) (reportGraph model.ReportGraph) {
  198. var sumTime, sumQPS, sumNetIo, min, max, sumCount, sumError, sumCodeEll, sumCodeWll, sumCodeWly, sumCodeWle, sumCodeWls,
  199. sumCodeSll, sumCodeSly, sumCodeSls, sumCodeKong, sumCodeNonHTTP, sumCodeOthers, fiftyTime, ninetyTime, ninetyFiveTime,
  200. ninetyNineTime, sumCode301, sumCode302, timeCount, sumQPSRecent, QPSRecent int
  201. var mins, maxs []int
  202. if len(reportGraphs) > 0 {
  203. for _, reportGraph := range reportGraphs {
  204. mins = append(mins, reportGraph.Min)
  205. maxs = append(maxs, reportGraph.Max)
  206. sumCount = sumCount + reportGraph.Count
  207. timeCount = reportGraph.Count * reportGraph.AvgTime
  208. sumTime = sumTime + timeCount
  209. sumError = sumError + reportGraph.Error
  210. sumQPS = sumQPS + reportGraph.QPS
  211. sumNetIo = sumNetIo + reportGraph.NetIo
  212. sumCodeEll = sumCodeEll + reportGraph.CodeEll
  213. sumCodeWll = sumCodeWll + reportGraph.CodeWll
  214. sumCodeWly = sumCodeWly + reportGraph.CodeWly
  215. sumCodeWle = sumCodeWle + reportGraph.CodeWle
  216. sumCodeWls = sumCodeWls + reportGraph.CodeWls
  217. sumCodeSll = sumCodeSll + reportGraph.CodeSll
  218. sumCodeSly = sumCodeSly + reportGraph.CodeSly
  219. sumCodeSls = sumCodeSls + reportGraph.CodeSls
  220. sumCodeKong = sumCodeKong + reportGraph.CodeKong
  221. sumCode301 = sumCode301 + reportGraph.Code301
  222. sumCode302 = sumCode302 + reportGraph.Code302
  223. sumCodeNonHTTP = sumCodeNonHTTP + reportGraph.CodeNonHTTP
  224. sumCodeOthers = sumCodeOthers + reportGraph.CodeOthers
  225. fiftyTime = fiftyTime + reportGraph.FiftyTime
  226. ninetyTime = ninetyTime + reportGraph.NinetyTime
  227. ninetyFiveTime = ninetyFiveTime + reportGraph.NinetyFiveTime
  228. ninetyNineTime = ninetyNineTime + reportGraph.NinetyNineTime
  229. }
  230. // 取最后 recent次统计的平均 qps,作为最近一段时间的qps
  231. recent := conf.Conf.Melloi.Recent
  232. if len(reportGraphs) > recent {
  233. for i := 1; i <= recent; i++ {
  234. sumQPSRecent += reportGraphs[len(reportGraphs)-i].QPS
  235. QPSRecent = sumQPSRecent / recent
  236. }
  237. } else {
  238. QPSRecent = sumQPS / len(reportGraphs)
  239. }
  240. if len(mins) != 0 {
  241. sort.Ints(mins)
  242. min = mins[0]
  243. sort.Ints(maxs)
  244. max = maxs[len(maxs)-1]
  245. }
  246. failPercentd := float64(sumError) * 100 / float64(sumCount)
  247. n10 := math.Pow10(3)
  248. fail := math.Trunc((failPercentd+0.5/n10)*n10) / n10
  249. failStr := strconv.FormatFloat(fail, 'f', -1, 64)
  250. failPercent := failStr + "%"
  251. num := len(reportGraphs)
  252. reportGraph = model.ReportGraph{
  253. TestName: reportGraphs[0].TestName, TestNameNick: reportGraphs[0].TestNameNick, Max: max, Min: min, Count: sumCount, Error: sumError,
  254. NetIo: sumNetIo / num, QPS: sumQPS / num, AvgTime: sumTime / sumCount, Ctime: reportGraphs[len(reportGraphs)-1].Ctime,
  255. CodeEll: sumCodeEll, CodeSll: sumCodeSll, CodeSly: sumCodeSly, CodeSls: sumCodeSls, CodeWll: sumCodeWll, CodeWly: sumCodeWly,
  256. CodeWle: sumCodeWle, CodeWls: sumCodeWls, CodeNonHTTP: sumCodeNonHTTP, CodeKong: sumCodeKong, CodeOthers: sumCodeOthers,
  257. FailPercent: failPercent, FiftyTime: fiftyTime / num, NinetyTime: ninetyTime / num, NinetyFiveTime: ninetyFiveTime / num,
  258. NinetyNineTime: ninetyNineTime / num, Code301: sumCode301, Code302: sumCode302, BeginTime: reportGraphs[0].Ctime, QpsRecent: QPSRecent,
  259. }
  260. }
  261. return
  262. }
  263. //addReGraphTimer add regraph timer
  264. func (s *Service) addReGraphTimer(c context.Context, addReGrapht model.AddReGraphTimer, res chan interface{}, timeout <-chan time.Time) {
  265. var (
  266. status = 1
  267. reportSummary model.ReportSummary
  268. testNamesd []string
  269. podNames []string
  270. beginTimed string
  271. afterTimed string
  272. beginTime = addReGrapht.BeginTime
  273. testNames = addReGrapht.TestNames
  274. jobName = addReGrapht.JobName
  275. token = addReGrapht.Token
  276. testNameNicks = addReGrapht.TestNameNicks
  277. RetMap *model.PaasJobQueryStatus
  278. scriptID = addReGrapht.ScriptID
  279. reportSuID = addReGrapht.ReportSuID
  280. ptestJobs []*model.PtestJob
  281. err error
  282. btm time.Time
  283. firstRetMap *model.PaasJobQueryStatus
  284. reportGraphs []model.ReportGraph
  285. JSON []byte
  286. fusingList = addReGrapht.FusingList
  287. useBusiStopList = addReGrapht.UseBusiStopList
  288. busiStopPercentList = addReGrapht.BusiStopPercentList
  289. )
  290. timer := time.NewTicker(5 * time.Second)
  291. done := make(chan bool, 1)
  292. num := 1
  293. go func() {
  294. defer close(res)
  295. a := 1
  296. for {
  297. if btm, err = time.Parse("2006-01-02 15:04:05", beginTime); err != nil {
  298. timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
  299. return
  300. }
  301. select {
  302. case <-timer.C:
  303. elapsedTime := (num - 1) * 5
  304. //实时当前任务的所有容器
  305. if ptestJobs, err = s.QueryOrStopAllPtestByJobName(context.TODO(), reportSuID, false, 3); err != nil {
  306. log.Error("get all Job err (%v)", err)
  307. }
  308. //遍历容器,并查询每个容器的cpu
  309. if len(ptestJobs) > 0 {
  310. for _, ptestJob := range ptestJobs {
  311. if RetMap, err = s.dao.Job(c, token, ptestJob.JobName); err != nil {
  312. log.Error("get job info err (%v)", err)
  313. }
  314. if RetMap != nil && len(RetMap.Data.Pods) > 0 {
  315. for _, pod := range RetMap.Data.Pods {
  316. podNames = append(podNames, pod.Name)
  317. log.Info("containerID :(%s)", pod.ContainerID)
  318. go s.addJobCPU(context.TODO(), pod, scriptID, reportSuID, elapsedTime, ptestJob.JobName)
  319. }
  320. }
  321. }
  322. }
  323. log.Info("podName :(%s)", podNames)
  324. if firstRetMap, err = s.dao.Job(c, token, jobName); err != nil {
  325. log.Error("查询容器状态 error-------(%v)", err)
  326. //接口报错,则删除所有压测容器
  327. timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
  328. return
  329. }
  330. if JSON, err = json.Marshal(firstRetMap); err != nil {
  331. timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
  332. }
  333. result := string(JSON)
  334. log.Info("查询容器状态:(%s)", result)
  335. if firstRetMap.Status == 400 {
  336. status = 3
  337. timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
  338. }
  339. if firstRetMap.Status == 200 && firstRetMap.Data.ActiveNum == 1 {
  340. log.Info("第(%d)次同步数据", a)
  341. if num == 1 {
  342. log.Info("job 执行参数 testName:(%s), beginTime :(%s),elapsedTime :(%d), num: (%d)", testNames, beginTime, elapsedTime, num)
  343. for index, testName := range testNames {
  344. testNameNick := QueryTestNameNick(testName, testNameNicks)
  345. reportGraphAdd := model.ReportGraphAdd{
  346. JobName: jobName,
  347. TestName: testName,
  348. BeginTime: beginTime,
  349. AfterTime: beginTime,
  350. TestNameNick: testNameNick,
  351. PodNames: podNames,
  352. ElapsedTime: elapsedTime,
  353. ReportSuID: reportSuID,
  354. UseBusinessStop: addReGrapht.UseBusinessStop,
  355. BusinessStopPercent: addReGrapht.BusinessStopPercent,
  356. }
  357. if addReGrapht.TestType == model.PROTOCOL_SCENE {
  358. reportGraphAdd.Fusing = fusingList[index]
  359. reportGraphAdd.UseBusinessStop = useBusiStopList[index]
  360. reportGraphAdd.BusinessStopPercent = busiStopPercentList[index]
  361. } else {
  362. reportGraphAdd.Fusing = addReGrapht.Fusing
  363. }
  364. go s.addReportGraph(context.TODO(), reportGraphAdd)
  365. }
  366. } else {
  367. for i := 1; i <= num-1; i++ {
  368. btm = btm.Add(time.Second * 5)
  369. aft := btm.Add(time.Second * 2)
  370. beginTimed = btm.Format("2006-01-02 15:04:05")
  371. afterTimed = aft.Format("2006-01-02 15:04:05")
  372. }
  373. log.Info("job 执行参数 testName:(%s),beginTime :(%s),elapsedTime :(%d)", testNames, beginTimed, elapsedTime)
  374. for index, testName := range testNames {
  375. testNameNick := QueryTestNameNick(testName, testNameNicks)
  376. reportGraphAdd := model.ReportGraphAdd{
  377. JobName: jobName,
  378. TestName: testName,
  379. BeginTime: beginTimed,
  380. AfterTime: afterTimed,
  381. TestNameNick: testNameNick,
  382. PodNames: podNames,
  383. ElapsedTime: elapsedTime,
  384. ReportSuID: reportSuID,
  385. UseBusinessStop: addReGrapht.UseBusinessStop,
  386. BusinessStopPercent: addReGrapht.BusinessStopPercent,
  387. }
  388. if addReGrapht.TestType == model.PROTOCOL_SCENE {
  389. reportGraphAdd.Fusing = fusingList[index]
  390. reportGraphAdd.UseBusinessStop = useBusiStopList[index]
  391. reportGraphAdd.BusinessStopPercent = busiStopPercentList[index]
  392. } else {
  393. reportGraphAdd.Fusing = addReGrapht.Fusing
  394. }
  395. go s.addReportGraph(context.TODO(), reportGraphAdd)
  396. }
  397. }
  398. }
  399. podNames = []string{}
  400. if firstRetMap.Status == 200 && firstRetMap.Data.ActiveNum == 0 {
  401. timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
  402. }
  403. num++
  404. res <- a
  405. a++
  406. case <-timeout:
  407. close(done)
  408. log.Info("real stop time (%s)", time.Now().Format("2006-01-02 15:04:05"))
  409. // 关闭所有压测该项目或者接口的容器
  410. go s.QueryOrStopAllPtestByJobName(context.TODO(), reportSuID, true, status)
  411. if reportGraphs, err = s.dao.QueryReportGraph(testNameNicks); err != nil {
  412. log.Error("query reportGraphs error :(%v) ", err)
  413. return
  414. }
  415. for _, reportGraph := range reportGraphs {
  416. testNamesd = append(testNames, reportGraph.TestName)
  417. }
  418. // 如果reportGraphs 的成员都是同一个testName ,则执行如下代码,表示进行结果合并,生成 reportSummary
  419. if IsUniqObject(testNamesd) {
  420. if len(reportGraphs) > 0 {
  421. reportGraph := ReportGraphAvg(reportGraphs)
  422. reportSummary = model.ReportSummary{
  423. ID: reportSuID,
  424. TestName: reportGraph.TestName,
  425. TestNameNick: reportGraph.TestNameNick,
  426. Count: reportGraph.Count,
  427. Error: reportGraph.Error,
  428. QPS: reportGraph.QPS,
  429. AvgTime: reportGraph.AvgTime,
  430. NetIo: reportGraph.NetIo,
  431. Min: reportGraph.Min,
  432. Max: reportGraph.Max,
  433. }
  434. reportSummary.TestStatus = status
  435. } else {
  436. log.Info("sorry,your test duration is too short ..... ")
  437. reportSummary = model.ReportSummary{ID: reportSuID, TestStatus: 3}
  438. }
  439. s.dao.UpdateReportSummary(&reportSummary)
  440. }
  441. //场景压测、多个接口走该逻辑
  442. if !IsUniqObject(testNamesd) && len(testNameNicks) > 0 {
  443. if len(reportGraphs) > 0 {
  444. reportSummary = model.ReportSummary{ID: reportSuID, TestStatus: status}
  445. } else {
  446. reportSummary = model.ReportSummary{ID: reportSuID, TestStatus: 3}
  447. }
  448. }
  449. s.dao.UpdateReportSummary(&reportSummary)
  450. return
  451. }
  452. }
  453. }()
  454. <-done
  455. }
  456. //addPtestJobHostIp add regraph timer
  457. func (s *Service) addPtestJobHostIp(c context.Context, addReGrapht model.AddReGraphTimer, res chan interface{}, timeout <-chan time.Time) {
  458. var (
  459. RetMap *model.PaasJobQueryStatus
  460. token = addReGrapht.Token
  461. err error
  462. ptestJobs []*model.PtestJob
  463. ptestJobsd []*model.PtestJob
  464. firstRetMap *model.PaasJobQueryStatus
  465. )
  466. timer := time.NewTicker(10 * time.Second)
  467. done := make(chan bool, 1)
  468. go func() {
  469. defer close(res)
  470. a := 1
  471. for {
  472. select {
  473. case <-timer.C:
  474. if firstRetMap, err = s.dao.Job(c, token, addReGrapht.JobName); err != nil {
  475. log.Error("查询容器状态 error-------(%v)", err)
  476. //接口报错,则删除所有压测容器
  477. return
  478. }
  479. if firstRetMap == nil || firstRetMap.Status == 400 || (firstRetMap.Status == 200 && firstRetMap.Data.ActiveNum == 0) {
  480. return
  481. }
  482. ptestJob := model.PtestJob{ReportSuID: addReGrapht.ReportSuID, Active: 1}
  483. if ptestJobs, err = s.dao.QueryPtestJob(&ptestJob); err != nil {
  484. return
  485. }
  486. for _, job := range ptestJobs {
  487. if job.HostIP == "" || job.JobIP == "" || job.JobID == "" {
  488. ptestJobsd = append(ptestJobsd, job)
  489. }
  490. }
  491. if len(ptestJobsd) > 0 {
  492. for _, ptestJob := range ptestJobsd {
  493. //查询容器状态
  494. if RetMap, err = s.dao.Job(c, token, ptestJob.JobName); err != nil {
  495. log.Error("get job info err (%v)", err)
  496. }
  497. if RetMap != nil && len(RetMap.Data.Pods) > 0 {
  498. for _, pod := range RetMap.Data.Pods {
  499. ptestjo := model.PtestJob{ID: ptestJob.ID, HostIP: pod.HostIP, JobID: pod.ContainerID, JobIP: pod.IP}
  500. //更新容器hostIp
  501. s.dao.UpdatePtestJob(ptestjo)
  502. }
  503. }
  504. }
  505. }
  506. res <- a
  507. a++
  508. case <-timeout:
  509. close(done)
  510. return
  511. }
  512. }
  513. }()
  514. <-done
  515. }
  516. //addJobCPU job cpu
  517. func (s *Service) addJobCPU(c context.Context, pod model.PodInfo, scriptID, reportSuID, elapsedTime int, jobName string) (err error) {
  518. var (
  519. clientMoni = model.ClientMoni{
  520. ScriptID: scriptID,
  521. ReportSuID: reportSuID,
  522. JobName: jobName,
  523. JobNameAll: pod.Name,
  524. ElapsdTime: elapsedTime,
  525. }
  526. dockerStats *model.DockerStats
  527. CPUResult *model.PaasQueryJobCPUResult
  528. )
  529. //首先查我们自己的容器cpu 获取服务
  530. if pod.ContainerID != "" {
  531. if dockerStats, err = s.QueryJobCPUByEP(context.TODO(), pod.ContainerID, pod.HostIP); err != nil {
  532. log.Error("query CPU err ...(%s)", err)
  533. }
  534. if dockerStats != nil && dockerStats.CPU != "" {
  535. cpu := strings.Replace(dockerStats.CPU, "%", "", 1)
  536. cpufloat, _ := strconv.ParseFloat(cpu, 32)
  537. cpuFinal := cpufloat
  538. cpuString := strconv.FormatFloat(cpuFinal, 'f', -1, 32)
  539. clientMoni.CPUUsed = cpuString
  540. }
  541. if dockerStats == nil || dockerStats.CPU == "" {
  542. //如果我们的服务挂了,就查 moni
  543. if CPUResult, err = s.QueryJobCPU(context.TODO(), pod.Name); err != nil {
  544. log.Error("query client cpu err(%v)", err)
  545. return
  546. }
  547. if len(CPUResult.Data) > 0 {
  548. for _, data := range CPUResult.Data {
  549. if len(data.Value) > 1 {
  550. clientMoni.CPUUsed = data.Value[1].(string)
  551. }
  552. }
  553. }
  554. }
  555. }
  556. //cpu 信息记录到数据库
  557. if _, err = s.AddClientMoni(&clientMoni); err != nil {
  558. log.Error("add ClientMoni err(%v)", err)
  559. return
  560. }
  561. return
  562. }
  563. //addReportGraph add reportGraph
  564. func (s *Service) addReportGraph(c context.Context, reportGraphAdd model.ReportGraphAdd) {
  565. var (
  566. sumTime, sumQPS, sumNetIo, sumCodeEll, sumCodeWll, sumCodeWly, sumCodeWle, sumCodeWls, sumCodeSll, sumCodeSly, sumCodeSls,
  567. sumCodeKong, sumCodeNonHTTP, sumCodeOthers, sumCount, sumError, sumThreads, fiftyTime, ninetyTime, ninetyFiveTime,
  568. timeCount, ninetyNineTime, sumCode301, sumCode302 int
  569. mins, maxs []int
  570. reportTimelys []*model.ReportTimely
  571. err error
  572. )
  573. busiStopPerc := reportGraphAdd.BusinessStopPercent
  574. if reportTimelys, err = s.dao.QueryReTimely(reportGraphAdd.TestName, reportGraphAdd.BeginTime, reportGraphAdd.AfterTime, reportGraphAdd.PodNames); err != nil {
  575. return
  576. }
  577. log.Info("------reportTimelys:(%v)", reportTimelys)
  578. if len(reportTimelys) > 0 {
  579. for _, reportTimely := range reportTimelys {
  580. mins = append(mins, reportTimely.Min)
  581. maxs = append(maxs, reportTimely.Max)
  582. sumCount = sumCount + reportTimely.Count
  583. //计算一个容器的接口响应总时间
  584. timeCount = reportTimely.Count * reportTimely.AvgTime
  585. //计算所有容器的接口响应时间
  586. sumTime = sumTime + timeCount
  587. sumQPS = sumQPS + reportTimely.QPS
  588. sumError = sumError + reportTimely.Error
  589. sumNetIo = sumNetIo + reportTimely.NetIo
  590. sumCodeEll = sumCodeEll + reportTimely.CodeEll
  591. sumCodeWll = sumCodeWll + reportTimely.CodeWll
  592. sumCodeWly = sumCodeWly + reportTimely.CodeWly
  593. sumCodeWle = sumCodeWle + reportTimely.CodeWle
  594. sumCodeWls = sumCodeWls + reportTimely.CodeWls
  595. sumCodeSll = sumCodeSll + reportTimely.CodeSll
  596. sumCodeSly = sumCodeSly + reportTimely.CodeSly
  597. sumCodeSls = sumCodeSls + reportTimely.CodeSls
  598. sumCodeKong = sumCodeKong + reportTimely.CodeKong
  599. sumCodeNonHTTP = sumCodeNonHTTP + reportTimely.CodeNonHTTP
  600. sumCodeOthers = sumCodeOthers + reportTimely.CodeOthers
  601. sumCode301 = sumCode301 + reportTimely.Code301
  602. sumCode302 = sumCode302 + reportTimely.Code302
  603. sumThreads = sumThreads + reportTimely.ThreadsSum
  604. fiftyTime = fiftyTime + reportTimely.FiftyTime
  605. ninetyTime = ninetyTime + reportTimely.NinetyTime
  606. ninetyFiveTime = ninetyFiveTime + reportTimely.NinetyFiveTime
  607. ninetyNineTime = ninetyNineTime + reportTimely.NinetyNineTime
  608. }
  609. sort.Ints(mins)
  610. min := mins[0]
  611. sort.Ints(maxs)
  612. max := maxs[len(maxs)-1]
  613. log.Info("test_nick_name ----- :(%s)", reportGraphAdd.TestNameNick)
  614. reportGraph := model.ReportGraph{
  615. TestName: reportGraphAdd.TestName, TestNameNick: reportGraphAdd.TestNameNick,
  616. Count: sumCount,
  617. QPS: sumQPS,
  618. Error: sumError,
  619. AvgTime: sumTime / sumCount,
  620. NetIo: sumNetIo,
  621. Min: min,
  622. Max: max,
  623. ElapsdTime: reportGraphAdd.ElapsedTime,
  624. CodeEll: sumCodeEll,
  625. CodeWll: sumCodeWll,
  626. CodeWly: sumCodeWly,
  627. CodeWle: sumCodeWle,
  628. CodeWls: sumCodeWls,
  629. CodeSll: sumCodeSll,
  630. CodeSly: sumCodeSly,
  631. CodeSls: sumCodeSls,
  632. CodeKong: sumCodeKong,
  633. CodeNonHTTP: sumCodeNonHTTP,
  634. CodeOthers: sumCodeOthers,
  635. ThreadsSum: sumThreads,
  636. FiftyTime: fiftyTime / len(reportTimelys),
  637. NinetyTime: ninetyTime / len(reportTimelys),
  638. NinetyFiveTime: ninetyFiveTime / len(reportTimelys),
  639. NinetyNineTime: ninetyNineTime / len(reportTimelys),
  640. Code301: sumCode301,
  641. Code302: sumCode302,
  642. }
  643. suCodeRate, suBusinessRate := CalcuSuccess(reportGraph)
  644. if reportGraphAdd.Fusing == 0 {
  645. reportGraphAdd.Fusing = conf.Conf.Melloi.DefaultFusing
  646. }
  647. //压测熔断
  648. //使用业务熔断,只要http code 和 业务断言错误满足一条阈值,则熔断
  649. if reportGraphAdd.UseBusinessStop {
  650. if busiStopPerc == 0 {
  651. busiStopPerc = conf.Conf.Melloi.DefaultBusinessRate
  652. }
  653. if suCodeRate < reportGraphAdd.Fusing || suBusinessRate < busiStopPerc {
  654. log.Info("接口失败率超过设置阈值,执行自动熔断,jobName :(%s)", reportGraphAdd.JobName)
  655. if _, err = s.DeleteJob(c, reportGraphAdd.JobName); err != nil {
  656. return
  657. }
  658. reportsu := model.ReportSummary{ID: reportGraphAdd.ReportSuID, IsFusing: true, BusinessValue: busiStopPerc, UseBusinessStop: reportGraphAdd.UseBusinessStop,
  659. FusingTestName: reportGraphAdd.TestName, SuccessCodeRate: suCodeRate, SuccessBusinessRate: suBusinessRate, FusingValue: reportGraphAdd.Fusing}
  660. s.dao.UpdateReportSummary(&reportsu)
  661. }
  662. } else { //不使用业务熔断
  663. if suCodeRate < reportGraphAdd.Fusing {
  664. log.Info("接口失败率超过设置阈值,执行自动熔断,jobName :(%s)", reportGraphAdd.JobName)
  665. if _, err = s.DeleteJob(c, reportGraphAdd.JobName); err != nil {
  666. return
  667. }
  668. reportsu := model.ReportSummary{ID: reportGraphAdd.ReportSuID, IsFusing: true, BusinessValue: busiStopPerc,
  669. FusingTestName: reportGraphAdd.TestName, SuccessCodeRate: suCodeRate, SuccessBusinessRate: suBusinessRate, FusingValue: reportGraphAdd.Fusing}
  670. s.dao.UpdateReportSummary(&reportsu)
  671. }
  672. }
  673. s.dao.AddReportGraph(&reportGraph)
  674. return
  675. }
  676. }
  677. //CalcuSuccess calcu success
  678. func CalcuSuccess(reportGraph model.ReportGraph) (successCodeRate, successBusinessRate int) {
  679. success := reportGraph.CodeEll + reportGraph.CodeKong + reportGraph.Code301 + reportGraph.Code302
  680. successCodeRate = success * 100 / reportGraph.Count
  681. successBusinessRate = (reportGraph.Count - reportGraph.Error) * 100 / reportGraph.Count
  682. return
  683. }
  684. // DelReportSummary delete report summary
  685. func (s *Service) DelReportSummary(id int) error {
  686. return s.dao.DelReportSummary(id)
  687. }