You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

422 lines
14 KiB

1 month ago
using System;
using Sog;
using Sog.Log;
using ProtoCSStruct;
using Sog.Service;
namespace BillLog
{
public class BillLogMsgHandler : BaseReloadableService
{
private ServerApp m_app;
// 本地bill日志
private Logger m_billLogger;
private DateTime m_lastLogTime;
// 本地bdc日志
private Logger m_bdcLogger;
private DateTime m_lastBdcLogTime;
// bdc客户端日志
private Logger m_clibdcLogger;
private DateTime m_cliLastBdcLogTime;
private int noUidCount;
//ta日志
private Logger m_taLogger;
private DateTime m_lastTaLogTime;
//ta客户端日志
private Logger m_clitaLogger;
private DateTime m_lastCliTaLogTime;
//ta过滤日志,关闭的日志是数数数量太多了不要了,我们这最好存好不上报吧
private Logger m_taFilterLogger;
private DateTime m_lastTaFilterLogTime;
// todo 这个值需要存盘, 否则会有重复的问题
private static long uuidSeq;
public override int GetServiceType()
{
return BillLogServiceType.BillLogMsgHandler;
}
//销毁的时候置空
public override void Dispose()
{
m_app = null;
m_billLogger = null;
m_bdcLogger = null;
m_clibdcLogger = null;
m_taLogger = null;
m_taFilterLogger = null;
}
public BillLogMsgHandler(ServerApp app)
{
m_app = app;
var logPaths = BillLogServerUtils.GetServerConfig().logpatchs;
//先写死,to do 放到配置文件
m_billLogger = new Logger(logPaths.bill, "", LogLevel.Debug);
//关闭文件自动滚动功能,自己实现按时间(每小时)滚动
m_billLogger.CloseShift();
m_bdcLogger = new Logger(logPaths.bdc, "", LogLevel.Debug);
//关闭文件自动滚动功能,自己实现按时间(每小时)滚动
m_bdcLogger.CloseShift();
m_clibdcLogger = new Logger(logPaths.bdcCli, "", LogLevel.Debug);
//关闭文件自动滚动功能,自己实现按时间(每小时)滚动
m_clibdcLogger.CloseShift();
m_taLogger = new Logger(logPaths.ta, "", LogLevel.Debug);
//关闭文件自动滚动功能,自己实现按时间(每小时)滚动
m_taLogger.CloseShift();
m_clitaLogger = new Logger(logPaths.taCli, "", LogLevel.Debug);
//关闭文件自动滚动功能,自己实现按时间(每小时)滚动
m_clitaLogger.CloseShift();
m_taFilterLogger = new Logger(logPaths.taFilter, "", LogLevel.Debug);
//关闭文件自动滚动功能,自己实现按时间(每小时)滚动
m_taFilterLogger.CloseShift();
}
public ServerApp GetApp()
{
return m_app;
}
public void HandlerMessage(uint remoteAppID, MessageData message)
{
StructPacket packet;
bool bSuccess = BillLogServerUtils.GetProtoPacker().UnpackMessage(message, out packet);
if(bSuccess == false)
{
TraceLog.Error("HandlerMessage ,unpack msg failed {0}, remoteAppID {1}", message.Header.Type, remoteAppID);
return;
}
//预先判断,提高效率
if (TraceLog.GetLogLevel() <= (int)Sog.Log.LogLevel.TraceDetail)
{
TraceLog.TraceDetail("recv message from server {0}, message type {1} length {2} : {3}->{4}"
, ServerIDUtils.IDToString(remoteAppID)
, message.Header.Type
, message.Header.Length
, packet.MessageName()
, packet.ToString());
}
switch (packet.MsgID)
{
case (int)SSGameMsgID.BillLogReq:
OnBillLogReq(remoteAppID, packet);
break;
case (int)SSGameMsgID.BdcLogReq:
OnBDCLogReq(remoteAppID, packet);
break;
case (int)CSGameMsgID.LogClientBdcReq:
OnBdcClientLogReq(remoteAppID, packet);
break;
case (int)SSGameMsgID.TaLogReq:
OnTALogReq(remoteAppID, packet);
break;
case (int)CSGameMsgID.LogClientTaReq:
OnTAClientLogReq(remoteAppID, packet);
break;
default:
TraceLog.Error("MsgHandler unknow MsgID {0}", packet.MsgID);
break;
}
}
private void OnBillLogReq(uint remoteAppID, StructPacket packet)
{
ref SSBillLogReq billLogReq = ref packet.GetMessage<SSBillLogReq>();
string logmessage = billLogReq.StrLogMessage.ToString();
TraceLog.Debug("OnBillLogReq log message from server {0} log:{1}", ServerIDUtils.IDToString(remoteAppID), logmessage);
WriteBillLog(logmessage);
}
private void OnBdcClientLogReq(uint remoteAppID, StructPacket packet)
{
ref CsLogClientBDCReq billLogReq = ref packet.GetMessage<CsLogClientBDCReq>();
string logmessage = billLogReq.StrLogMessage.ToString();
TraceLog.Debug("OnBdcClientLogReq log message from server {0} log:{1}", ServerIDUtils.IDToString(remoteAppID), logmessage);
WriteClientBdcLog(logmessage);
}
private void OnTAClientLogReq(uint remoteAppID, StructPacket packet)
{
ref CsLogClientTAReq taLogReq = ref packet.GetMessage<CsLogClientTAReq>();
string logmessage = taLogReq.StrLogMessage.ToString();
TraceLog.Debug("OnTAClientLogReq log message from server {0} log:{1}", ServerIDUtils.IDToString(remoteAppID), logmessage);
WriteClientTALog(logmessage);
}
private void WriteBillLog(string strMessage)
{
DateTime now = DateTime.Now;
if(IsLogFileNameChanged(m_lastLogTime, now))
{
m_lastLogTime = now;
m_billLogger.SetFileName(CalcLogFileName(now));
}
//时间就用这个now,写的时候不用再取了,取2次会有时间不一致问题
m_billLogger.WriteLogWithTime(now,strMessage);
}
private void WriteLocalBdcLog(string strMessage)
{
DateTime now = DateTime.Now;
if (IsLogFileNameChanged(m_lastBdcLogTime, now))
{
m_lastBdcLogTime = now;
m_bdcLogger.SetFileName(CalcLogFileName(now, 1));
}
//时间就用这个now,写的时候不用再取了,取2次会有时间不一致问题
m_bdcLogger.WriteLogWithTime(now, strMessage);
}
private void WriteLocalTALog(string strMessage)
{
DateTime now = DateTime.Now;
if (IsLogFileNameChanged(m_lastTaLogTime, now))
{
m_lastTaLogTime = now;
m_taLogger.SetFileName(CalcLogFileName(now, 3));
}
m_taLogger.WriteTALog(strMessage);
}
private void WriteLocalTAFilterLog(string strMessage)
{
DateTime now = DateTime.Now;
if (IsLogFileNameChanged(m_lastTaFilterLogTime, now))
{
m_lastTaFilterLogTime = now;
m_taFilterLogger.SetFileName(CalcLogFileName(now, 5));
}
m_taFilterLogger.WriteTALog(strMessage);
}
private void WriteClientBdcLog(string strMessage)
{
DateTime now = DateTime.Now;
if (IsLogFileNameChanged(m_cliLastBdcLogTime, now))
{
m_cliLastBdcLogTime = now;
m_clibdcLogger.SetFileName(CalcLogFileName(now, 2));
}
//时间就用这个now,写的时候不用再取了,取2次会有时间不一致问题
m_clibdcLogger.WriteLogWithTime(now, strMessage);
}
private void WriteClientTALog(string strMessage)
{
DateTime now = DateTime.Now;
if (IsLogFileNameChanged(m_lastCliTaLogTime, now))
{
m_lastCliTaLogTime = now;
m_clitaLogger.SetFileName(CalcLogFileName(now, 4));
}
m_clitaLogger.WriteLogWithTime(now, strMessage);
}
private string CalcLogFileName(DateTime now, int logType = 0)
{
// "2016-10-01 01:13:59"
string nowTimeFormat = now.ToString("u");
string nowDay = nowTimeFormat.Substring(0, 10);
string nowHour = nowTimeFormat.Substring(11, 2);
if (logType == 1)
{
return string.Format("bdcSvr_{0}_{1}.log", nowDay, nowHour);
}
else if(logType == 2)
{
return string.Format("bdcCli_{0}_{1}.log", nowDay, nowHour);
}
else if (logType == 3)
{
return string.Format("talog_{0}_{1}.log", nowDay, nowHour);
}
else if (logType == 4)
{
return string.Format("clitalog_{0}_{1}.log", nowDay, nowHour);
}
else if (logType == 5)
{
return string.Format("tafilterlog_{0}_{1}.log", nowDay, nowHour);
}
return string.Format("bill_{0}_{1}.log", nowDay, nowHour);
}
private bool IsLogFileNameChanged(DateTime lastLogTime, DateTime now)
{
if(lastLogTime.Hour == now.Hour
&& lastLogTime.Day == now.Day
&& lastLogTime.Month == now.Month
&& lastLogTime.Year == now.Year)
{
return false;
}
return true;
}
private string GenUUID()
{
uuidSeq++;
if (uuidSeq > 1000000)
{
uuidSeq = 1;
}
return $"{BillLogServerUtils.GetDateTime().ToString("yyyyMMdd-HHmmss")}-{uuidSeq.ToString().PadLeft(7, '0')}";
}
private void OnBDCLogReq(uint remoteAppID, StructPacket packet)
{
var cfg = BillLogServerUtils.GetServerConfig().bdcCfg;
if (cfg.isBdcOpen == 0)
{
return;
}
//因为需要放入每个线程的队列,所以需要clone 一个新的对象,UnpackMessage出来的消息每次其实是同一个
//如果存在性能问题,可以根据消息类型进行缓冲
packet = packet.Clone();
string uuid = GenUUID();
ref SSBDCLogReq req = ref packet.GetMessage<SSBDCLogReq>();
req.Event_uuid.SetString(uuid);
// 本地bdc日志在主线程里面写入bdc_xxx_xxx.log
// 本地bdc日志比远端bdc日志少了2个字段, appKey, platform, 这2个字段读取的配置文件, 运行期间不会改变
// 另外, 本地和远端的event_time可能不一致, 按照bdc要求event_time是日志上报时间
// 远端event_time是work线程实际提交http请求时的时间.
// 目前选择不统一本地和远端的event_time, 保留时间差以便性能分析
var localBdcMsg = string.Format("{0}|event_uuid={1}|event_time={2}|event_time2={3}|platform={4}|time_zone={5}"
, req.LogMsg.GetString()
, uuid
, BillLogServerUtils.GetTimeSecond().ToString()
, BillLogServerUtils.GetDateTime().ToString("yyyy-MM-dd"),
BillLogServerUtils.GetServerConfig().bdcCfg.Bdcplatform,
"UTC+" + AppTime.TimeZone.ToString() + ":00");
WriteLocalBdcLog(localBdcMsg);
bool isFilter = false;
if (req.EventId > 0 && cfg.FilterLogEventIds != null && cfg.FilterLogEventIds.Length > 0)
{
for (int i = 0; i < cfg.FilterLogEventIds.Length; i++)
{
if (req.EventId == cfg.FilterLogEventIds[i])
{
isFilter = true;
break;
}
}
}
if (!isFilter)
{
int iTaskIndex = CalcTaskIndex(noUidCount);
noUidCount++;
if (noUidCount < 0)
{
noUidCount = 1;
}
MessageTaskDistributor.Instance.Distribute(remoteAppID, packet, iTaskIndex);
}
}
private void OnTALogReq(uint remoteAppID, StructPacket packet)
{
if (BillLogServerUtils.GetServerConfig().isTALogOpen == 0)
{
return;
}
ref SSTALogReq req = ref packet.GetMessage<SSTALogReq>();
if(IsTaFilterEvent(req.EventName.ToString())) //是过滤事件
{
WriteLocalTAFilterLog(req.LogMsg.ToString());
}
else
{
WriteLocalTALog(req.LogMsg.ToString());
}
}
private bool IsTaFilterEvent(string eventName)
{
if(string.IsNullOrEmpty(eventName)) //不是事件,是上报属性
{
return false;
}
var cfg = BillLogServerUtils.GetServerConfig().taCfg;
//没有配置过滤
if(cfg == null || cfg.isOpenFilter == false || cfg.filterEvents == null)
{
return false;
}
foreach(var filter in cfg.filterEvents)
{
if(filter == eventName)
{
return true;
}
}
return false;
}
private int CalcTaskIndex(long uid)
{
return (int)(uid % MessageTaskHandler.TaskCount);
}
}
}