package monitor import ( "backend/Type" "backend/alibaba" "backend/model" "backend/util" "fmt" "net" "time" ) func UserAliveMonitor(AppId int) { AppConfig, _ := util.GetAppConfig(AppId) Db := util.MPool.GetTopicDB(AppConfig.Topic) defer Db.Close() for { curCount, yCount, err := util.CountDistinctUidLastHour() if err != nil { continue } if yCount > 0 { drop := float64(yCount-curCount) / float64(yCount) str := ` # **游戏数据监控异常** - 项目名称: meowment - 监控项名称: 用户存活监控
------------------------- 监控时间段: %s ~ %s
昨日活跃用户数: %d
当前活跃用户数: %d
用户流失率: **%.2f%%**
@所有人 ` if drop >= 0.3 && (yCount-curCount) >= int64(10) { alibaba.SendAliveMsg("服务器报警", fmt.Sprintf(str, time.Now().Format("2006-01-02 15:04:05"), time.Now().Add(time.Hour).Format("2006-01-02 15:04:05"), yCount, curCount, drop*100), "red") // feishu.SendNoticeMsg("meowment", "用户存活监控", // fmt.Sprintf("监控时间段: %s ~ %s\n昨日活跃用户数: %d\n当前活跃用户数: %d\n用户流失率: %.2f%%", // time.Now().Format("2006-01-02 15:04:05"), // time.Now().Add(time.Hour).Format("2006-01-02 15:04:05"), // yCount, // curCount, // drop*100)) } } time.Sleep(time.Until(time.Now().Truncate(time.Hour).Add(time.Hour))) } } func ServerInfoMonitor() { for { now := time.Now() next := now.Truncate(1 * time.Minute).Add(1 * time.Minute) time.Sleep(time.Until(next)) monitorServerInfo() } } func monitorServerInfo() { Db := util.MPool.GetGameDB() var server []*Type.ServerInfo defer Db.Close() err := Db.Select(&server, "SELECT `AppId`, `ServerId`, `ServerName`, `Status`, `CreateTime`, `OpenServerTime`, `Host`, `Port` FROM server ") if err != nil { return } for _, v := range server { if v.Status == 2 || v.Status == 3 { // 维护中或停用跳过 continue } go func(v *Type.ServerInfo) { tmpDb := util.MPool.GetGameDB() defer tmpDb.Close() // TCP ping test for server connectivity address := fmt.Sprintf("%s:%d", v.Host, v.Port) // adjust port as needed timeout := 3 * time.Second start := time.Now() conn, err := net.DialTimeout("tcp", address, timeout) latency := time.Since(start).Milliseconds() if err != nil { // Connection failed, mark server as offline tmpDb.Exec("update server set Status=0 where AppId=? and ServerId=?", v.AppId, v.ServerId) return } conn.Close() res, err := model.GetServerInfo(v.AppId, v.ServerId) if err != nil { //tmpDb.Exec("update server set Status=0 where AppId=? and ServerId=?", v.AppId, v.ServerId) return } serverInfo := res.(map[string]interface{}) free_mem := util.Int(serverInfo["FreeMem"]) usage_mem := util.Int(serverInfo["Sys"]) cpu := util.Int(serverInfo["CPU"]) // compute weight in 0-100 based on free_mem (MB) and cpu (%) // heuristic: more free memory and lower CPU -> higher weight memCap := 8192 // 8GB as reference cap for normalization if free_mem < 0 { free_mem = 0 } memScore := 0 if free_mem >= memCap { memScore = 100 } else { memScore = free_mem * 100 / memCap } if cpu < 0 { cpu = 0 } if cpu > 100 { cpu = 100 } cpuScore := 100 - cpu // lower CPU -> higher score // weighted: 60% memory, 40% CPU weight := (memScore*6 + cpuScore*4) / 10 if weight < 0 { weight = 0 } if weight > 100 { weight = 100 } // optionally store/update weight serverInfo["Weight"] = weight // Process serverInfo as needed tmpDb.Exec("update server set Status=1, Online=?,free_mem=?,cpu=?,weight=?,latency=? where AppId=? and ServerId=?", util.Int(serverInfo["PlayerNum"]), usage_mem, cpu, weight, latency, v.AppId, v.ServerId) }(v) } }