log4cpp中小项目log记录

来源:互联网 发布:ediary电子日记本软件 编辑:程序博客网 时间:2024/06/05 09:46

下载链接:download

对于一个上点规模的C++项目而言,Log的作用是毋庸置疑的,出问题的时候,看了Log,常见的问题处理起来自是方便不过,即使遇到麻烦的问题,也可以从log总发现不少蛛丝马迹。因此一个严肃的项目应该从一开始就好好考虑如何打Log,便于分析、维护。

现实的情况却是很多项目都是从最初的数千行代码逐步庞大起来;开始的时候可能为了图方便,加log的方式大多是自己在iostream的基础上自己封装一下;等到项目扩大数十倍的时候,却发现这种方式很力不从心,Log文件凌乱复杂,难以管理。

现有的log工具,基本是分为两个阵营,经典的syslog和花哨强大的log4j,从而衍生出很多个变体。log4j基本已经成为复杂应用程序的log标准了,无奈C++的几个模仿者确各有千秋。我的情况是:
1>不需要复杂的配置,甚至不需要配置文件,但修改log消息格式又要很方便
2>支持自动备份功能
3>多线程安全
4>效率要尽量高
5>不要有其他依赖

log4cpp很轻易的满足了我的要求,只需要用已有的RollingFileAppender准备好后端,创建PatternLayout,一切就可以了;log级别的设置完全和syslog协议一样,很直观,打log地方,调用默认的Category管理器取得一个命名的Category,其他就是简单的调用了: log(), debug(), notice(), info(), notice()....

日志记录
#include <log4cpp/Category.hh>
日志配置读取
#include <log4cpp/PropertyConfigurator.hh>
NDC
#include <log4cpp/NDC.hh>

9 日志代码
每个类可以有自己的类别(log4cpp::Category),
可以在配置文件中添加该类别并设置日志级别。
所有的log4cpp::Category都使用同一个Appender
不同的Category配置为不同的日志级别,就可以控制日志输出的范围。
一般只使用四个记录日志级:DEBUG,INFO,WARN,ERROR
如:
log4cpp::Category::getRoot().info("Now run line %d", __LINE__);
或使用非根类别
log4cpp::Category::getInstance("MyCat").info("Now run line %d", __LINE__);

使用流:
log4cpp::Category::getInstance("main_cat").infoStream()
    << "This will show up as " 
    << 1 << " emergency message" 
    << log4cpp::CategoryStream::ENDLINE;
    
具体的函数说明见api文档.

7 读取配置代码
读取log配置文件,应在log4cpp静态成员初始化之后。
如在CXXXApp::InitInstance()中

    try
    {
        log4cpp::PropertyConfigurator::configure("log.ini");
    }
    catch (log4cpp::ConfigureFailure e)
    {
        log4cpp::Category::getRoot().warn(e.what());
    }
    

8 配置文件

[log4cpp]
# Set root category priority to DEBUG and its only appender to A1.  
# priority enum: "FATAL", "ALERT", "CRIT", "ERROR", "WARN",
#            "NOTICE", "INFO", "DEBUG", "NOTSET", "UNKNOWN" 
rootCategory=DEBUG,A1
additivity.rootCategory=false
                
# define appender
appender.A1=RollingFileAppender
#appender.A1.threshold=NOTSET
appender.A1.fileName=XXXX.log
#appender.A1.maxFileSize=10485760
#appender.A1.maxBackupIndex=1
appender.A1.layout=PatternLayout
appender.A1.layout.ConversionPattern=[%d{%Y-%m-%d %H:%M:%S}](%p)%c %x: %m%n

appender.Info_Cons=ConsoleAppender
appender.Info_Cons.threshold=INFO
appender.Info_Cons.layout=PatternLayout
appender.Info_Cons.layout.ConversionPattern=[%d{%Y-%m-%d %H:%M:%S}](%p)%c %x: %m%n

# category for sub1 
category.sub1=DEBUG,A1,Info_Cons
additivity.sub1=false
category.sub2=INFO,A1
additivity.sub1=false

# other categories

[others]
djkf=dksajf

 

 

最基本的使用方法;

手动使用log4cpp的基本步骤如下:

  1. 实例化一个layout 对象;
  2. 初始化一个appender 对象;
  3. 把layout对象附着在appender对象上;
  4. 调用log4cpp::Category::getInstance("name"). 实例化一个category对象;
  5. 把appender对象附到category上(根据additivity的值取代其他appender或者附加在其他appender后)。
  6. 设置category的优先级;
