基于log4cpp和boost的日志模块

时间:2022-09-09 08:54:03

头文件:

#ifndef LOG4CPP 
#define LOG4CPP 
#include <log4cpp/Category.hh> 
#include <log4cpp/FileAppender.hh> 
#include <log4cpp/BasicLayout.hh> 
#include <log4cpp/RollingFileAppender.hh> 
#include <log4cpp/PatternLayout.hh> 
 
namespace niiwoo  
{ 
namespace util 
{ 
namespace log 
{ 
        enum LOG_LEVEL 
        { 
                        LOG_LEVEL_NONE  = 0,    // 不打日志      
                        LOG_LEVEL_ERROR = 1, 
                        LOG_LEVEL_WARN  = 2, 
                        LOG_LEVEL_INFO  = 3, 
                        LOG_LEVEL_DEBUG = 4, 
 
                        LOG_LEVEL_MAX   = 5       
        }; 
         
        enum ERR_CODE 
        { 
                ERR_CODE_OK = 0, 
                ERR_CODE_PATH = -1, 
 
                OTHER_ERR = -2 
        }; 
 
        // 调用NiiwooLog* GetInstance()->Init() 初始化之后,即可使用以下宏打印日志 
        // DEBUG级别日志会同时打印到屏幕一份 
        #define LOG4_DEBUG(...) NiiwooLog::GetInstance()->Log(LOG_LEVEL_DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) 
        #define LOG4_WARN(...) NiiwooLog::GetInstance()->Log(LOG_LEVEL_WARN, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) 
        #define LOG4_INFO(...) NiiwooLog::GetInstance()->Log(LOG_LEVEL_INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) 
        #define LOG4_ERROR(...) NiiwooLog::GetInstance()->Log(LOG_LEVEL_ERROR, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)    
 
        class NiiwooLog 
        { 
        public: 
                ERR_CODE Init(std::string strLogPath, std::string strModName, LOG_LEVEL lev, long iLogFileSize, long iLogPathSize);//ilogFileSize:size of per log file:Byte,iLogPathSize:Maxsize of LogPath:Byte 
        private: 
                NiiwooLog(); 
                virtual ~NiiwooLog(); 
      public:
<span style="white-space:pre">		</span>static NiiwooLog* GetInstance();


<span style="white-space:pre">		</span>int Log(LOG_LEVEL lev, char const *file, int line, char const *func, char const *format, ...);
<span style="white-space:pre">		</span>int SetFileName(std::string& FileName, std::string strModName);
<span style="white-space:pre">		</span>ERR_CODE CheckPath(std::string &strLogPath);
<span style="white-space:pre">		</span>int SetLev(LOG_LEVEL lev);
<span style="white-space:pre">		</span>int RebuildCurLog();
<span style="white-space:pre">		</span>void LogClearTimer(std::string strLogPath, long lPathSize);
<span style="white-space:pre">	</span>private:
<span style="white-space:pre">			</span>
<span style="white-space:pre">		</span>LOG_LEVEL m_lev;
<span style="white-space:pre">		</span>log4cpp::Category *m_pTotal;
<span style="white-space:pre">		</span>log4cpp::PatternLayout *m_pLayout;
<span style="white-space:pre">		</span>log4cpp::RollingFileAppender *m_pAppender;
<span style="white-space:pre">			</span>
<span style="white-space:pre">		</span>bool m_isRunning;<span style="white-space:pre">	</span>
<span style="white-space:pre">		</span>std::string m_strLogPath;
<span style="white-space:pre">		</span>std::string m_strCurLog;
<span style="white-space:pre">		</span>std::string m_strModName;
<span style="white-space:pre">		</span>unsigned long m_lMaxFileSize;
<span style="white-space:pre">	</span>};
}
}
}
#endif           
                                                                                                      


实现程序

#include <boost/format.hpp>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include "log4.h"

#define MAX_PATH_LEN 1024
#define MAX_LOG_LEN 1024

using namespace std;
namespace fs = boost::filesystem;

namespace niiwoo
{

	namespace util
	{

		namespace log
		{

