log4cplus解读


主要模块:Loggers,Appenders,Layouts
codeproject中对于三个主要模块的功能介绍:These three types of components work together to enable developers to log messages according to message type and level, and to control at runtime how these messages are formatted and where they are reported.
Layout模块:在1.0.2版本中三类输出格式定义:

SimpleLayout, TTCCLayout and PatternLayout. The following are the examples

SimpleLayout : DEBUG - Hello world

TTCCLayout : 225 [main] INFO Hello World

PatternLayout:INFO 21 May 2001 11:00:57,109 HELLO WORLD

Appender模块:决定了将日志输出到具体的devices。

    用户自己可以根据Appender实现继承类,将log输出到socket, a shared memory buffer或者其他设备上。在1.0.2版本中, FileAppender, RollingFileAppender, and ConsoleAppender

Logger模块:实现了logging, 一个logger对象主要包括了两个主要部分appenders和 log level。

    logger对象被创建的时候,其中包含了默认的appender标准输出和默认的priority with none。之后可以添加更多的appenders到指定的logger,priority的等级划分 NOT_SET_LOG_LEVEL, TRACE_LOG_LEVEL, DEBUG_LOG_LEVEL, INFO_LOG_LEVEL, WARN_LOG_LEVEL, ERROR_LOG_LEVEL, FATAL_LOG_LEVEL。Appenders类集合在Logger类中由hierarchy类负责管理。

主要使用流程:

1. 如果需要初始化一个console appender或者一个 file appender: 

SharedAppenderPtr myAppender(new FileAppender("myLogFile.log"));

myAppender->setName("myAppenderName");

2. 如果需要初始化layout对象:
std::auto_ptr<Layout>; myLayout = std::auto_ptr<Layout>(new log4cplus::TTCCLayout());
3. 绑定layout到appender:
myAppender->setLayout( myLayout );
4. 初始化logger:
Logger myLogger= Logger::getInstance("myLoggerName");
5. 绑定appender到logger:
myLogger.addAppender(myAppender);
6. 设置loglevel:
myLogger.setLogLevel ( INFO_LOG_LEVEL );
7. 最后输出log消息到指定logger:

LOG4CPLUS_FATAL(myLogger, "logEvent");//for a fatal priority event

LOG4CPLUS_ERROR(myLogger, "logEvent");//for a error priority event

LOG4CPLUS_WARN(myLogger, "logEvent") ;//for a warn priority event

LOG4CPLUS_INFO(myLogger, "logEvent"); //for a info priority event

LOG4CPLUS_DEBUG(myLogger, "logEvent");//for a debug priority event

log4cplus在了解了几个主要模块功能之后,自己耐心解读应该不会很难

读源码的时候可以参考:

(一) http://www.cppblog.com/tx7do/articles/11715.html

(二) http://www.cppblog.com/tx7do/articles/11716.html

(三) http://www.cppblog.com/tx7do/articles/11717.html

(四) http://www.cppblog.com/tx7do/articles/11718.html

(五) http://www.cppblog.com/tx7do/articles/11719.html

(六) http://www.cppblog.com/tx7do/articles/11720.html

(七) http://www.cppblog.com/tx7do/articles/11721.html

一些收获

1. static局部变量的使用:

class Logger
{
... // others
Hierarchy& Logger::getDefaultHierarchy()
{
static Hierarchy defaultHierarchy;
return defaultHierarchy;
}
}
Hierarchy类用以管理logger树,使用map来维持所有logger,并且管理父Logger和子Logger的关系。
所有的Logger类需要具有唯一的一个defaultHierarchy ,如果是我,可能会将Hierarchy设计成单例模式,或者直接在Logger类中添加成员变量static defaultHierarchy。作者采用的方法利用了static局部变量的特性,同时很好的对外隐藏了defaultHierarchy,以及更小的限定了作用域。
另例:同样以static局部变量达到了singleton的效果。
class LOG4CPLUS_EXPORT LogLevelManager {
    /**
     * Returns the singleton LogLevelManager.
     */
    LOG4CPLUS_EXPORT LogLevelManager& getLogLevelManager() {}
}
LogLevelManager&
log4cplus::getLogLevelManager()
{
    static LogLevelManager singleton;
    return singleton;
}

