服务器公共库开发--log系统

服务器公共库开发--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:

/* *******************************************************************
    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 ;
}


你可能感兴趣的:(服务器公共库开发--log系统)