			NiiwooLog::NiiwooLog()
			{
				m_isRunning = false;
				m_strLogPath = "/usr/local/var/NiiwooLog/";
				m_strCurLog = "/usr/local/var/NiiwooLog/NiiwoLog.log";
				m_lMaxFileSize = 2*1024;
			}	

			NiiwooLog* NiiwooLog::GetInstance()
			{
				static NiiwooLog log;
				return &log;
			}

			int NiiwooLog::Log(LOG_LEVEL lev, char const *file, int line, char const *func, char const *format, ...)
			{
				if(m_isRunning == false)
				{
					return -1;
				}
				if(lev>m_lev||m_lev == LOG_LEVEL_NONE)
				{
					return -1;
				}
				char buf[MAX_LOG_LEN]={0};
				char buff[MAX_LOG_LEN]={0};
				char *p1;	
				snprintf(buf,1024, "%s:%d@%s@", file, line, func);

				va_list argptr;
				va_start(argptr, format);
				vsnprintf(buf+strlen(buf), MAX_LOG_LEN, format, argptr);
				va_end(argptr);
				p1 = buf;
				for(int i=0;i<(int)(strlen(buf));i++)
				{
					if(buf[i]==':')
						break;
					if(buf[i]=='/')
					{
						p1 = buf+i;
					}

				}
				memcpy(buff,p1+1,strlen(p1)-1);
				switch(lev)
				{
					case LOG_LEVEL_ERROR:
						m_pTotal->error(buff);
						break;
					case LOG_LEVEL_WARN:
						m_pTotal->warn(buff);
						break;
					case LOG_LEVEL_INFO:
						m_pTotal->info(buff);
						break;
					case LOG_LEVEL_DEBUG:
						std::cout<<buff<<std::endl;
						m_pTotal->debug(buff);
						break;
					default:
						break;
				}

				return 0;
			}

			ERR_CODE NiiwooLog::CheckPath(std::string &strLogPath)
			{
				if(strLogPath.empty())
				{
					return ERR_CODE_PATH;
				}
				if(strLogPath.at(strLogPath.size()-1)!='/')
				{
					strLogPath += '/';
				}

				if (!fs::exists(strLogPath))
				{
					fs::create_directory(strLogPath);
				}	
				return ERR_CODE_OK;
			}

			int  NiiwooLog::SetFileName(std::string& strFileFullPath, std::string strModName)
			{
				struct timeval    tv;  
				struct timezone tz;  
				struct tm *tm_now;  
				gettimeofday(&tv, &tz);
				tm_now = localtime(&tv.tv_sec);
				int us = tv.tv_usec/1000;

				strFileFullPath += (boost::format("%s_%04d-%02d-%02d_%02d.%02d.%02d.%02d.log")%strModName 
						%(tm_now->tm_year+1900) %(tm_now->tm_mon+1) %tm_now->tm_mday %tm_now->tm_hour %tm_now->tm_min %tm_now->tm_sec %us).str();
				return 0;	
			}

			unsigned long get_file_size(const char *path)  
			{  
				unsigned long filesize = -1;      
				struct stat statbuff;  
				if(stat(path, &statbuff) < 0)
				{  
					return filesize;  
				}
				else
				{  
					filesize = statbuff.st_size;  
				}  
				return filesize;  
			} 			


			void NiiwooLog::LogClearTimer(std::string strLogPath, long lPathSize)
			{
				while(1)
				{
					fs::path RootPath(strLogPath);
					long lTotalSize=0;
					vector<std::string> FileVector;
					fs::path CurLogFullPath(m_strCurLog);

					if (!fs::exists(CurLogFullPath))
					{
						//fs::create_directory(CurLogFullPath);
						RebuildCurLog();
					}

					if(get_file_size(m_strCurLog.c_str()) > m_lMaxFileSize)
					{
						RebuildCurLog();
					}

					fs::directory_iterator end_iter;
					for (fs::directory_iterator iter(RootPath); iter!=end_iter; ++iter)
					{	
						if (fs::is_regular_file(iter->status()))
						{	
							FileVector.push_back(iter->path().string());
							fs::path PathIter = iter->path();
							if(fs::exists(PathIter))
								lTotalSize += fs::file_size(PathIter);
						}

					}

					if(lTotalSize > lPathSize)
					{
						std::sort(FileVector.begin(),FileVector.end());
						vector<std::string>::iterator it;
						for(it=FileVector.begin(); it!=FileVector.end();)
						{
							fs::path PathIter(*it);
							cout<<*it<<endl;
							if(fs::exists(PathIter))
							{
								lTotalSize -= fs::file_size(PathIter);
								fs::remove(PathIter);
							}
							FileVector.erase(it);
							if(lTotalSize <= lPathSize)
								break;
						}
					}

					boost::this_thread::sleep(boost::posix_time::seconds(1800));
				}
			}

