技术系列之 必备外围功能-log

log模块是一个小模块,却是每个系统必备的模块。优秀的系统一定会有优秀的log信息,也可以说全面到位的log信息在一定程度上决定了一个系统的健壮性。在linux上,log模块是跟踪程序运行,验证业务逻辑正确的唯一方法。
一、功能
一个优秀的log系统应该包含以下功能:
(1)支持打印到屏幕、文件、socket、syslog
(2)支持分级别打印
(3)支持分模块打印
(4)支持多线程
(5)支持文件转储:按时间、按大小。
二、使用原则
方便说明,这里定义8个log级别:

typedef  enum {
    XLOG_CRITICAL
=0x1,
    XLOG_ERROR
=0x2,
    XLOG_WARNING
=0x4,
    XLOG_NOTICE
=0x8,
    XLOG_INFO
=0x10,
    XLOG_DEBUG
=0x20,
    XLOG_TRACE
=0x40,
    XLOG_ALL
=0x80
}
XLogLevel;

使用方式举例如下:

X_LOG(XLOG_NOTICE, " message[%s:%d]/n " ,char_value,int_value);

打印log的原则:
(1)重要的函数(业务处理)入口处打印XLOG_DEBUG级别log,打印出函数名称、入口参数。
(2)函数有多个执行支路,在异常退出函数的支路上,打印XLOG_WARNING级别log,表明退出原因。
(3)系统调用发生异常,甚至造成程序退出的地方,打印XLOG_ERROR级别log,表明发生该错误的文件、行数、错误号
(4)为所有的类对象实现dump方法,该方法打印该类中的所有私有属性信息,以XLOG_NOTICE级别打印,当类对象中含有自定义的类属性时,该类的dump中打印属性类信息可以直接调用属性类的dump。运行期间,可以给用户提供输入接口:telnet、交互式shell命令行、或者简单的getchar,根据用户要求,执行顶级类对象的dump,以运行期间查看系统内所有数据的内部信息。
(5)该系统与外在系统的交互信息,往来数据包使用XLOG_INFO级别打印。
(6)为了调试系统,更为细微的查看系统的运行状况而加入的log,使用XLOG_TRACE级别。
三、log模块框架
可选的开源log很多:ace_log/Log4c/log4c**/log4c++/Pantheios/Log4cplus。依据开源项目活跃程度、库本身的独立性以及参考文档的数量,个人选择的开源库是Log4cplus。个人测试,未发现该库(v1.02)有bug或者内存泄漏现象,大力推荐。网上有关该库的文档的也相当多,我就不再罗唆了。
下面是我的log框架,不依赖于具体的log模块,相信你会喜欢:

#ifndef _X_LOG_H_
#define _X_LOG_H_
#include 
< stdio.h >
#include 
< errno.h >

#ifdef USE_LOG4CPLUS
    #include 
< log4cplus / configurator.h >
    #include 
< string >
    
static  log4cplus::Logger logger =  log4cplus::Logger::getInstance( " Log " );
    
static   void  init_log( const  std::string  &  path)
    
{
        log4cplus::PropertyConfigurator::doConfigure(path);   
    }

    #define XLOG_ALL        log4cplus::TRACE_LOG_LEVEL
    #define XLOG_TRACE        log4cplus::TRACE_LOG_LEVEL
    #define XLOG_DEBUG        log4cplus::DEBUG_LOG_LEVEL
    #define XLOG_INFO            log4cplus::INFO_LOG_LEVEL
    #define XLOG_NOTICE        log4cplus::INFO_LOG_LEVEL
    #define XLOG_WARNING    log4cplus::WARN_LOG_LEVEL
    #define XLOG_ERROR        log4cplus::ERROR_LOG_LEVEL
    #define XLOG_CRITICAL    log4cplus::FATAL_LOG_LEVEL

    #define X_LOG(l, ) /
    
do   { /
        
if(logger.isEnabledFor(l)) { /
            
char __buf__internal__[2046]={0}; /
            snprintf(__buf__internal__,
2045,__VA_ARGS__); /
            logger.forcedLog(l, __buf__internal__, __FILE__, 

__LINE__); /
        }
 /
    }
  while ( 0 );
#elif define USE_ACE_LOG
    #include 
" ace/Log_Msg.h "
    #include 
" ace/Trace.h "
    #define XLOG_ALL        LM_TRACE
    #define XLOG_TRACE        LM_TRACE
    #define XLOG_DEBUG        LM_DEBUG
    #define XLOG_INFO             LM_INFO
    #define XLOG_NOTICE        LM_NOTICE
    #define XLOG_WARNING    LM_WARNING
    #define XLOG_ERROR        LM_ERROR
    #define XLOG_CRITICAL        LM_CRITICAL
    #define X_LOG(l,
