go_dreamfactory/modules/robot/statisticalcomp.go
2023-12-20 16:52:18 +08:00

176 lines
5.8 KiB
Go

package robot
import (
"fmt"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/core/cbase"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/utils"
"os"
"sort"
"sync"
"time"
)
/*
统计组件
*/
type statisticalComp struct {
cbase.ModuleCompBase
module *RobotModule
succclientNum int32 //链接成功客户端数
failclientNum int32 //链接失败客户端数
curonlineNum int32 //当前在线人数
maxonlineNum int32 //最大在线人数
robotdata map[string][]*RobotStatistics //机器人统计数据
receiveMsg map[string]int32 //接收消息数统计
receiveMsgSize map[string]int64 //接收消息数统计
lock sync.RWMutex
start time.Time //开始时间
end time.Time //结束时间
}
//组件初始化接口
func (this *statisticalComp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
this.ModuleCompBase.Init(service, module, comp, options)
this.module = module.(*RobotModule)
this.robotdata = make(map[string][]*RobotStatistics)
this.receiveMsg = make(map[string]int32)
this.receiveMsgSize = make(map[string]int64)
return
}
func (this *statisticalComp) Start() (err error) {
err = this.ModuleCompBase.Start()
this.start = time.Now()
go this.run()
return
}
//添加成功客户端数
func (this *statisticalComp) AddSuccClient(robot *Robot) {
this.lock.Lock()
this.curonlineNum++
if this.curonlineNum > this.maxonlineNum {
this.maxonlineNum = this.curonlineNum
}
this.lock.Unlock()
}
//添加失败客户端数
func (this *statisticalComp) AddFailClient(robot *Robot, err error) {
this.failclientNum++
}
//机器人测试结束
func (this *statisticalComp) RobotFinishedTest(robot *Robot) {
this.lock.Lock()
this.robotdata[robot.Account()] = robot.statistics
for k, v := range robot.receiveNum {
this.receiveMsg[k] += v
}
for k, v := range robot.receiveSize {
this.receiveMsgSize[k] += v
}
this.curonlineNum--
this.succclientNum++
this.end = time.Now()
this.lock.Unlock()
}
//输出报表
func (this *statisticalComp) OutReport() {
var (
messagestime map[string][]int64 = make(map[string][]int64)
requestsize map[string]int64 = make(map[string]int64)
receive map[string]int32 = make(map[string]int32)
receiveSize map[string]int64 = make(map[string]int64)
totalmessage int32
totalrequestSize int64
totalreceive int32
totalreceiveSize int64
ok bool
)
this.lock.RLock()
for _, datas := range this.robotdata {
for _, v := range datas {
totalmessage++
if _, ok = messagestime[v.message]; !ok {
messagestime[v.message] = make([]int64, 0)
}
messagestime[v.message] = append(messagestime[v.message], v.time)
requestsize[v.message] += v.reqsize
totalrequestSize += v.reqsize
}
}
for k, v := range this.receiveMsg {
receive[k] = v
totalreceive += v
}
for k, v := range this.receiveMsgSize {
receiveSize[k] = v
totalreceiveSize += v
}
this.lock.RUnlock()
file, err := os.OpenFile(this.module.options.OutFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
file.WriteString(fmt.Sprintf("机器人总数: %d\n", this.module.options.RobotTotalNum))
file.WriteString(fmt.Sprintf("成功数量: %d\n", this.succclientNum))
file.WriteString(fmt.Sprintf("失败数量: %d\n", this.failclientNum))
file.WriteString(fmt.Sprintf("最大同时在线人数: %d\n", this.maxonlineNum))
file.WriteString(fmt.Sprintf("消息总请求数: %d\n", totalmessage))
file.WriteString(fmt.Sprintf("消息总请求大小: %s\n", utils.FormatByesSize(totalrequestSize)))
file.WriteString(fmt.Sprintf("消息总接收数: %d\n", totalreceive))
file.WriteString(fmt.Sprintf("消息总接收大小: %s\n", utils.FormatByesSize(totalreceiveSize)))
file.WriteString(fmt.Sprintf("压测执行时长: %.2f秒\n", this.end.Sub(this.start).Seconds()))
file.WriteString(fmt.Sprintf("QPS: %.2f\n", float64(totalmessage)/this.end.Sub(this.start).Seconds()))
file.WriteString("---消息压测详情----------------------------------------------------------------------------------------------------\n")
for message, data := range messagestime {
sort.Slice(data, func(i, j int) bool {
return data[i] < data[j]
})
reqsize := requestsize[message]
respsize := receiveSize[message]
max := data[len(data)-1]
min := data[0]
sum := int64(0)
for _, num := range data {
sum += num
}
avg := float64(sum) / float64(len(data))
var median float64
if len(data)%2 == 0 {
median = float64(data[len(data)/2-1]+data[len(data)/2]) / 2.0
} else {
median = float64(data[len(data)/2])
}
file.WriteString(fmt.Sprintf("消息名:%-30s 请求次数:%-5d 请求数据:%-10s --%-2.2f%% 接收数据:%-10s --%-2.2f%% 耗时最小:%-5dms 耗时最大:%-5dms 平均耗时:%-5.2fms 中位耗时:%-5.2fms \n", message, len(data), utils.FormatByesSize(reqsize), 100*(float32(reqsize)/float32(totalrequestSize)), utils.FormatByesSize(respsize), 100*(float32(respsize)/float32(totalreceiveSize)), min, max, avg, median))
}
for k, v := range receive {
if _, ok = messagestime[k]; !ok {
file.WriteString(fmt.Sprintf("消息名:%-30s 推送次数:%-5d 数据大小:%-5s --%-2.2f%% \n", k, v, utils.FormatByesSize(receiveSize[k]), 100*(float32(receiveSize[k])/float32(totalreceiveSize))))
}
}
}
func (this *statisticalComp) run() {
timer := time.NewTicker(time.Second * 10)
locp:
for {
select {
case <-timer.C:
this.OutReport()
if this.failclientNum+this.succclientNum >= this.module.options.RobotTotalNum {
break locp
}
}
}
timer.Stop()
log.Debug("[机器人 WTask]")
}