			int NiiwooLog::RebuildCurLog()
			{
				if(m_isRunning == false)
				{
					std::cout<<"log module need init"<<std::endl;
					return -1;
				}
				std::string strNewLogFileFullPath;
				strNewLogFileFullPath = (boost::format("%s")%m_strLogPath).str();
				SetFileName(strNewLogFileFullPath, m_strModName);

				m_pTotal->shutdown();
				log4cpp::PatternLayout* DebugLo = new log4cpp::PatternLayout();
				DebugLo->setConversionPattern("%d{%Y-%m-%d %H:%M:%S.%l}[%p]%m%n");

				//log4cpp::RollingFileAppender* Debug_Appender = new log4cpp::RollingFileAppender("Debug_Appender",strNewLogFileFullPath.c_str(), m_lMaxFileSize, 0);
				log4cpp::Appender* Debug_Appender = new log4cpp::FileAppender("Debug_Appender",strNewLogFileFullPath.c_str(),true,0666);
				Debug_Appender->setLayout(DebugLo);

				m_pLayout = DebugLo;
				//m_pAppender = Debug_Appender;

				m_pTotal->setAdditivity(false);
				m_pTotal->setAppender(Debug_Appender);

				m_strCurLog.clear();
				m_strCurLog = strNewLogFileFullPath;	
				return 0;
			}



			ERR_CODE NiiwooLog::Init(std::string strLogPath, std::string strModName, LOG_LEVEL iLogLevel, long iLogFileSize, long iLogPathSize)
			{
				if(m_isRunning)
				{
					std::cout<<"log module has been init"<<std::endl;
					return OTHER_ERR;
				}
				iLogPathSize *= 1024*1024;
				iLogFileSize *= 1024*1024;

				std::string strFileFullPath;
				ERR_CODE errCode;
				if((errCode = CheckPath(strLogPath)) != ERR_CODE_OK)
				{
					return errCode;
				}

				strFileFullPath = str(boost::format("%s")%strLogPath);
				SetFileName(strFileFullPath, strModName);

				m_lev = iLogLevel;
				m_strLogPath.clear();
				m_strLogPath = strLogPath;
				m_strCurLog = strFileFullPath;
				m_lMaxFileSize = (iLogFileSize>1*1024*1024)?iLogFileSize:1*1024*1024;
				iLogPathSize = (iLogPathSize/m_lMaxFileSize>=100)?iLogPathSize:m_lMaxFileSize*100;
				m_strModName = strModName;

				log4cpp::Category& total = log4cpp::Category::getInstance("total");
				m_pTotal = &total;

				log4cpp::PatternLayout* DebugLo = new log4cpp::PatternLayout();
				DebugLo->setConversionPattern("%d{%Y-%m-%d %H:%M:%S.%l}[%p]%m%n");

				//log4cpp::RollingFileAppender* Debug_Appender = new log4cpp::RollingFileAppender("Debug_Appender", strFileFullPath.c_str(), m_lMaxFileSize,100);
				log4cpp::Appender* Debug_Appender = new log4cpp::FileAppender("Debug_Appender",strFileFullPath.c_str(),true,0666);
				Debug_Appender->setLayout(DebugLo);

				m_pLayout = DebugLo;
				//m_pAppender = Debug_Appender;

				m_pTotal->setAdditivity(false);
				m_pTotal->setAppender(Debug_Appender);

				switch(m_lev)
				{
					case LOG_LEVEL_ERROR:
						m_pTotal->setPriority(log4cpp::Priority::ERROR);
						break;
					case LOG_LEVEL_WARN:
						m_pTotal->setPriority(log4cpp::Priority::WARN);
						break;
					case LOG_LEVEL_INFO:
						m_pTotal->setPriority(log4cpp::Priority::INFO);
						break;                
					case LOG_LEVEL_DEBUG:
						m_pTotal->setPriority(log4cpp::Priority::DEBUG);
						break;
					default:
						m_pTotal->setPriority(log4cpp::Priority::DEBUG);
						break;
				}

				m_isRunning = true;

				boost::thread ThreadLogClearTimer(boost::bind(&NiiwooLog::LogClearTimer, this,  strLogPath, iLogPathSize));
				return ERR_CODE_OK;
			}

