2019-04-22 02:59:20 +00:00

714 lines
26 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"encoding/json"
"math"
"sort"
"strconv"
"strings"
"time"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/model"
"go-common/library/log"
)
// QueryReportSummarys query report summary
func (s *Service) QueryReportSummarys(c context.Context, sessionID string, qrsr *model.QueryReportSuRequest) (qrs *model.QueryReportSuResponse, err error) {
// 获取服务树节点
var treeNodes, treeNodesd []string
if treeNodesd, err = s.QueryUserRoleNode(c, sessionID); err != nil {
log.Error("QueryUserRoleNode (%v): ", err)
return
}
treeNodes = append(treeNodesd, "")
if ExistsInSlice(qrsr.Executor, conf.Conf.Melloi.Executor) {
if qrs, err = s.dao.QueryReportSummarysWhiteName(&qrsr.ReportSummary, qrsr.SearchAll, qrsr.PageNum, qrsr.PageSize); err != nil {
return
}
} else {
if qrs, err = s.dao.QueryReportSummarys(&qrsr.ReportSummary, qrsr.SearchAll, qrsr.PageNum, qrsr.PageSize, treeNodes); err != nil {
return
}
}
// 获取label
for _, report := range qrs.ReportSummarys {
lr := model.LabelRelation{Type: model.ReportType, TargetID: int64(report.ID)}
if report.Labels, err = s.dao.QueryLabelRelation(&lr); err != nil {
return
}
}
return
}
// QueryReportByID Query Report By ID
func (s *Service) QueryReportByID(id int) (summary *model.ReportSummary, err error) {
return s.dao.QueryReportSuryByID(id)
}
// CountQueryReportSummarys count query report summarys
func (s *Service) CountQueryReportSummarys(reportSummary *model.ReportSummary) (int, error) {
return s.dao.CountQueryReportSummarys(reportSummary)
}
// UpdateReportSummary update report summary
func (s *Service) UpdateReportSummary(reportSummary *model.ReportSummary) (status string, err error) {
if err = s.dao.UpdateReportSummary(reportSummary); err != nil {
status = "update fail"
return
}
status = "success"
return
}
// UpdateReportStatus update report summary status
func (s *Service) UpdateReportStatus(status int) error {
return s.dao.UpdateReportStatus(status)
}
// AddReSummaryByPtest Add ReSummary By Ptest
func (s *Service) AddReSummaryByPtest(ptestParam model.DoPtestParam, jobName, executeID string, testNameNicks []string, snapID, Debug int) (reportSuID int, err error) {
reportSummary := model.ReportSummary{
JobName: jobName,
TestStatus: 2,
UserName: ptestParam.UserName,
ResJtl: ptestParam.ResJtl,
JmeterLog: ptestParam.JmeterLog,
Department: ptestParam.Department,
Project: ptestParam.Project,
APP: ptestParam.APP,
ScriptID: ptestParam.ScriptID,
DockerSum: 1,
Active: 1,
Debug: Debug,
ScriptSnapID: snapID,
ExecuteID: executeID,
SceneID: ptestParam.SceneID,
Type: ptestParam.Type,
LoadTime: ptestParam.LoadTime,
}
//Upload==true这里表示从前端上传的脚本testNames 和 testNameNicks 长度可能大于1需要遍历写入 reportSummary
if ptestParam.Upload {
reportSummary.TestNameNick = SliceToString(testNameNicks, ",")
reportSummary.TestName = ptestParam.ProjectName
reportSummary.Type = model.PROTOCOL_SCENE
}
// 从页面上直接输入参数生成的单场景脚本testNames 和 testNameNicks 长度都是 1
// 生成的场景脚本ptestParam.TestNameNick 不为空
if !ptestParam.Upload {
for _, testName := range ptestParam.TestNames {
reportSummary.TestNameNick = QueryTestNameNick(testName, testNameNicks)
reportSummary.TestName = testName
}
//场景脚本的 reportSummary 逻辑
if ptestParam.Type == model.PROTOCOL_SCENE && ptestParam.TestNameNick != "" {
reportSummary.TestNameNick = ptestParam.TestNameNick
reportSummary.TestName = ptestParam.SceneName
}
}
if reportSuID, err = s.dao.AddReportSummary(&reportSummary); err != nil {
log.Error("s.dao.AddReportSummary err :(%v)", err)
return
}
return
}
// AddReportSummary add report summary
func (s *Service) AddReportSummary(reportSummary *model.ReportSummary) (status string, reportSuID int, err error) {
var total int
if total, err = s.dao.CountQueryReportSummarys(reportSummary); err != nil {
log.Error("CountQueryReportSummarys error:(%v)", err)
status = "fail"
return
}
if (total == 1) || (reportSummary.TestName == "") {
status = "数据已存在或者无接口名"
} else {
if reportSuID, err = s.dao.AddReportSummary(reportSummary); err != nil {
status = "fail"
return
}
status = "success"
}
return
}
// QueryReGraph query reGraph
func (s *Service) QueryReGraph(testNameNicks []string) (reportGraphssd [][]model.ReportGraph, err error) {
var (
TestNames []string
reportGraphss []model.ReportGraph
reportGraphs []model.ReportGraph
)
if reportGraphs, err = s.dao.QueryReportGraph(testNameNicks); err != nil {
log.Error("dao.QueryReportGraph error:(%v)", err)
return
}
if len(reportGraphs) > 0 {
for _, reportGraph := range reportGraphs {
TestNames = append(TestNames, reportGraph.TestName)
}
TestNamesd := RemoveRepByMap(TestNames)
for _, testName := range TestNamesd {
for _, reportGraph := range reportGraphs {
if reportGraph.TestName == testName {
reportGraphss = append(reportGraphss, reportGraph)
}
}
reportGraphssd = append(reportGraphssd, reportGraphss)
reportGraphss = []model.ReportGraph{}
}
}
return
}
// QueryClientMoni query client moni
func (s *Service) QueryClientMoni(cli *model.ClientMoni) (clientMonisd [][]*model.ClientMoni, err error) {
var (
jobNames []string
clientMoniss []*model.ClientMoni
clientMonis []*model.ClientMoni
)
if clientMonis, err = s.dao.QueryClientMoni(cli); err != nil {
log.Error("dao.QueryClientMoni error:(%v)", err)
return
}
if len(clientMonis) > 0 {
for _, clientMoni := range clientMonis {
jobNames = append(jobNames, clientMoni.JobName)
}
jobNamesd := RemoveRepByMap(jobNames)
for _, jobNamed := range jobNamesd {
for _, clientMoni := range clientMonis {
if clientMoni.JobName == jobNamed {
clientMoniss = append(clientMoniss, clientMoni)
}
}
clientMonisd = append(clientMonisd, clientMoniss)
clientMoniss = []*model.ClientMoni{}
}
}
return
}
//QueryReGraphAvg query reGraph
func (s *Service) QueryReGraphAvg(testNameNicks []string) (reportGraphAvgs []model.ReportGraph, err error) {
var reportGraphssd [][]model.ReportGraph
if reportGraphssd, err = s.QueryReGraph(testNameNicks); err != nil {
log.Error("QueryReGraph error :(%s)", err)
return
}
for _, reportGraphsd := range reportGraphssd {
reportGraph := ReportGraphAvg(reportGraphsd)
reportGraphAvgs = append(reportGraphAvgs, reportGraph)
}
return
}
//ReportGraphAvg report graph avg
func ReportGraphAvg(reportGraphs []model.ReportGraph) (reportGraph model.ReportGraph) {
var sumTime, sumQPS, sumNetIo, min, max, sumCount, sumError, sumCodeEll, sumCodeWll, sumCodeWly, sumCodeWle, sumCodeWls,
sumCodeSll, sumCodeSly, sumCodeSls, sumCodeKong, sumCodeNonHTTP, sumCodeOthers, fiftyTime, ninetyTime, ninetyFiveTime,
ninetyNineTime, sumCode301, sumCode302, timeCount, sumQPSRecent, QPSRecent int
var mins, maxs []int
if len(reportGraphs) > 0 {
for _, reportGraph := range reportGraphs {
mins = append(mins, reportGraph.Min)
maxs = append(maxs, reportGraph.Max)
sumCount = sumCount + reportGraph.Count
timeCount = reportGraph.Count * reportGraph.AvgTime
sumTime = sumTime + timeCount
sumError = sumError + reportGraph.Error
sumQPS = sumQPS + reportGraph.QPS
sumNetIo = sumNetIo + reportGraph.NetIo
sumCodeEll = sumCodeEll + reportGraph.CodeEll
sumCodeWll = sumCodeWll + reportGraph.CodeWll
sumCodeWly = sumCodeWly + reportGraph.CodeWly
sumCodeWle = sumCodeWle + reportGraph.CodeWle
sumCodeWls = sumCodeWls + reportGraph.CodeWls
sumCodeSll = sumCodeSll + reportGraph.CodeSll
sumCodeSly = sumCodeSly + reportGraph.CodeSly
sumCodeSls = sumCodeSls + reportGraph.CodeSls
sumCodeKong = sumCodeKong + reportGraph.CodeKong
sumCode301 = sumCode301 + reportGraph.Code301
sumCode302 = sumCode302 + reportGraph.Code302
sumCodeNonHTTP = sumCodeNonHTTP + reportGraph.CodeNonHTTP
sumCodeOthers = sumCodeOthers + reportGraph.CodeOthers
fiftyTime = fiftyTime + reportGraph.FiftyTime
ninetyTime = ninetyTime + reportGraph.NinetyTime
ninetyFiveTime = ninetyFiveTime + reportGraph.NinetyFiveTime
ninetyNineTime = ninetyNineTime + reportGraph.NinetyNineTime
}
// 取最后 recent次统计的平均 qps作为最近一段时间的qps
recent := conf.Conf.Melloi.Recent
if len(reportGraphs) > recent {
for i := 1; i <= recent; i++ {
sumQPSRecent += reportGraphs[len(reportGraphs)-i].QPS
QPSRecent = sumQPSRecent / recent
}
} else {
QPSRecent = sumQPS / len(reportGraphs)
}
if len(mins) != 0 {
sort.Ints(mins)
min = mins[0]
sort.Ints(maxs)
max = maxs[len(maxs)-1]
}
failPercentd := float64(sumError) * 100 / float64(sumCount)
n10 := math.Pow10(3)
fail := math.Trunc((failPercentd+0.5/n10)*n10) / n10
failStr := strconv.FormatFloat(fail, 'f', -1, 64)
failPercent := failStr + "%"
num := len(reportGraphs)
reportGraph = model.ReportGraph{
TestName: reportGraphs[0].TestName, TestNameNick: reportGraphs[0].TestNameNick, Max: max, Min: min, Count: sumCount, Error: sumError,
NetIo: sumNetIo / num, QPS: sumQPS / num, AvgTime: sumTime / sumCount, Ctime: reportGraphs[len(reportGraphs)-1].Ctime,
CodeEll: sumCodeEll, CodeSll: sumCodeSll, CodeSly: sumCodeSly, CodeSls: sumCodeSls, CodeWll: sumCodeWll, CodeWly: sumCodeWly,
CodeWle: sumCodeWle, CodeWls: sumCodeWls, CodeNonHTTP: sumCodeNonHTTP, CodeKong: sumCodeKong, CodeOthers: sumCodeOthers,
FailPercent: failPercent, FiftyTime: fiftyTime / num, NinetyTime: ninetyTime / num, NinetyFiveTime: ninetyFiveTime / num,
NinetyNineTime: ninetyNineTime / num, Code301: sumCode301, Code302: sumCode302, BeginTime: reportGraphs[0].Ctime, QpsRecent: QPSRecent,
}
}
return
}
//addReGraphTimer add regraph timer
func (s *Service) addReGraphTimer(c context.Context, addReGrapht model.AddReGraphTimer, res chan interface{}, timeout <-chan time.Time) {
var (
status = 1
reportSummary model.ReportSummary
testNamesd []string
podNames []string
beginTimed string
afterTimed string
beginTime = addReGrapht.BeginTime
testNames = addReGrapht.TestNames
jobName = addReGrapht.JobName
token = addReGrapht.Token
testNameNicks = addReGrapht.TestNameNicks
RetMap *model.PaasJobQueryStatus
scriptID = addReGrapht.ScriptID
reportSuID = addReGrapht.ReportSuID
ptestJobs []*model.PtestJob
err error
btm time.Time
firstRetMap *model.PaasJobQueryStatus
reportGraphs []model.ReportGraph
JSON []byte
fusingList = addReGrapht.FusingList
useBusiStopList = addReGrapht.UseBusiStopList
busiStopPercentList = addReGrapht.BusiStopPercentList
)
timer := time.NewTicker(5 * time.Second)
done := make(chan bool, 1)
num := 1
go func() {
defer close(res)
a := 1
for {
if btm, err = time.Parse("2006-01-02 15:04:05", beginTime); err != nil {
timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
return
}
select {
case <-timer.C:
elapsedTime := (num - 1) * 5
//实时当前任务的所有容器
if ptestJobs, err = s.QueryOrStopAllPtestByJobName(context.TODO(), reportSuID, false, 3); err != nil {
log.Error("get all Job err (%v)", err)
}
//遍历容器并查询每个容器的cpu
if len(ptestJobs) > 0 {
for _, ptestJob := range ptestJobs {
if RetMap, err = s.dao.Job(c, token, ptestJob.JobName); err != nil {
log.Error("get job info err (%v)", err)
}
if RetMap != nil && len(RetMap.Data.Pods) > 0 {
for _, pod := range RetMap.Data.Pods {
podNames = append(podNames, pod.Name)
log.Info("containerID :(%s)", pod.ContainerID)
go s.addJobCPU(context.TODO(), pod, scriptID, reportSuID, elapsedTime, ptestJob.JobName)
}
}
}
}
log.Info("podName :(%s)", podNames)
if firstRetMap, err = s.dao.Job(c, token, jobName); err != nil {
log.Error("查询容器状态 error-------(%v)", err)
//接口报错,则删除所有压测容器
timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
return
}
if JSON, err = json.Marshal(firstRetMap); err != nil {
timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
}
result := string(JSON)
log.Info("查询容器状态:(%s)", result)
if firstRetMap.Status == 400 {
status = 3
timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
}
if firstRetMap.Status == 200 && firstRetMap.Data.ActiveNum == 1 {
log.Info("第(%d)次同步数据", a)
if num == 1 {
log.Info("job 执行参数 testName:(%s), beginTime :(%s),elapsedTime :(%d), num: (%d)", testNames, beginTime, elapsedTime, num)
for index, testName := range testNames {
testNameNick := QueryTestNameNick(testName, testNameNicks)
reportGraphAdd := model.ReportGraphAdd{
JobName: jobName,
TestName: testName,
BeginTime: beginTime,
AfterTime: beginTime,
TestNameNick: testNameNick,
PodNames: podNames,
ElapsedTime: elapsedTime,
ReportSuID: reportSuID,
UseBusinessStop: addReGrapht.UseBusinessStop,
BusinessStopPercent: addReGrapht.BusinessStopPercent,
}
if addReGrapht.TestType == model.PROTOCOL_SCENE {
reportGraphAdd.Fusing = fusingList[index]
reportGraphAdd.UseBusinessStop = useBusiStopList[index]
reportGraphAdd.BusinessStopPercent = busiStopPercentList[index]
} else {
reportGraphAdd.Fusing = addReGrapht.Fusing
}
go s.addReportGraph(context.TODO(), reportGraphAdd)
}
} else {
for i := 1; i <= num-1; i++ {
btm = btm.Add(time.Second * 5)
aft := btm.Add(time.Second * 2)
beginTimed = btm.Format("2006-01-02 15:04:05")
afterTimed = aft.Format("2006-01-02 15:04:05")
}
log.Info("job 执行参数 testName:(%s),beginTime :(%s),elapsedTime :(%d)", testNames, beginTimed, elapsedTime)
for index, testName := range testNames {
testNameNick := QueryTestNameNick(testName, testNameNicks)
reportGraphAdd := model.ReportGraphAdd{
JobName: jobName,
TestName: testName,
BeginTime: beginTimed,
AfterTime: afterTimed,
TestNameNick: testNameNick,
PodNames: podNames,
ElapsedTime: elapsedTime,
ReportSuID: reportSuID,
UseBusinessStop: addReGrapht.UseBusinessStop,
BusinessStopPercent: addReGrapht.BusinessStopPercent,
}
if addReGrapht.TestType == model.PROTOCOL_SCENE {
reportGraphAdd.Fusing = fusingList[index]
reportGraphAdd.UseBusinessStop = useBusiStopList[index]
reportGraphAdd.BusinessStopPercent = busiStopPercentList[index]
} else {
reportGraphAdd.Fusing = addReGrapht.Fusing
}
go s.addReportGraph(context.TODO(), reportGraphAdd)
}
}
}
podNames = []string{}
if firstRetMap.Status == 200 && firstRetMap.Data.ActiveNum == 0 {
timeout = time.After(time.Until(time.Now().Add(1 * time.Second)))
}
num++
res <- a
a++
case <-timeout:
close(done)
log.Info("real stop time (%s)", time.Now().Format("2006-01-02 15:04:05"))
// 关闭所有压测该项目或者接口的容器
go s.QueryOrStopAllPtestByJobName(context.TODO(), reportSuID, true, status)
if reportGraphs, err = s.dao.QueryReportGraph(testNameNicks); err != nil {
log.Error("query reportGraphs error :(%v) ", err)
return
}
for _, reportGraph := range reportGraphs {
testNamesd = append(testNames, reportGraph.TestName)
}
// 如果reportGraphs 的成员都是同一个testName ,则执行如下代码,表示进行结果合并,生成 reportSummary
if IsUniqObject(testNamesd) {
if len(reportGraphs) > 0 {
reportGraph := ReportGraphAvg(reportGraphs)
reportSummary = model.ReportSummary{
ID: reportSuID,
TestName: reportGraph.TestName,
TestNameNick: reportGraph.TestNameNick,
Count: reportGraph.Count,
Error: reportGraph.Error,
QPS: reportGraph.QPS,
AvgTime: reportGraph.AvgTime,
NetIo: reportGraph.NetIo,
Min: reportGraph.Min,
Max: reportGraph.Max,
}
reportSummary.TestStatus = status
} else {
log.Info("sorry,your test duration is too short ..... ")
reportSummary = model.ReportSummary{ID: reportSuID, TestStatus: 3}
}
s.dao.UpdateReportSummary(&reportSummary)
}
//场景压测、多个接口走该逻辑
if !IsUniqObject(testNamesd) && len(testNameNicks) > 0 {
if len(reportGraphs) > 0 {
reportSummary = model.ReportSummary{ID: reportSuID, TestStatus: status}
} else {
reportSummary = model.ReportSummary{ID: reportSuID, TestStatus: 3}
}
}
s.dao.UpdateReportSummary(&reportSummary)
return
}
}
}()
<-done
}
//addPtestJobHostIp add regraph timer
func (s *Service) addPtestJobHostIp(c context.Context, addReGrapht model.AddReGraphTimer, res chan interface{}, timeout <-chan time.Time) {
var (
RetMap *model.PaasJobQueryStatus
token = addReGrapht.Token
err error
ptestJobs []*model.PtestJob
ptestJobsd []*model.PtestJob
firstRetMap *model.PaasJobQueryStatus
)
timer := time.NewTicker(10 * time.Second)
done := make(chan bool, 1)
go func() {
defer close(res)
a := 1
for {
select {
case <-timer.C:
if firstRetMap, err = s.dao.Job(c, token, addReGrapht.JobName); err != nil {
log.Error("查询容器状态 error-------(%v)", err)
//接口报错,则删除所有压测容器
return
}
if firstRetMap == nil || firstRetMap.Status == 400 || (firstRetMap.Status == 200 && firstRetMap.Data.ActiveNum == 0) {
return
}
ptestJob := model.PtestJob{ReportSuID: addReGrapht.ReportSuID, Active: 1}
if ptestJobs, err = s.dao.QueryPtestJob(&ptestJob); err != nil {
return
}
for _, job := range ptestJobs {
if job.HostIP == "" || job.JobIP == "" || job.JobID == "" {
ptestJobsd = append(ptestJobsd, job)
}
}
if len(ptestJobsd) > 0 {
for _, ptestJob := range ptestJobsd {
//查询容器状态
if RetMap, err = s.dao.Job(c, token, ptestJob.JobName); err != nil {
log.Error("get job info err (%v)", err)
}
if RetMap != nil && len(RetMap.Data.Pods) > 0 {
for _, pod := range RetMap.Data.Pods {
ptestjo := model.PtestJob{ID: ptestJob.ID, HostIP: pod.HostIP, JobID: pod.ContainerID, JobIP: pod.IP}
//更新容器hostIp
s.dao.UpdatePtestJob(ptestjo)
}
}
}
}
res <- a
a++
case <-timeout:
close(done)
return
}
}
}()
<-done
}
//addJobCPU job cpu
func (s *Service) addJobCPU(c context.Context, pod model.PodInfo, scriptID, reportSuID, elapsedTime int, jobName string) (err error) {
var (
clientMoni = model.ClientMoni{
ScriptID: scriptID,
ReportSuID: reportSuID,
JobName: jobName,
JobNameAll: pod.Name,
ElapsdTime: elapsedTime,
}
dockerStats *model.DockerStats
CPUResult *model.PaasQueryJobCPUResult
)
//首先查我们自己的容器cpu 获取服务
if pod.ContainerID != "" {
if dockerStats, err = s.QueryJobCPUByEP(context.TODO(), pod.ContainerID, pod.HostIP); err != nil {
log.Error("query CPU err ...(%s)", err)
}
if dockerStats != nil && dockerStats.CPU != "" {
cpu := strings.Replace(dockerStats.CPU, "%", "", 1)
cpufloat, _ := strconv.ParseFloat(cpu, 32)
cpuFinal := cpufloat
cpuString := strconv.FormatFloat(cpuFinal, 'f', -1, 32)
clientMoni.CPUUsed = cpuString
}
if dockerStats == nil || dockerStats.CPU == "" {
//如果我们的服务挂了,就查 moni
if CPUResult, err = s.QueryJobCPU(context.TODO(), pod.Name); err != nil {
log.Error("query client cpu err(%v)", err)
return
}
if len(CPUResult.Data) > 0 {
for _, data := range CPUResult.Data {
if len(data.Value) > 1 {
clientMoni.CPUUsed = data.Value[1].(string)
}
}
}
}
}
//cpu 信息记录到数据库
if _, err = s.AddClientMoni(&clientMoni); err != nil {
log.Error("add ClientMoni err(%v)", err)
return
}
return
}
//addReportGraph add reportGraph
func (s *Service) addReportGraph(c context.Context, reportGraphAdd model.ReportGraphAdd) {
var (
sumTime, sumQPS, sumNetIo, sumCodeEll, sumCodeWll, sumCodeWly, sumCodeWle, sumCodeWls, sumCodeSll, sumCodeSly, sumCodeSls,
sumCodeKong, sumCodeNonHTTP, sumCodeOthers, sumCount, sumError, sumThreads, fiftyTime, ninetyTime, ninetyFiveTime,
timeCount, ninetyNineTime, sumCode301, sumCode302 int
mins, maxs []int
reportTimelys []*model.ReportTimely
err error
)
busiStopPerc := reportGraphAdd.BusinessStopPercent
if reportTimelys, err = s.dao.QueryReTimely(reportGraphAdd.TestName, reportGraphAdd.BeginTime, reportGraphAdd.AfterTime, reportGraphAdd.PodNames); err != nil {
return
}
log.Info("------reportTimelys:(%v)", reportTimelys)
if len(reportTimelys) > 0 {
for _, reportTimely := range reportTimelys {
mins = append(mins, reportTimely.Min)
maxs = append(maxs, reportTimely.Max)
sumCount = sumCount + reportTimely.Count
//计算一个容器的接口响应总时间
timeCount = reportTimely.Count * reportTimely.AvgTime
//计算所有容器的接口响应时间
sumTime = sumTime + timeCount
sumQPS = sumQPS + reportTimely.QPS
sumError = sumError + reportTimely.Error
sumNetIo = sumNetIo + reportTimely.NetIo
sumCodeEll = sumCodeEll + reportTimely.CodeEll
sumCodeWll = sumCodeWll + reportTimely.CodeWll
sumCodeWly = sumCodeWly + reportTimely.CodeWly
sumCodeWle = sumCodeWle + reportTimely.CodeWle
sumCodeWls = sumCodeWls + reportTimely.CodeWls
sumCodeSll = sumCodeSll + reportTimely.CodeSll
sumCodeSly = sumCodeSly + reportTimely.CodeSly
sumCodeSls = sumCodeSls + reportTimely.CodeSls
sumCodeKong = sumCodeKong + reportTimely.CodeKong
sumCodeNonHTTP = sumCodeNonHTTP + reportTimely.CodeNonHTTP
sumCodeOthers = sumCodeOthers + reportTimely.CodeOthers
sumCode301 = sumCode301 + reportTimely.Code301
sumCode302 = sumCode302 + reportTimely.Code302
sumThreads = sumThreads + reportTimely.ThreadsSum
fiftyTime = fiftyTime + reportTimely.FiftyTime
ninetyTime = ninetyTime + reportTimely.NinetyTime
ninetyFiveTime = ninetyFiveTime + reportTimely.NinetyFiveTime
ninetyNineTime = ninetyNineTime + reportTimely.NinetyNineTime
}
sort.Ints(mins)
min := mins[0]
sort.Ints(maxs)
max := maxs[len(maxs)-1]
log.Info("test_nick_name ----- :(%s)", reportGraphAdd.TestNameNick)
reportGraph := model.ReportGraph{
TestName: reportGraphAdd.TestName, TestNameNick: reportGraphAdd.TestNameNick,
Count: sumCount,
QPS: sumQPS,
Error: sumError,
AvgTime: sumTime / sumCount,
NetIo: sumNetIo,
Min: min,
Max: max,
ElapsdTime: reportGraphAdd.ElapsedTime,
CodeEll: sumCodeEll,
CodeWll: sumCodeWll,
CodeWly: sumCodeWly,
CodeWle: sumCodeWle,
CodeWls: sumCodeWls,
CodeSll: sumCodeSll,
CodeSly: sumCodeSly,
CodeSls: sumCodeSls,
CodeKong: sumCodeKong,
CodeNonHTTP: sumCodeNonHTTP,
CodeOthers: sumCodeOthers,
ThreadsSum: sumThreads,
FiftyTime: fiftyTime / len(reportTimelys),
NinetyTime: ninetyTime / len(reportTimelys),
NinetyFiveTime: ninetyFiveTime / len(reportTimelys),
NinetyNineTime: ninetyNineTime / len(reportTimelys),
Code301: sumCode301,
Code302: sumCode302,
}
suCodeRate, suBusinessRate := CalcuSuccess(reportGraph)
if reportGraphAdd.Fusing == 0 {
reportGraphAdd.Fusing = conf.Conf.Melloi.DefaultFusing
}
//压测熔断
//使用业务熔断只要http code 和 业务断言错误满足一条阈值,则熔断
if reportGraphAdd.UseBusinessStop {
if busiStopPerc == 0 {
busiStopPerc = conf.Conf.Melloi.DefaultBusinessRate
}
if suCodeRate < reportGraphAdd.Fusing || suBusinessRate < busiStopPerc {
log.Info("接口失败率超过设置阈值,执行自动熔断,jobName (%s)", reportGraphAdd.JobName)
if _, err = s.DeleteJob(c, reportGraphAdd.JobName); err != nil {
return
}
reportsu := model.ReportSummary{ID: reportGraphAdd.ReportSuID, IsFusing: true, BusinessValue: busiStopPerc, UseBusinessStop: reportGraphAdd.UseBusinessStop,
FusingTestName: reportGraphAdd.TestName, SuccessCodeRate: suCodeRate, SuccessBusinessRate: suBusinessRate, FusingValue: reportGraphAdd.Fusing}
s.dao.UpdateReportSummary(&reportsu)
}
} else { //不使用业务熔断
if suCodeRate < reportGraphAdd.Fusing {
log.Info("接口失败率超过设置阈值,执行自动熔断,jobName (%s)", reportGraphAdd.JobName)
if _, err = s.DeleteJob(c, reportGraphAdd.JobName); err != nil {
return
}
reportsu := model.ReportSummary{ID: reportGraphAdd.ReportSuID, IsFusing: true, BusinessValue: busiStopPerc,
FusingTestName: reportGraphAdd.TestName, SuccessCodeRate: suCodeRate, SuccessBusinessRate: suBusinessRate, FusingValue: reportGraphAdd.Fusing}
s.dao.UpdateReportSummary(&reportsu)
}
}
s.dao.AddReportGraph(&reportGraph)
return
}
}
//CalcuSuccess calcu success
func CalcuSuccess(reportGraph model.ReportGraph) (successCodeRate, successBusinessRate int) {
success := reportGraph.CodeEll + reportGraph.CodeKong + reportGraph.Code301 + reportGraph.Code302
successCodeRate = success * 100 / reportGraph.Count
successBusinessRate = (reportGraph.Count - reportGraph.Error) * 100 / reportGraph.Count
return
}
// DelReportSummary delete report summary
func (s *Service) DelReportSummary(id int) error {
return s.dao.DelReportSummary(id)
}