Log4cpp学习记录
1. 下载
http://log4cpp.sourceforge.net/
2. 编译(这一步一开始搞了比较久,后来搜到如下的信息帮助解决了)
问题:由于log4cpp-0.3.5rc3仅提供了vc6的工程文件,因此,使用vs2005打开后,需要进行转换。但是转换后,不能正确编译,提示Custom Build Step时出现了错误。
分 析:因为log4cpp在生成NTEventLogAppender.dll时,需要连接NTEventLogCategories.mc文件。所以,项 目设置了自定义的生成步骤去生成NTEventLogAppender.dll。但从vc6的工程文件转换时,这些步骤却没有正确的转换过来。从而出现上述问题。
解决方法:重新填写Custom Build Step项。
其中,CommandLine填写以下内容:
if not exist $(OutDir) md $(OutDir)
"mc.exe" -h $(OutDir) -r $(OutDir) $(ProjectDir)..\$(InputName).mc
"RC.exe" -r -fo $(OutDir)\$(InputName).res $(OutDir)\$(InputName).rc
"link.exe" /MACHINE:IX86 -dll -noentry-out:$(OutDir)\NTEventLogAppender.dll $(OutDir)\$(InputName).res
适用范围:log4cpp项目、log4cppDLL项目的Debug和Release配置。同时,该方法适用于vs2003(vc7.1)。
问题:log4cppDLL项目编译时会报8个连接错误,提示符号std::_Tree找不到
解决方案:
将include\log4cpp\FactoryParams.hh文件中的
const_iterator find(const std::string& t) const;
修改为
const_iterator find(const std::string& t) const {return storage_.find(t); }
后重新编译
问题:log4cppDLL项目编译时会报1个连接错误,提示符号log4cpp::localtime找不到
解决方案:
将src\localtime.cpp文件添加到项目中重新编译
3. 使用
http://www-128.ibm.com/developerworks/cn/linux/l-log4cpp/index.html
log4cpp应用手册
1 下载log4cpp并解压。
2 打开\log4cpp-0.3.4b\msvc6\msvc6.dsw
编译log4cpp工程Release版。
3 将编译后的log4cpp.lib复制到VC的Lib目录中。
4 将头文件的目录log4cpp-0.3.4b\include\log4cpp\
复制到VC的Include目录.
(或者添加log4cpp-0.3.4b\include到VC的Include环境变量)
6 目标工程包含库
log4cpp.lib ws2_32.lib
(要选择库连接方式相同的库)
5 包含头文件
日志记录
#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("Nowrun line %d", __LINE__);
或使用非根类别
log4cpp::Category::getInstance("MyCat").info("Nowrun 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的基本步骤如下:
- 实例化一个layout 对象;
- 初始化一个appender 对象;
- 把layout对象附着在appender对象上;
- 调用log4cpp::Category::getInstance("name"). 实例化一个category对象;
- 把appender对象附到category上(根据additivity的值取代其他appender或者附加在其他appender后)。
- 设置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)。这三种类型的组件一起工作使得开发员可以根据信息的类型和级别记录它们,并且在运行时控制这些信息的输出格式和位置。