			int NiiwooLog::SetLev(LOG_LEVEL lev)
			{
				m_lev=lev;
				switch(m_lev)
				{
					case LOG_LEVEL_ERROR:
						m_pTotal->setPriority(log4cpp::Priority::ERROR);
						break;
					case LOG_LEVEL_WARN:
						m_pTotal->setPriority(log4cpp::Priority::WARN);
						break;
					case LOG_LEVEL_INFO:
						m_pTotal->setPriority(log4cpp::Priority::INFO);
						break;                
					case LOG_LEVEL_DEBUG:
						m_pTotal->setPriority(log4cpp::Priority::DEBUG);
						break;
					default:
						m_pTotal->setPriority(log4cpp::Priority::DEBUG);
						break;
				}
				return lev;
			}

			NiiwooLog::~NiiwooLog()
			{
				//log4cpp::Category::shutdown();
			}
		}
	}
}


测试程序:

#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/BasicLayout.hh>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "log4.h"

using namespace niiwoo::util::log;

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		printf("please input debug level,0:none,1:error,2:warn,3:info,other:debug\n");
		return 0;
	}
	int lev = atoi(argv[1]);

	std::string name("yanglei");
	std::string module=("log4cpp");
	std::string path("/opt/LogPath");

	LOG_LEVEL level;
	switch(lev)
	{
		case 0:
			level = LOG_LEVEL_NONE;
			break;
		case 1:
			level = LOG_LEVEL_ERROR;
			break;
		case 2:
			level = LOG_LEVEL_WARN;
			break;
		case 3:
			level = LOG_LEVEL_INFO;
			break;
		default:
			level = LOG_LEVEL_DEBUG;
	}
	
	NiiwooLog *pLog;
	pLog = NiiwooLog::GetInstance();
	pLog->Init(path, module, level, 0, 100);
    for(int i=0; i<=500000; i++)
    {
	LOG4_DEBUG("//debug log test,//%s-%s-%d//", name.c_str(), module.c_str(), 2014);
	LOG4_INFO("//error log test,//%s-%s-%d//",name.c_str(), module.c_str(),2014);
	LOG4_WARN("//warn log test,//%s-%s-%d//",name.c_str(), module.c_str(),2014);
	LOG4_ERROR("//info log test,//%s-%s-%d//",name.c_str(), module.c_str(),2014);
    }
    /*	
	pLog->RebuildCurLog();
	LOG4_DEBUG("debug log test,%s-%s-%d", name.c_str(), module.c_str(), 2014);
        LOG4_INFO("error log test,%s-%s-%d",name.c_str(), module.c_str(),2014);
        LOG4_WARN("warn log test,%s-%s-%d",name.c_str(), module.c_str(),2014);
        LOG4_ERROR("info log test,%s-%s-%d",name.c_str(), module.c_str(),2014);
	//在不使用log4cpp时可调用log4cpp::Category::shutdown(),其功能如同HierarchyMaintainer的内存清理。但如果不手动调用,在程序结束时HierarchyMaintainer会调用Category的析构函数来释放所有Appender。
	*/
	return 0;
}

依赖库:

liblog4cpp.a
libboost_filesystem.a
libboost_thread.a

相关文章