// FileName: test_log4cpp1.cpp
// Test log4cpp by manual operation.
// Announce: use as your own risk.
// Compile : g++ -otest1 -llog4cpp test_log4cpp1.cpp
// Run     : ./test1
// Tested  : RedHat 7.2 log4cpp0.3.4b
// Author  : liqun (liqun@nsfocus.com)
// Data    : 2003-6-27
#include       "log4cpp/Category.hh"
#include       "log4cpp/FileAppender.hh"
#include       "log4cpp/BasicLayout.hh"
int main(int argc, char* argv[])
{
        // 1实例化一个layout 对象
        log4cpp::Layout* layout = 
        new log4cpp::BasicLayout();
        // 2. 初始化一个appender 对象
        log4cpp::Appender* appender = new 
              log4cpp::FileAppender("FileAppender",
              "./test_log4cpp1.log");
        // 3. 把layout对象附着在appender对象上
        appender->setLayout(layout);
        // 4. 实例化一个category对象
        log4cpp::Category& warn_log = 
        log4cpp::Category::getInstance("mywarn");
        // 5. 设置additivity为false,替换已有的appender
        warn_log.setAdditivity(false);
        // 5. 把appender对象附到category上
        warn_log.setAppender(appender);
        // 6. 设置category的优先级,低于此优先级的日志不被记录
        warn_log.setPriority(log4cpp::Priority::WARN);
        // 记录一些日志
        warn_log.info("Program info which cannot be wirten");
        warn_log.debug("This debug message will fail to write");
        warn_log.alert("Alert info");
        // 其他记录日志方式
        warn_log.log(log4cpp::Priority::WARN, "This will be a logged warning");
        log4cpp::Priority::PriorityLevel priority;
        bool this_is_critical = true;
        if(this_is_critical)
               priority = log4cpp::Priority::CRIT;
        else
               priority = log4cpp::Priority::DEBUG;
        warn_log.log(priority,"Importance depends on context");
        
        warn_log.critStream() << "This will show up << as " 
        << 1 << " critical message" 
        << log4cpp::CategoryStream::ENDLINE;
        // clean up and flush all appenders
        log4cpp::Category::shutdown();
        return 0;
}

 

从以上例子,并结合文档,可以看出,实际上,其Log是log4cpp::Category::的一部分,而这些Category可以绑定不同的appender,以使得log输出到不同的出口,如文件或终端或网络等。实际记录的时候是靠优先级来实现的,即优先级低于目前的log所设定的优先级,则不需要记录此信息,只有高于当前优先级的log信息才会被记录。对于Category的层次,log4cpp::Category::getRoot()为最高层次,其它getInstance(“name”)得到的只有命名为”name”的Category,应该是Root()的子层。

Log4cpp的优势

1,提供应用程序运行上下文,方便跟踪调试.这对开发人员很有帮助,特别是调试的时候,这一点log均可实现.

2,把记录的日志输送到多种方式上.包括命令行,控制台(调试的时候马上就能看到哪里有问题),文件(把完整的日志信息保存起来,以利于整个系统的维护,统计),回卷文件、内存等.这一点是有特色的地方,因为其只有一个输出内容,但可绑定到多个输出源,比如,你可以用控制台输出看到即时结果的同时,将输出的内容存到文件中。或者你为了在测试的时候尽量不影响性能,可以将日志输出到内存,待关闭程序的时候再将其写回到硬盘。

3,可以动态控制日志记录级别,在效率和功能中进行调整.当执行等级小于设定等级时就不输出.其设定了INFO,DEBUG,ALERT,EMERGE等不同的级别,当当前Log的级别低于设定的需记录的级别时,将忽略此信息,这个对记录不同程度的信息详细度有帮助,可以专注于特定的重要级别的错误的调试。

4,所有配置可以通过配置文件进行动态调整.这个暂时还没有使用,若要使用可参见 《便利的开发工具-log4cpp快速使用指南》(http://www.ibm.com/developerworks/cn/linux/l-log4cpp/index.html)

中第三节

5,现在log4**系列已经开始支持其他语言了.如Java(log4j),C++(log4cpp、log4cplus),C(log4c),python(log4p)等.好的东西容易被人借鉴和传播.

Log4cpp有三个主要的组件:日志类别(Category)、输出源( Appenders)和布局(Layouts)。这三种类型的组件一起工作使得开发员可以根据信息的类型和级别记录它们,并且在运行时控制这些信息的输出格式和位置。

以上。

0 0
原创粉丝点击