基于消息机制的日志类

之前用的日志记录是阻塞式的,会影响主程序的运行。于是我决定自己撸一个用消息机制来记录日志的日志类。

既然是要用消息机制,肯定要有一个消息队列,还要有一个线程来不断接收消息,写日志。另外还需要使用单例类来管理日志的记录

首先来看主体代码,Run:

int CLogByMsg::Run(){
	int iSize;
	while (m_bExist){
		Sleep(10);
		iSize = m_QLogMsg.size();
		if (m_QLogMsg.empty()){
			continue;
		}
		CLogParam logMsg = m_QLogMsg.front();
		m_QLogMsg.pop();
		fprintf(m_pLogFile, "[%s][%s-%d] [%04d-%02d-%02d %02d:%02d:%02d.%d]\t\t%s \n",
			logMsg.strFunction.c_str(),
			logMsg.strFile.c_str(),
			logMsg.lLine,
			logMsg.sysTime.wYear,
			logMsg.sysTime.wMonth,
			logMsg.sysTime.wDay,
			logMsg.sysTime.wHour,
			logMsg.sysTime.wMinute,
			logMsg.sysTime.wSecond,
			logMsg.sysTime.wMilliseconds,
			logMsg.strLog.c_str());
		m_lCnt++;
		if (m_lCnt % 20 == 0){
			fclose(m_pLogFile);
			m_pLogFile = NULL;
			Sleep(100);
			string strLogWithTime;
			GetLogFileNameWithTime(m_strLogFilePath, strLogWithTime);
			m_pLogFile = fopen(strLogWithTime.c_str(), "a+");
		}
	}
	return eSucess;
}


代码很简单,就循环判断消息队列是否为空,如果不为空则往文件里写日志。

如果日志记录已经超过了20条,则将文件关闭一次,然后重新打开。之所以要这样是因为fclose文件后,缓存中的数据才会真正写到硬盘中,这样在程序运行期时,我们仍然看到日志。


那如何往队列里添加消息呢?用这两个方法:

CLogByMsg::eResult  CLogByMsg::WriteLog(const char* lpFile, const char * lpFunction ,long lLine,  const char* lpLog){
	SYSTEMTIME sys;
	GetLocalTime(&sys);
	SendLog(sys, lpFile, lpFunction, lLine, lpLog);
	return eSucess;
}

int CLogByMsg::SendLog(SYSTEMTIME sys, const char* lpFile, const char * lpFunction, long lLine, const char* lpLog){
	EnterCriticalSection(&g_QueueECS);
	m_QLogMsg.push(CLogParam(sys,lpLog, lpFile, lpFunction, lLine));
	LeaveCriticalSection(&g_QueueECS);
	return eSucess;
}

WriteLog是公开的方法,而SendLog是私有方法。SendLog则是往消息队列中添加CLogParam类型的消息。因为日志常常会在线程中使用,所以还要为消息队列加锁


CLogParam定义如下 :

class CLogParam
{
public:
	CLogParam();
	CLogParam(SYSTEMTIME sys,const char * pcLog, const char * pcFile, const char * pcFunction, long lLine);
	~CLogParam(); 
	//系统时间
	SYSTEMTIME sysTime;
	// 日志信息
	string strLog;
	// 日志记录时所处的文件位置
	string strFile;
	// 日志记录时所处的函数
	string strFunction;
	// 日志记录时,所处代码中的行号
	long lLine;

};

包括记录日志的时间,文件位置 ,函数等。


最后是调用。在这里我们用宏来完成日志的初始化和记录,原因我们后面讲。

首先是日志类的初始化,要调用:

#define  LOG_CREATE(pcPath)  CLogByMsg::GetInstance()->Create(pcPath)
pcPath就是日志要存储的位置。而Create文件要做的事也很简单,将pcPath文件打开


释放时调用

#define  LOG_RELEASE() CLogByMsg::GetInstance()->Release();
LOG_RELEASE会把日志文件关闭


如果要记录日志就调用

#define  LOG_INFO(pcLog) CLogByMsg::GetInstance()->WriteLog(__FILE__, __FUNCTION__, __LINE__, pcLog)

利用LOG_INFO来记录,__FILE__, __FUNCTION__, __LINE__,分别表示该行代码所在的文件,所属于的函数,和该代码在本代码页中的行数。这些数据将会在编译时将这些数据作为char*类型参数输入到WriteLog中。

而利用LOG_INFO宏就避免了每次调用WriteLog时,都要输入__FILE__, __FUNCTION__, __LINE__这几个参数,只要这样使用就行了。

LOG_INFO("begin connect");

该日志类还可以写成dll,直接被调用。

具体可以看我的工程:基于消息机制的日志类

在里面已经直接做成了dll,使用时,只要有LogByMsg.dll和LogByMsg.lib就行了。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值