服务器公共库开发--log系统
实现了简易的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:
logger.h
logger.cpp
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__ */
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__ */
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 ;
}
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 ;
}