do { /
        ACE_DEBUG((l,
"[%T|%t] %s-%s:%

d
",__FILE__,__FUNCTION__,__LINE__)); /
        ACE_DEBUG((l,__VA_ARGS__)); /
        }
while ( 0 )
#
else
    #include 
< pthread.h >
    #include 
< time.h >
    #include 
< sys / time.h >
    #define XLOG_LEVEL 
0xFF
    typedef 
enum {
        XLOG_CRITICAL
=0x1,
        XLOG_ERROR
=0x2,
        XLOG_WARNING
=0x4,
        XLOG_NOTICE
=0x8,
        XLOG_INFO
=0x10,
        XLOG_DEBUG
=0x20,
        XLOG_TRACE
=0x40,
        XLOG_ALL
=0x80
    }
XLogLevel;
    #define X_LOG(l,
do { /
        
if(XLOG_LEVEL&l){ /
                struct timeval now;/
                gettimeofday(
&now,0); /
                struct tm 
*ptm=localtime(&(now.tv_sec)); /
                printf(
"[%d|%d:%d:%d.%d] [%s/%s/%d] 

",pthread_self(),ptm->tm_hour,ptm->tm_min,ptm-

>tm_sec,now.tv_usec,__FILE__,__FUNCTION__,__LINE__); /
                printf( __VA_ARGS__); /
            }
 /
        }
while ( 0 )
#endif

#define die(str) 
{X_LOG(XLOG_WARNING,str); return;}

#define die_0(str) 
{X_LOG(XLOG_WARNING,str); return 0; }

#define die_1(str) 
{X_LOG(XLOG_WARNING,str); return -1; }

#define die_ns(str) 
{X_LOG(XLOG_WARNING,str); return ""; }

/*safe func return empty,0,-1*/
#define SAFE_FUNC(func) 
if ((func) < 0 ) /
    
{ /
        X_LOG(XLOG_ERROR,
"[%s:%d]error!error[%d:%s]

/n
",__FILE__,__LINE__,errno,strerror(errno)); /
        exit(-1); /
    }


/*safe func but 1 err return empty,0,-1*/
#define SAFE_FUNC_BUT_ERR1(func,ERR1) 
do  /
    
{ /
        
if((func)<0){ /
            X_LOG(XLOG_ERROR,
"[%s:%d]error!error[%d:%s]

/n
",__FILE__,__LINE__,errno,strerror(errno)); /
            if(errno!=ERR1) exit(-1); /
        }
 /
        
else break; /
    }
while ( 1 )

/*safe func but 2 err return empty,0,-1*/
#define SAFE_FUNC_BUT_ERR2(func,ERR1,ERR2) 
do  /
    
{ /
        
if((func)<0){ /
            X_LOG(XLOG_ERROR,
"[%s:%d]error!error[%d:%s]

/n
",__FILE__,__LINE__,errno,strerror(errno)); /
            if(errno!=ERR1&&errno!=ERR2)  exit(-1); /
        }
 /
        
else break; /
    }
while ( 1 )
#endif

当前的XLog.h文件实现了使用log4cplus、ace、printf三种方式,当然可以随意扩展。die则是XLOG_WARNING的打印方式,SAFE_FUNC是XLOG_ERROR的打印方式。
如果要使用log4cplus,请定义USE_LOG4CPLUS宏,使用的时候在进程开始处,

#ifdef  USE_LOG4CPLUS
  init_log(
" log.properties " );
#endif

以X_LOG的方式使用log4cplus,你可以对log4cplus一无所知。执行你编译好的程序前,在可执行程序的目录下建立log.properties文件,内容你可以这样写:

# Define the root logger
log4cplus.rootLogger
= TRACE, consoleAppender, fileAppender

# Define a file appender named 
" consoleAppender "
log4cplus.appender.consoleAppender
= log4cplus::ConsoleAppender
log4cplus.appender.consoleAppender.layout
= log4cplus::PatternLayout
log4cplus.appender.consoleAppender.layout.ConversionPattern
=%- 5p - [ % t][ % D {%H:%M:%%Q} ] % m

# Define a file appender named 
" fileAppender "
log4cplus.appender.fileAppender
= log4cplus::RollingFileAppender
log4cplus.appender.fileAppender.MaxFileSize
= 200KB
log4cplus.appender.fileAppender.File
= . / log.log
log4cplus.appender.fileAppender.MaxBackupIndex
= 3
log4cplus.appender.fileAppender.layout
= log4cplus::PatternLayout
log4cplus.appender.fileAppender.layout.ConversionPattern
=%- 5p - [ % t][ % D {%H:%M:%%Q} ] % m

有关log.properties文件的配置,可以自行去查找有关log4cplus的文章。如果你没使用过log4cplus,ok,那么下载一个log4cplus,编译,依据本文的XLog.h文件构建一个系统,尝试以下,你一定会惊叹log4cplus的强大与美妙。

(本文首次发表于http://www.cppblog.com/CppExplore/archive/2008/06/05/52216.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值