using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Sog.Log { public class NetMsgStat { public int MsgID; //发送数量 public int SendNum; //发送的数据长度,字节 public long SendLength; //接收数量 public int RecvNum; //接收的数据长度,字节 public long RecvLength; //接受消息总耗时 public long RecvTotalTime; //接受消息最大耗时 public long RecvMaxTime; //接受消息最小耗时 public long RecvMinTime; public void Clear() { SendNum = 0; SendLength = 0; RecvNum = 0; RecvLength = 0; RecvTotalTime = 0; RecvMaxTime = 0; RecvMinTime = 0; } } public class StatIDValue { public string ID; public long Value; //log后不清空,缺省都清空 public bool NotClearAfterLog; } /// /// 服务器统计类 /// public class ServerStat : Singleton { //字符串为索引 private SortedDictionary m_statIDValuesMap; //每个消息发送,接收信息 private SortedDictionary m_statNetMsgMap; private int TotalSendNum; private int TotalRecvNum; private long TotalSendLength; private long TotalRecvLength; private long m_lastLogTime; private int m_logInterval; private object m_threadLock = new object(); public ServerStat() { //缺省60秒log一次 m_logInterval = 60*1000; m_statIDValuesMap = new SortedDictionary(); m_statNetMsgMap = new SortedDictionary(); } public void Tick(long tNowMs) { if(m_lastLogTime == 0) { m_lastLogTime = tNowMs; } if (tNowMs < m_lastLogTime + m_logInterval) { return; } m_lastLogTime = tNowMs; LogHead(); LogContent(); LogTail(); } private void LogContent_imp() { LogNetMsg(); LogIDValues(); LogGCMonitor(); } private void LogContent() { lock (m_threadLock) { LogContent_imp(); } } //搞个头,看起来方便点 private void LogHead() { TraceLog.Stat("ServerStat begin ================================================================="); } private void LogTail() { TraceLog.Stat("ServerStat end.\n"); } private void LogIDValues() { //没有就算了 if(m_statIDValuesMap.Count == 0) { return; } TraceLog.Stat(" ID Value"); foreach(var idvalue in m_statIDValuesMap.Values) { TraceLog.Stat("{0,-40}{1,-20}", idvalue.ID, idvalue.Value); //log完后清空这项数值 if (idvalue.NotClearAfterLog == false) { idvalue.Value = 0; } } /* var keys = m_statIDValuesMap.Keys; var keyarray = keys.ToArray(); foreach (string id in keyarray) { StatIDValue idvalue = m_statIDValuesMap[id]; TraceLog.Stat("{0,-40}{1,-20}",id, idvalue.Value); //log完后清空这项数值 if (idvalue.NotClearAfterLog == false) { idvalue.Value = 0; } }*/ } /// /// 给id项目加value /// /// /// private void AddValue_imp(string id,long value, bool clearAfterLog = true) { if (m_statIDValuesMap.ContainsKey(id) == false) { StatIDValue idvalue = new StatIDValue(); idvalue.ID = id; idvalue.Value = value; idvalue.NotClearAfterLog = !clearAfterLog; m_statIDValuesMap.Add(id, idvalue); } else { StatIDValue idvalue = m_statIDValuesMap[id]; idvalue.Value += value; idvalue.NotClearAfterLog = !clearAfterLog; } } public void AddValue(string id, long value, bool clearAfterLog = true) { lock (m_threadLock) { AddValue_imp(id, value, clearAfterLog); } } /// /// 设置id项目为value /// /// /// private void SetValue_imp(string id, long value, bool clearAfterLog = true) { if (m_statIDValuesMap.ContainsKey(id) == false) { StatIDValue idvalue = new StatIDValue(); idvalue.ID = id; idvalue.Value = value; idvalue.NotClearAfterLog = !clearAfterLog; m_statIDValuesMap.Add(id, idvalue); } else { StatIDValue idvalue = m_statIDValuesMap[id]; idvalue.Value = value; idvalue.NotClearAfterLog = !clearAfterLog; } } public void SetValue(string id, long value, bool clearAfterLog = true) { lock (m_threadLock) { SetValue_imp(id, value, clearAfterLog); } } //如果不存在则创建 private NetMsgStat GetNetMsgStatByID(int iMsgID) { if(!m_statNetMsgMap.ContainsKey(iMsgID)) { NetMsgStat stat = new NetMsgStat(); stat.MsgID = iMsgID; m_statNetMsgMap.Add(iMsgID, stat); } return m_statNetMsgMap[iMsgID]; } public void OnNetSend(int iMsgID, int iDataLength) { lock (m_threadLock) { NetMsgStat stat = GetNetMsgStatByID(iMsgID); stat.SendLength += iDataLength; stat.SendNum += 1; TotalSendLength += iDataLength; TotalSendNum += 1; } } public void OnNetRecv(int iMsgID, int iDataLength, long time) { lock (m_threadLock) { NetMsgStat stat = GetNetMsgStatByID(iMsgID); stat.RecvLength += iDataLength; stat.RecvNum += 1; stat.RecvTotalTime += time; stat.RecvMaxTime = stat.RecvMaxTime < time ? time : stat.RecvMaxTime; if (stat.RecvNum > 1) //不是第一次 { stat.RecvMinTime = stat.RecvNum > 0 ? time : stat.RecvMinTime; } else { stat.RecvMinTime = time; } TotalRecvLength += iDataLength; TotalRecvNum += 1; } } //网络消息,接受,发送数量和长度 private void LogNetMsg() { TraceLog.Stat("TotalSendNum:{0,-10} TotalRecvNum:{1,-10} TotalSendLength:{2,-12} TotalRecvLength:{3,-12}", TotalSendNum, TotalRecvNum, TotalSendLength, TotalRecvLength); //清空 TotalRecvLength = 0; TotalRecvNum = 0; TotalSendLength = 0; TotalSendNum = 0; TraceLog.Stat("MsgID SendNum RecvNum SendLength RecvLength RecvTotalTime RecvMaxTime RecvMinTime RecvAvgTime"); foreach(var item in m_statNetMsgMap.Values) { long RecvAvgTime = item.RecvNum <= 0 ? 0 : item.RecvTotalTime / item.RecvNum; TraceLog.Stat("{0,-10}{1,-10}{2,-10}{3,-15}{4,-15}{5,-18}{6,-16}{7,-16}{8,-16}", item.MsgID, item.SendNum, item.RecvNum, item.SendLength, item.RecvLength, item.RecvTotalTime, item.RecvMaxTime, item.RecvMinTime, RecvAvgTime); //log完后清空这项数值 item.Clear(); } /* var keys = m_statNetMsgMap.Keys; var keyarray = keys.ToArray(); foreach (int id in keyarray) { NetMsgStat stat = m_statNetMsgMap[id]; TraceLog.Stat("{0,-10}{1,-10}{2,-10}{3,-15}{4,-15}", id, stat.SendNum,stat.RecvNum,stat.SendLength,stat.RecvLength); //log完后清空这项数值 stat.Clear(); } */ } private void LogGCMonitor() { GCMonitor.Instance.LogStat(); } } }