2. 大量采用Impl设计方式( 进一步学习http://blog.csdn.net/onejian/article/details/17484283
class LoggerImpl;
class Logger
{
...
protected:

     // Data
     /** This is a pointer to the implementation class. */
     spi::LoggerImpl *value;
    // Friends
    friend class log4cplus::spi::LoggerImpl;

}

实现类中私有部分对外隐藏,同时减少编译依赖,解开使用接口和实现的耦合度。

3. Logger的实例化采用抽象Factory的设计模式:( 进一步学习http://blog.csdn.net/onejian/article/details/17484571  http://blog.csdn.net/onejian/article/details/17484565
/** * This class is used to create the default implementation of 
     * the Logger class */ 
    class LOG4CPLUS_EXPORT DefaultLoggerFactory : public spi::LoggerFactory {
    public:
        Logger makeNewLoggerInstance(const log4cplus::tstring& name, Hierarchy& h);
    };

  /** * Implement this interface to create new instances of Logger or 
* a sub-class of Logger.
*/
class LOG4CPLUS_EXPORT LoggerFactory {
public:
 /** * Creates a new <code>Logger</code> object. */ 
virtual Logger makeNewLoggerInstance(const log4cplus::tstring& name,
                                                 Hierarchy& h) = 0;
virtual ~LoggerFactory(){}
};
class Logger 
{
... //others

    virtual Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory);

}

因为只具有一个产品等级结构(即Logger),感觉使用Factory method设计模式也可以完成,但是失去了Reveal interface的效果。另外BaseFactory,AppenderFactory...本质上还是采用了抽象工厂的设计方式

4. 智能指针的设计(进步学习http://blog.csdn.net/onejian/article/details/17484153)

safe_auto_ptr类在std::auto_ptr的基础进行封装,对空指针异常进行了抛出处理。ShareObjectPtr模板类类似于Boost::shared_ptr模板类,采用引用计数方法,可以看到作者添加了access_mutex来保证了ShareObjectPtr线程安全,shared_ptr不能保证同时写线程安全。作者在头文件中也提到了,在设计此类的时候参考了More Effective C++。

// Note: Some of this code uses ideas from "More Effective C++" by Scott
// Myers, Addison Wesley Longmain, Inc., (c) 1996, Chapter 29, pp. 183-213
//

5. 借鉴log4cplus,实现了一个自己的logger,线程池,后续将贴上github上的地址

log4cplus是C++编写的开源的日志系统,功能非常全面,用到自己开发的工程中会比较专业的,:),本文介绍了log4cplus基本概念,以及如何安装,配置。 ### 简介 ### log4cplus是C++编写的开源的日志系统,前身是java编写的log4j系统.受Apache Software License保护。作者是Tad E. Smith。log4cplus具有线程安全、灵活、以及多粒度控制的特点,通过将信息划分优先级使其可以面向程序调试、运行、测试、和维护等全生命周 期; 你可以选择将信息输出到屏幕、文件、 NT event log、甚至是远程服务器;通过指定策略对日志进行定期备份等等。 ### 下载 ### 最新的log4cplus可以从以下网址下载 http://log4cplus.sourceforge.net本文使用的版本为:1.0.2 ### 安装 ### 1. linux下安装 tar xvzf log4cplus-x.x.x.tar.gz cd log4cplus-x.x.x ./configure --prefix=/where/to/install make make install 这里我采用缺省安装路径:/usr/local,下文如无特别说明,均以此路径为准。 2. windows下安装 不需要安装,有一个msvc6存放包括源代码和用例在内的开发工程(for VC6 only),使用之前请先编译 "log4cplus_dll class"工程生成dll,或者编译"log4cplus_static class"工程生成lib. ### 使用前的配置 ### 1. linux下的配置 确保你的Makefile中包含 /usr/local/lib/liblog4cplus.a(静态库)或 -llog4cplus(动态库)即可, 头文件在/usr/local/include/log4cplus目录下。对于动态库,要想正常使用,还得将库安装路径加入到 LD_LIBRARY_PATH 中,我一般是这样做的:以管理员身份登录,在/etc/ld.so.conf中加入安装路径,这里 是/usr/local/lib,然后执行ldconfig使设置生效即可。 2. windows下的配置 将"log4cplus_dll class"工程或"log4cplus_static class"工程的dsp 文件插入到你的工程中,或者直接 把两个工程编译生成的库以及头文件所在目录放到你的工程的搜索路径中,如果你使用静态库,请在你的工程中 "project/setting/C++"的preprocessor definitions中加入LOG4CPLUS_STATIC。 ### 构成要素介绍 ### 虽然功能强大,应该说log4cplus用起来还是比较复杂的,为了更好地使用它,先介绍一下它的基本要素。 Layouts :布局器,控制输出消息的格式. Appenders :挂接器,与布局器紧密配合,将特定格式的消息输出到所挂接的设备终端 (如屏幕,文件等等)。 Logger :记录器,保存并跟踪对象日志信息变更的实体,当你需要对一个对象进行 记录时,就需要生成一个logger。 Categories :分类器,层次化(hierarchy)的结构,用于对被记录信息的分类,层次中 每一个节点维护一个logger的所有信息。 Priorities :优先权,包括TRACE, DEBUG, INFO, WARNING, ERROR, FATAL。 本文介绍了log4cplus基本概念,以及如何安装,配置,下一篇将通过例子介绍如何使用log4cplus。 (二) 本文介绍了使用log4cplus有六个步骤,并提供了一些例子引导你了解log4cplus的基本使用。 ### 基本使用 ### 使用log4cplus有六个基本步骤: 1. 实例化一个appender对象 2. 实例化一个layout对象 3. 将layout对象绑定(attach)到appender对象 4. 实例化一个logger对象,调用静态函数:log4cplus::Logger::getInstance("logger_name") 5. 将appender对象绑定(attach)到logger对象,如省略此步骤,标准输出(屏幕)appender对象会绑定到logger 6. 设置logger的优先级,如省略此步骤,各种有限级的消息都将被记录 下面通过一些例子来了解log4cplus的基本使用。 〖例1〗 cpp 代码 /* 严格实现步骤1-6,appender输出到屏幕, 其中的布局格式和LogLevel后面会详细解释。*/ #include #include #include using namespace log4cplus; using namespace log4cplus::helpers; int main(){ /* step 1: Instantiate an appender object */ SharedObjectPtr _append (new ConsoleAppender()); _append->setName("append for test"); /* step 2: Instantiate a layout object */ std::string pattern = "%d{%m/%d/%y %H:%M:%S} - %m [%l]%n"; std::auto_ptr _layout(new PatternLayout(pattern)); /* step 3: Attach the layout object to the appender */ _append->setLayout( _layout ); /* step 4: Instantiate a logger object */ Logger _logger = Logger::getInstance("test"); /* step 5: Attach the appender object to the logger */ _logger.addAppender(_append); /* step 6: Set a priority for the logger */ _logger.setLogLevel(ALL_LOG_LEVEL); /* log activity */ LOG4CPLUS_DEBUG(_logger, "This is the FIRST log message...") sleep(1); LOG4CPLUS_WARN(_logger, "This is the SECOND log message...") return 0; } 输出结果: 10/14/04 09:06:24 - This is the FIRST log message... [main.cpp:31] 10/14/04 09:06:25 - This is the SECOND log message... [main.cpp:33] 〖例2〗 /* 简洁使用模式,appender输出到屏幕。 */ #include #include using namespace log4cplus; using namespace log4cplus::helpers; int main() { /* step 1: Instantiate an appender object */ SharedAppenderPtr _append(new ConsoleAppender()); _append->setName("append test"); /* step 4: Instantiate a logger object */ Logger _logger = Logger::getInstance("test"); /* step 5: Attach the appender object to the logger */ _logger.addAppender(_append); /* log activity */ LOG4CPLUS_DEBUG(_logger, "This is the FIRST log message...") sleep(1); LOG4CPLUS_WARN(_logger, "This is the SECOND log message...") return 0; } 输出结果: DEBUG - This is the FIRST log message... WARN - This is the SECOND log message... 〖例3〗 /* iostream模式,appender输出到屏幕。 */ #include #include #include /* 其实这个东东还是放到log4cplus头文件中比较合适些,个人意见:) */using namespace log4cplus; int main() { /* step 1: Instantiate an appender object */ SharedAppenderPtr _append(new ConsoleAppender()); _append->setName("append test"); /* step 4: Instantiate a logger object */ Logger _logger = Logger::getInstance("test"); /* step 5: Attach the appender object to the logger */ _logger.addAppender(_append); /* log activity */ LOG4CPLUS_TRACE(_logger, "This is" << " just a t" << "est." << std::endl) LOG4CPLUS_DEBUG(_logger, "This is a bool: " << true) LOG4CPLUS_INFO(_logger, "This is a char: " << 'x') LOG4CPLUS_WARN(_logger, "This is a int: " << 1000) LOG4CPLUS_ERROR(_logger, "This is a long(hex): " << std::hex << 100000000) LOG4CPLUS_FATAL(_logger, "This is a double: " << std::setprecision(15) << 1.2345234234) return 0; } 输出结果: DEBUG - This is a bool: 1 INFO - This is a char: x WARN - This is a int: 1000 ERROR - This is a long(hex): 5f5e100 FATAL - This is a double: 1.2345234234 〖例4〗 /* 调试模式,通过loglog来控制输出调试、警告或错误信息,appender输出到屏幕。 */ #include #include using namespace log4cplus::helpers; void printMsgs(void) { std::cout << "Entering printMsgs()..." << std::endl; LogLog::getLogLog()->debug("This is a Debug statement..."); LogLog::getLogLog()->warn("This is a Warning..."); LogLog::getLogLog()->error("This is a Error..."); std::cout << "Exiting printMsgs()..." << std::endl << std::endl; } int main() { /* LogLog类实现了debug, warn, error 函数用于输出调试、警告或错误信息, 同时提供了两个方法来进一步控制所输出的信息,其中: setInternalDebugging方法用来控制是否屏蔽输出信息中的调试信息,当输入 参数为false则屏蔽,缺省设置为false。 setQuietMode方法用来控制是否屏蔽所有输出信息,当输入参数为true则屏蔽, 缺省设置为false。 LogLog::getLogLog()->setInternalDebugging(false); */ printMsgs(); std::cout << "Turning on debug..." << std::endl; LogLog::getLogLog()->setInternalDebugging(true); printMsgs(); std::cout << "Turning on quiet mode..." << std::endl; LogLog::getLogLog()->setQuietMode(true); printMsgs(); return 0; } 输出结果: Entering printMsgs()... log4cplus:WARN This is a Warning... log4cplus:ERROR This is a Error... Exiting printMsgs()... Turning on debug... Entering printMsgs()... log4cplus: This is a Debug statement... log4cplus:WARN This is a Warning... log4cplus:ERROR This is a Error... Exiting printMsgs()... Turning on quiet mode... Entering printMsgs()... Exiting printMsgs()... 需要指出的是,输出信息中总是包含"log4cplus:"前缀,有时候会感觉不爽,这是因为LogLog在实现时候死定了要这么写: LogLog::LogLog() : mutex(LOG4CPLUS_MUTEX_CREATE), debugEnabled(false), quietMode(false), PREFIX( LOG4CPLUS_TEXT("log4cplus: ") ), WARN_PREFIX( LOG4CPLUS_TEXT("log4cplus:WARN ") ), ERR_PREFIX( LOG4CPLUS_TEXT("log4cplus:ERROR ") ) { } 你可以把这些前缀换成自己看着爽的提示符号,然后重新编译,hihi。除非万不得已或者实在郁闷的不行,否则还是不要这样干。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值