首页 / 软件开发 / C++ / 一个简单又高效的日志系统
一个简单又高效的日志系统2011-02-04 vckbase 大唐 三枝花一、程序日志是商品程序中必不可少的部分。在正式商用的程序中一般对于日志都会有一些类似的要求:性能要求运行时日志级别可调整日志文件空间使用安全性问题下面逐一针对上面的问题一起分析程序实现。二、性能问题。客户对程序的要求当然是越高越好。如果对于日志打印采用普通的方法,来一条日志就写一条日志到文件中,这样性能是很低的。因为程序不断的与磁盘进行交付,对系统的冲击很大,有可能会影响到正常的磁盘IO请求。对于这个问题,一般的,都是采用批量写入的方法来解决。每写一条日志,并不是把日志立即写入文件中,而是先写到一个缓冲区中。当这个缓冲区达到一定的量时,再一次批量写入到文件中。见如下代码实现:if (!strLog.IsEmpty())
{
m_strWriteStrInfo += GetCurTimeStr();
// 增加日志级别信息
if (enLevel == ENUM_LOG_LEVEL_ERROR)
{
m_strWriteStrInfo += _T("Error! ");
}
m_strWriteStrInfo += strLog;
m_strWriteStrInfo += _T("
");
}
if ( bForce
|| m_strWriteStrInfo.GetLength() > MAX_STR_LOG_INFO_LEN
|| m_iWriteBinLogLen > MAX_BIN_LOG_INFO_LEN/10)
{
// write info,达到一定量时才提交到文件中
WriteLogToFile();
}
但这样会带来一个问题,如果日志量比较少,很可能要很久才能达到批量提交的量,这样就会造成程序写了日志,但是日志写入器还是把消息写在缓冲区里,文件中没有及时体现出来。我们可以采用定时又定时的办法来输出日志。程序对缓冲区内的日志消息定时强制刷新到文件中去。为了体现程序的使用简单性,把这个功能放在日志模块中实现了,从而调用日志的程序就不用考虑定时来刷新文件了。见如下程序实现:CSuperLog::CSuperLog(void)
{
// 初始化临界区变量
InitializeCriticalSection(&m_csWriteLog);
// 启动信息
m_strWriteStrInfo = WELCOME_LOG_INFO;
// Create the Logger thread.
m_hThread = (HANDLE)_beginthreadex( NULL, 0, &LogProcStart, NULL, 0, &m_uiThreadID );
}
unsigned __stdcall CSuperLog::LogProcStart( void* pArguments )
{
int nCount = 1;
do
{
Sleep(300);
if (++nCount % 10 == 0 )
{
WriteLog(strTemp, ENUM_LOG_LEVEL_ERROR, true); // 每隔三秒写一次日志
}
} while (m_bRun);
}
采有一个全局日志类变量,在构造函数中启动线程,线程每隔三秒去刷新一次文件。