package lib import ( "bytes" "fmt" "os" "path/filepath" "sort" "strings" "sync" "sync/atomic" "time" "github.com/sirupsen/logrus" "legu.airobot/storage" ) type MyAI struct { robots []*Robot scenes []*scene iscenes []IScene tickets Tickets //票池 Obs Observer userCountTotal uint32 //总数 cache sync.Mutex //数据缓存锁 lock sync.Mutex //合并数据锁 config *storage.Config //配置 ReportMap map[int]map[string]*Statistics //测试报告 key1:场景 key2:协议 } func NewAI(aip AIParam) (*MyAI, error) { if err := aip.Check(); err != nil { return nil, err } ai := &MyAI{ scenes: make([]*scene, 0), config: aip.Config, iscenes: aip.Scenes, ReportMap: make(map[int]map[string]*Statistics), } if err := ai.init(); err != nil { return nil, err } return ai, nil } func (m *MyAI) init() error { var buf bytes.Buffer buf.WriteString("初始化AI") uct := m.config.Global.UserCountTotal tickets, err := NewTickets(uct) if err != nil { return err } m.tickets = tickets buf.WriteString(fmt.Sprintf("完成 用户数量:%d", uct)) logrus.Debug(buf.String()) return nil } func (m *MyAI) AppendRobot(robot *Robot) { defer m.lock.Unlock() m.lock.Lock() m.robots = append(m.robots, robot) } func (m *MyAI) Start() bool { if len(m.config.Scenes) == 0 { logrus.Warn("还未设置场景") return false } go func() { for { m.tickets.Take(int32(m.config.Global.UserCount), m.config.Global.IntervalS) go func() { robot := NewRobot(m) robot.SetScenes() m.AppendRobot(robot) atomic.AddUint32(&m.userCountTotal, 1) m.Obs.Notify(EVENT_ROBOT, int32(1)) robot.Start() }() } }() return true } func (m *MyAI) Stop() { } func (m *MyAI) MergeResult() { m.lock.Lock() defer m.lock.Unlock() n := make(map[int]map[string]*Statistics) for _, r := range m.robots { if len(n) == 0 { n = r.ReportMap } else { x := n //已存在的 y := r.ReportMap //将要合并的 for i, v := range x { for j, w := range y { //场景相同 if i == j { for k, a := range v { for l, b := range w { //判断协议是否相同 if k == l { statis := &Statistics{} statis.ElapseTotal = time.Duration(int64(a.ElapseTotal + b.ElapseTotal)) statis.AvgElapse = time.Duration(int64(a.AvgElapse+b.AvgElapse) / int64(2)) statis.CallCount = (a.CallCount + b.CallCount) max := a.MaxElapse if max < b.MaxElapse { max = b.MaxElapse } statis.MaxElapse = max min := a.MinElapse if min > b.MinElapse { min = b.MinElapse } statis.MinElapse = min statis.Route = a.Route statis.SceneName = a.SceneName statis.TimeoutCount = (a.TimeoutCount + b.TimeoutCount) if n[i][k] == nil { n[i] = make(map[string]*Statistics) } n[i][k] = statis } else { if _, ok := n[i][k]; !ok { n[i][k] = a } if _, ok := n[i][l]; !ok { n[i][l] = b } } } } } else { if _, ok := n[i]; !ok { n[i] = v } if _, ok := n[j]; !ok { n[j] = w } } } } } } m.ReportMap = n } func (m *MyAI) GenReport(elipse time.Duration) { var msgs []string var i []int for key, _ := range m.ReportMap { i = append(i, key) } sort.Ints(i) for _, routes := range i { for r, d := range m.ReportMap[routes] { msgs = append(msgs, fmt.Sprintf("【%s】协议:%s 调用次数:%d 总耗时:%v 平均耗时:%v 最大耗时:%v 最小耗时:%v 超时次数:%v", d.SceneName, r, d.CallCount, d.ElapseTotal.String(), d.AvgElapse.String(), d.MaxElapse.String(), d.MinElapse.String(), d.TimeoutCount)) } } record := strings.Join(msgs, "\n") var buf bytes.Buffer buf.WriteString(fmt.Sprintf("测试报告 时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))) buf.WriteString(fmt.Sprintf("用户总数:%d 单次投放人数:%d 投放间隔时间:%ds 共计时间:%s\n", m.config.Global.UserCountTotal, m.config.Global.UserCount, m.config.Global.IntervalS, elipse.String())) buf.WriteString(record) buf.WriteString("\n------------------------------------------------------------------------------------------------------\n") // logrus.WithField("res", buf.String()).Debug("报告内容") file, err := os.OpenFile(filepath.Join("./", "report.log"), os.O_TRUNC|os.O_CREATE, os.ModePerm) if err != nil { logrus.Error(err) } defer file.Close() if _, err := file.WriteString(buf.String()); err != nil { logrus.Error(err) } logrus.Info("已生成测试报告") m.Obs.Notify(EVENT_FLAG, true) }