--[[ 网络协议统计 ]] local NetStatistics = {} local private = {} local LuaUpdater = require "Main/LuaUpdater" local JSON = require("cjson") --接收协议关联的发送协议 --有些发送的协议关注的可能是其他的协议,那么自己的接收协议配置空,代表忽略自己的Resp --关注的协议配对发送的协议,比如收到MessageS2CRoleEnterScene,则去匹配MessageEnterFuben或者MessageEnterGuildBoss的发送 local RespMsgIdRelatedSendMsgIdCfg = { [MessageEnums.MessageEnterFuben] = {}, [MessageEnums.MessageRobRebel] = {}, [MessageEnums.MessageEnterGuildBoss] = {}, [MessageEnums.MessageEnterWorldBoss] = {}, [MessageEnums.MessageS2CRoleEnterScene] = {MessageEnums.MessageEnterFuben, MessageEnums.MessageEnterGuildBoss}, [MessageEnums.MessageG2CInitFubenInfo] = {MessageEnums.MessageRobRebel, MessageEnums.MessageEnterGuildBoss, MessageEnums.MessageEnterWorldBoss}, [MessageEnums.MessageG2CPushHint] = {MessageEnums.MessageRobRebel}, [MessageEnums.MessageG2CEnterWorldBoss] = {MessageEnums.MessageEnterWorldBoss}, } --每隔5秒检测一次 local NetStatisticsSendInterval = 5 --协议延时的时间 local NetMessageRespDelayTimeMax = 1 --是否开启统计 local IsStatisticsEnabled = true --统计数据 --(发送,接受,延时总量) local TotalSendMsgCount = 0 local TotalReceiveCount = 0 local TotalDelayCount = 0 local TotalTimeoutCount = 0 --单个协议的收发,延时和超时 key:msgid value{0,0,0,0}发+收+延时+超时 local MessageStatisticsData = {} --收发协议记录 local reqRespMessageList = {} private.EmptyFunc = function(param) -- logging.error(LTAG.ERROR, param) end function NetStatistics.Init() private.ResetNetStatistcsData() if IsStatisticsEnabled then NetStatistics.OnMsgSend = private.OnMsgSend NetStatistics.OnMsgRecv = private.OnMsgRecv else NetStatistics.OnMsgSend = private.EmptyFunc NetStatistics.OnMsgRecv = private.EmptyFunc end end function NetStatistics.StartUpdate() if IsStatisticsEnabled then LuaUpdater.StartUpdate(private.TrySendNetStatisticsDatas) end end function NetStatistics.StopUpdate() if IsStatisticsEnabled then LuaUpdater.StopUpdate(private.TrySendNetStatisticsDatas) end end --与服务器建立连接成功清空发送队列记录 function NetStatistics.OnReconnectSuccess() reqRespMessageList = {} end --添加至发送队列(待收协议进行匹配),同时总发送量以及单条协议的发送量+1 function private.OnMsgSend(msgId) TotalSendMsgCount = TotalSendMsgCount + 1 private.CheckMessageStatisticsDataMessageList(msgId) MessageStatisticsData[msgId][1] = MessageStatisticsData[msgId][1] + 1 reqRespMessageList[msgId] = reqRespMessageList[msgId] or {} table.insert(reqRespMessageList[msgId], private.GetCurTime(0)) end function private.GetCurTime(time) if time and time > 0 then return time end return AuxUtil.GetLocalTimeStampMS()/1000 end --收到协议进行匹配处理 function private.OnMsgRecv(msgId, receiveTime, isServerReturnFailure) if RespMsgIdRelatedSendMsgIdCfg[msgId] then local isEmpty = true for __, releatedMsgId in ipairs(RespMsgIdRelatedSendMsgIdCfg[msgId]) do isEmpty = false if private.ExcuteBIMessageList(releatedMsgId, receiveTime) then return end end if isEmpty and isServerReturnFailure then private.ExcuteBIMessageList(msgId, receiveTime) end else private.ExcuteBIMessageList(msgId, receiveTime) end end --延时则加入到延时统计中 function private.ExcuteBIMessageList(msgId, receiveTime) if reqRespMessageList[msgId] and #reqRespMessageList[msgId] > 0 then local delay = private.GetCurTime(receiveTime)-reqRespMessageList[msgId][1] if delay >= NetMessageRespDelayTimeMax then private.AddNetStatisticsMsg(msgId, delay) end private.RemoveBIRecordMsg(msgId) return true elseif not RespMsgIdRelatedSendMsgIdCfg[msgId] then --服务器主动推送的协议 TotalReceiveCount = TotalReceiveCount + 1 private.CheckMessageStatisticsDataMessageList(msgId) MessageStatisticsData[msgId][2] = MessageStatisticsData[msgId][2] + 1 end return false end --从发送队列移除,同时总的接受数量和单条协议的接收数量+1 --消息发送时间的记录理论应该是将所有的消息整体放在同一个时间维度上记录,但是需要格式为{msgid1:time, msgid2:time, msgid1:time} --现在按msgId保存的话,则可能丢失一部分协议之间的时序信息 --假设客户端消息A和B都使用服务器C消息来进行回复,那么当客户端以ABA的顺序进行发送,收到服务器的CCC,参看RespMsgIdRelatedSendMsgIdCfg --理论上应该与ABA进行匹配(此时配置应为C={A,B}),但如果配置为C={B,A},则配对变成了BAA function private.RemoveBIRecordMsg(msgId) TotalReceiveCount = TotalReceiveCount + 1 private.CheckMessageStatisticsDataMessageList(msgId) MessageStatisticsData[msgId][2] = MessageStatisticsData[msgId][2] + 1 table.remove(reqRespMessageList[msgId], 1) if #reqRespMessageList[msgId] == 0 then reqRespMessageList[msgId] = nil end end function private.AddNetStatisticsMsg(msgId, delayTime) private.CheckMessageStatisticsDataMessageList(msgId) if delayTime >= NetManager.NetMessageTimeOutMax then TotalTimeoutCount = TotalTimeoutCount + 1 MessageStatisticsData[msgId][4] = MessageStatisticsData[msgId][4] + 1 else TotalDelayCount = TotalDelayCount + 1 MessageStatisticsData[msgId][3] = MessageStatisticsData[msgId][3] + 1 end end function private.TrySendNetStatisticsDatas(deltaTime, timeSinceUpdate) if NetManager.IsLaunch() then return end NetStatisticsSendInterval = NetStatisticsSendInterval - deltaTime if NetStatisticsSendInterval <= 0 then NetStatisticsSendInterval = 5 private.SendTotalDataToClientBI() end end --msgId--string function private.CheckMessageStatisticsDataMessageList(msgId) if not MessageStatisticsData[msgId] then MessageStatisticsData[msgId] = {0, 0, 0, 0} end end --在X秒内发送的数量大于5或者接受的数量大于10,或者延时的数量大于2则发送统计(值可调) function private.SendTotalDataToClientBI() if TotalSendMsgCount >= 5 or TotalReceiveCount >= 10 or TotalDelayCount >= 2 or TotalTimeoutCount > 0 then if TotalTimeoutCount > 0 then BIManager.SendTotalNetMsgStatistics(TotalSendMsgCount, TotalReceiveCount, TotalDelayCount, TotalTimeoutCount) elseif TotalDelayCount > 0 then BIManager.SendTotalNetMsgStatistics(TotalSendMsgCount, TotalReceiveCount, TotalDelayCount) else BIManager.SendTotalNetMsgStatistics(TotalSendMsgCount, TotalReceiveCount) end -- logging.error(LTAG.ERROR, "Total", TotalSendMsgCount, TotalReceiveCount, TotalDelayCount, TotalTimeoutCount) for msgId, statisticsData in pairs(MessageStatisticsData) do if statisticsData[4] > 0 then BIManager.ReportSingleNetMsgStatistics(msgId, statisticsData[1], statisticsData[2], statisticsData[3], statisticsData[4]) elseif statisticsData[3] > 0 then BIManager.ReportSingleNetMsgStatistics(msgId, statisticsData[1], statisticsData[2], statisticsData[3]) else BIManager.ReportSingleNetMsgStatistics(msgId, statisticsData[1], statisticsData[2]) end -- logging.error(LTAG.ERROR, "Single", msgId, statisticsData[1], statisticsData[2], statisticsData[3], statisticsData[4]) end private.ResetNetStatistcsData() end end function private.ResetNetStatistcsData() TotalSendMsgCount = 0 TotalReceiveCount = 0 TotalDelayCount = 0 TotalTimeoutCount = 0 for msgId, singleData in pairs(MessageStatisticsData) do for i=1, 4 do singleData[i] = 0 end end end return NetStatistics