|  | 
				
					
	
		
		
		实现了简易的log打印,有以下的特点: 1) 支持向标准输出或者文件打印log 2) 向文件打印log时限制log文件的大小, 同时, 如果在文件大小超出范围的时候, 可以选择下一个文件进行打印.在这里, 文件大小和文件的数量都是可以配置的. 3) 支持分级别打印, 目前分的级别有DEBUG,ERROR,WARN,INFO这几种, 在打印时, 也可以通过宏来开启DEBUG,WARN的log. 4) 在向文件打印log时, 支持多线程, 同样的, 这个也是可以配置的. 分为三个文件,log.h是对外的接口, 提供对文件打印log和对标准输出打印log的简易封装, 具体使用哪种方式, 可以通过宏进行配置;logger.h和logger.cpp是对文件进行打印的类封装, 是一个单件类, 因此继承自前面提过的singleton类. log.h:
 /********************************************************************created:    2008/08/02
 filename:   log.h
 author:        Lichuang
 
 purpose:    log模块的对外接口, 可以根据宏将log打印到文件或者标准
 输出
 *********************************************************************/
 
 #ifndef __LOG_H__
 #define __LOG_H__
 
 #ifdef __USE_LOG_FILE__
 
 #include "logger.h"
 
 #define LOG(runlevel, file, lineno, args)   \
 do                                  \
 {                                   \
 CLogger::GetInstance()->Log(    \
 runlevel, file,         \
 lineno, args);          \
 } while (0)
 
 #define RUN_MSG_LOG(
  )        LOG(INFO, __FILE__, __LINE__, __VA_ARGS__); #define ERROR_MSG_LOG(
  )      LOG(ERROR, __FILE__, __LINE__, __VA_ARGS__); 
 #ifdef LOG_DEBUG_MSG
 #define DEBUG_MSG_LOG(
  )  LOG(DEBUG, __FILE__, __LINE__, __VA_ARGS__); #else
 #define DEBUG_MSG_LOG(
  ) #endif
 
 #ifdef LOG_WARN_MSG
 #define WARN_MSG_LOG(
  )   LOG(WARN, __FILE__, __LINE__, __VA_ARGS__); #else
 #define WARN_MSG_LOG(
  ) #endif
 
 #else
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 #include <stdarg.h>
 #include <sys/time.h>
 
 #define LOG(runlevel, file, lineno, args)   \
 do{ \
 struct timeval now;\
 gettimeofday(&now,0); \
 struct tm *ptm=localtime(&(now.tv_sec)); \
 fprintf(runlevel, "[%d:%d] [%s:%d]",ptm->tm_hour,ptm->tm_min, file,lineno); \
 fprintf(runlevel, args); \
 fprintf(runlevel, "\n"); \
 }while(0)
 
 #define RUN_MSG_LOG(
  )        LOG(stdout, __FILE__, __LINE__, __VA_ARGS__); #define ERROR_MSG_LOG(
  )      LOG(stderr, __FILE__, __LINE__, __VA_ARGS__); 
 #ifdef LOG_DEBUG_MSG
 #define DEBUG_MSG_LOG(
  )  LOG(stdout, __FILE__, __LINE__, __VA_ARGS__); #else
 #define DEBUG_MSG_LOG(
  ) #endif
 
 #ifdef LOG_WARN_MSG
 #define WARN_MSG_LOG(
  )   LOG(stdout, __FILE__, __LINE__, __VA_ARGS__); #else
 #define WARN_MSG_LOG(
  ) #endif
 
 #endif
 
 #endif /* __LOG_H__ */
 
 logger.h
 /********************************************************************created:    2008/08/02
 filename:   logger.h
 author:        Lichuang
 
 purpose:    实现简易的log打印
 *********************************************************************/
 
 #ifndef __LOGGER_H__
 #define __LOGGER_H__
 
 #include "defines.h"
 #include "singleton.h"
 #include "threadmutex.h"
 #include <string>
 
 using namespace std;
 
 struct LogInfo
 {
 int nFileNum;
 string strFileSuffix;
 string strFileName;
 };
 
 enum
 {
 DEBUG = 0,
 WARN,
 ERROR,
 INFO,
 NUM_OF_LOG_LEVEL
 };
 
 class CLogger
 : public CSingleton<CLogger>
 {
 public:
 
 public:
 int Init(const string& strLogPath, const string& strFileName);
 int Log(int nLogLevel, const char* pFileName, int nLine, const char *szFormat,
  ); 
 private:
 DECLARE_SINGLETON_CLASS(CLogger)
 CLogger();
 virtual ~CLogger();
 
 int GetFileName(int nLogLevel);
 int CheckFileSize(const string& strFileName);
 void GenerateFileName(string& strFileName, int nFileNum, int nLogLevel);
 
 private:
 string m_strLogPath;
 string m_strFileName;
 LogInfo m_szLogInfo[NUM_OF_LOG_LEVEL];
 CThreadMutex m_tThreadMutex;
 };
 
 #endif /* __LOGGER_H__ */
 
 logger.cpp
 /********************************************************************created:    2008/08/02
 filename:   logger.h
 author:        Lichuang
 
 purpose:    实现简易的log打印
 *********************************************************************/
 
 #include "logger.h"
 #include <sys/stat.h>
 
 static const char* g_szLogSuffix[] =
 {
 ".debug",
 ".warn",
 ".error",
 ".info",
 NULL
 };
 
 CLogger::CLogger()
 {
 }
 
 CLogger::~CLogger()
 {
 }
 
 int CLogger::Init(const string& strLogPath, const string& strFileName)
 {
 m_strLogPath = strLogPath;
 m_strFileName = strFileName;
 
 for (int i = DEBUG; i < NUM_OF_LOG_LEVEL; ++i)
 {
 m_szLogInfo[i].strFileSuffix = g_szLogSuffix[i];
 if (0 > GetFileName(i))
 return -1;
 }
 
 return 0;
 }
 
 int CLogger::GetFileName(int nLogLevel)
 {
 int i;
 string strFileName;
 for (i = 0; i < MAX_FILE_NUM; ++i)
 {
 GenerateFileName(strFileName, i, nLogLevel);
 if (!CheckFileSize(strFileName))
 {
 break;
 }
 }
 
 if (MAX_FILE_NUM == i)
 {
 return -1;
 }
 
 m_szLogInfo[nLogLevel].nFileNum = i;
 m_szLogInfo[nLogLevel].strFileName = strFileName;
 
 return 0;
 }
 
 int CLogger::CheckFileSize(const string& strFileName)
 {
 struct stat tStat;
 int nRet = ::stat(strFileName.c_str(), &tStat);
 if (0 == nRet && tStat.st_size > MAX_FILE_SIZE)
 {
 return -1;
 }
 else
 {
 return 0;
 }
 }
 
 void CLogger::GenerateFileName(string& strFileName, int nFileNum, int nLogLevel)
 {
 char szFileNum[10];
 ::snprintf(szFileNum, sizeof(szFileNum), "_%02d", nFileNum);
 strFileName = m_strLogPath + m_strFileName + m_szLogInfo[nLogLevel].strFileSuffix + szFileNum;
 }
 
 int CLogger::Log(int nLogLevel, const char* pFileName, int nLine, const char *szFormat,
  ) {
 va_list ap;
 FILE *pFile;
 char szTime[32];
 time_t nCurrTime;
 struct tm stCurrTime;
 
 THREAD_LOCK(m_tThreadMutex);
 
 if (0 > CheckFileSize(m_szLogInfo[nLogLevel].strFileName))
 {
 m_szLogInfo[nLogLevel].nFileNum = (m_szLogInfo[nLogLevel].nFileNum + 1) % MAX_FILE_NUM;
 GenerateFileName(m_szLogInfo[nLogLevel].strFileName, m_szLogInfo[nLogLevel].nFileNum, nLogLevel);
 }
 
 if(NULL == (pFile = ::fopen(m_szLogInfo[nLogLevel].strFileName.c_str(), "a+")))
 {
 return -1;
 }
 
 ::time(&nCurrTime);
 ::localtime_r(&nCurrTime, &stCurrTime);
 ::snprintf(szTime, sizeof(szTime), "%d%02d%02d %02d:%02d:%02d",
 stCurrTime.tm_year+1900, stCurrTime.tm_mon+1, stCurrTime.tm_mday,
 stCurrTime.tm_hour, stCurrTime.tm_min, stCurrTime.tm_sec);
 ::fprintf(pFile, "[%s]:[%s][%d] ", szTime, pFileName, nLine);
 
 ::va_start(ap, szFormat);
 ::vfprintf(pFile, szFormat, ap);
 ::va_end(ap);
 
 ::fprintf(pFile, "\n");
 ::fclose(pFile);
 
 THREAD_UNLOCK(m_tThreadMutex);
 
 return 0;
 }
 
   |