-
log4..简介
log4..是基于log4j的一系列的c++移植版本,使用了log4j的模式结构,目前主要有以下几个版本:
1. log4cxx, 目前是到0.10.0版,Apache下的孵化项目,不能独立编译,依赖于APR,编译比较麻烦,2008年以后就没再更新
2. log4cplus,目前最新版本是1.2.0,最近一次更新2016-01-16,不依赖于第三方库,下载位置https://sourceforge.net/projects/log4cplus/files/log4cplus-stable/1.2.0/
3. log4cpp,目前最新版本1.1.2,最近一次更新2016年-08-02,也不依赖与第三方库,与log4cplus功能类似,但是简化了一些实现,增加了一些功能,下载位置https://sourceforge.net/projects/log4cpp/files/?source=navbar因为基本结构大致类似,性能上相比也没有明显差别,下面就选择log4cpp进行介绍
log4cpp基本结构
log4cpp从大的结构上分为日志类别(Category),日志追加器(Appender),日志布局(Layout),日志级别(Priority)。除此以外还提供了一些帮助类,简化我们对日志的代码设置。
1、Category,日志输出主体类,提供了输出各种日志级别的方法,并且能够设置类别优先级,低于此优先级的类都不再输出,可以有多个分类,但每个应用程序都有一个root分类,其他分类都是root分类的子分类,有点类似于java的单继承结构,子分类的输出同时会输出到父分类中。
// 根分类root log4cpp::Category& root = log4cpp::Category::getRoot(); // 子分类subCat1 log4cpp::Category& sub1 = log4cpp::Category::getInstance("sub1"); root.error("test root error"); root.warn("test root error"); root.info("test root error"); sub1.fatal("test sub1 error"); sub1.notice("test sub1 error"); sub1.debug("test sub1 error");
2、Appender,主要是用来确定日志输出行为,例如输出到哪儿,如何输出。类Appender是由Category来加载的,一个Category可以加载多个Appender,输出到多个地方,一个Appender也可以被多个Category加载,但是有些Appender类没有设置互斥,日志的多线程支持主要是在Category里做的处理,因此不要使用一个Appender加载到多个Category中。
// OstreamAppender:输出到输出流中(输出到控制台上) // FileAppender:输出到文件中 // RollingFileAppender:输出到文件中并且能够设置文件最大超过多少时生成新文件 // DailyRollingFileAppender:每天生成一个新文件 // NTEventLogAppender:将日志输出到Windows事件日志中去 // ... log4cpp::Appender *appender = new log4cpp::FileAppender("test", "D:/log4cppTest/log4cppTest.log"); root.addAppender(appender);
3、Layout,设置日志输出风格,有BasicLayout、SimpleLayout、PatternLayout,其中BasicLayout,SimpleLayout主要是提供的成型的简单日志风格,实际中基本不会使用,主要是使用PatternLayout对日志做格式输出,Layout是加载到Appender中去的。
// %% 输出一个% // %c 输出Categroy名称 // %d 输出日期 // %m 输出消息 // %n 输出换行 // %p 输出Priority // %d{%Y-%m-%d %H:%M:%S:%l}对输出日期做定制,年月日时分秒毫秒 // %t 线程ID log4cpp::PatternLayout *patternLayout = new log4cpp::PatternLayout(); patternLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S.%l} %t [%p] %m %n"); appender->setLayout(patternLayout);
4、Priority,log4cpp有如下几级日志级别
typedef enum { EMERG = 0, // emergency FATAL = 0, // fatal ALERT = 100, // alert CRIT = 200, // critical ERROR = 300, // error WARN = 400, // wanning NOTICE = 500, // notice INFO = 600, // infomation DEBUG = 700, // debug NOTSET = 800 } PriorityLevel;
其中每个Category都有一个level,低于此高于此level的日志将不会输出,比如Category设置priority为ERROR则,使用此Category输出的WARN,NOTICE等级别的日志都不会输出, 当Category的Priority设置为NOTSET时,该Categroy继承父Category的Priority;每个Appender也可以设置其threshold,当输出日志的Priority的值大于threshold时,此Appender将不会输出此条日志
// 代码设置 root.setPriority(log4cpp::Priority::DEBUG); appender->setThreshold()
1、帮助类, log4cpp主要提供如下几个类来简化代码设置:SimpleConfigurator,BasicConfigurator,PropertyConfigurator,其中SimpleConfigurator和BasicConfigurator,主要是使用代码的方式,进行了一些简单的默认配置,而PropertyConfigurator,是通过配置文件的方式对日志进行配置,也是最常用的,下面就是配置文件的格式:
#文件名为logTest.Property #配置root Category的Priority为DEBUG, Appender为rootAppender log4cpp.rootCategory=DEBUG, rootAppender #配置子Category sub1的Priority为DEBUG, Appender为A1 log4cpp.category.sub1=DEBUG, A1 #配置rootAppender为FileAppender log4cpp.appender.rootAppender=FileAppender #配置日志文件名为test1.log,存放在D盘根目录下 log4cpp.appender.rootAppender.fileName=D:/test1.log #配置layout为PatternLayout log4cpp.appender.rootAppender.layout=PatternLayout #设置日志输出风格 log4cpp.appender.rootAppender.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S.%l} %t [%p] %m %n #配置A1为RollingFileAppender log4cpp.appender.A1=RollingFileAppender #配置日志文件名为test2.log,存放在D盘根目录下 log4cpp.appender.A1.fileName=D:/test2.log #配置日志文件最大不能超过1M log4cpp.appender.A1.maxFileSize=1024 * 1024 #日志文件最多存储3个文件,超过就会删除旧的 log4cpp.appender.A1.maxBackupIndex=2 #设置日志风格 log4cpp.appender.A1.layout=PatternLayout log4cpp.appender.A1.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S.%l} %t [%p] %m %n // 代码设置配置文件 log4cpp::PropertyConfigurator::configure(logTest.Property);
代码使用
windows环境下
获取到源代码后,找到源码目录中的msvc10目录,使用VS2010打开msvc10.sln解决方案文件,编译源码获得log4cpp.DLL和log4cpp.lib;在源码目录中有include文件夹,将include整个拷贝到我们的工程目录下,将include添加到工程属性中的附加包含目录中(QT工程则添加到INCLUDEPATH中去),这时就能够正常使用了。
linux环境下
1.下载log4cpp-1.1.1.tar.gz
2. 安装:先将log4cpp-1.1.1.tar.gz拖入用户主目录(~),
然后再执行以下步骤:
$ tar zxvf log4cpp-1.1.1.tar.gz
$ cd ~/log4cpp/
$ ./configure
$ make
$ make check
$ sudo make install
这里已经安装成功.
默认lib库路径是 : /usr/local/lib/
默认头文件的位置: /usr/local/include/log4cpp
3. 使用:
3.1 编译使用log4cpp库的CPP文件时,要加上库文件,才能顺利的编译通过,如下示例
$ g++ log4test.cpp -llog4cpp -lpthread
3.2 运行时,如若提示缺少log4cpp库文件,表示找不到log4cpp的动态库,需要进行以下设置
以管理员身份登录终端,然后执行以下操作:
a. $ sudo vim /etc/ld.so.conf
b. 在打开的文件末尾另起一行添加动态库log4cpp的路径(这里是/usr/local/lib),然后保存退出;
执行命令ldconfig使设置生效即可。
c. $ sudo ldconfig //更新库文件的缓存信息
测试用例
#include <stdio.h> #include <time.h> #include <iostream> #include <boost/circular_buffer.hpp> #include <thread> #include <mutex> #include <vector> #include <stdio.h> #include <log4cpp/Category.hh> #include <log4cpp/FileAppender.hh> #include <log4cpp/SimpleLayout.hh> #include "log4cpp/PropertyConfigurator.hh" using namespace std; std::mutex g_mutex; // protects g_i // 1. circular_buffer 在多线程下是否需要加锁 // ---- thread1 write // ---- thread2 read // ---- thread3 write boost::circular_buffer<int> cb(3); void thread1_foo() { int i = 0; while(i++ < 1000) { cb.push_back(i); { lock_guard<std::mutex> lock(g_mutex); cout << "thread1 write: " << i << endl; } } } void log_test() { try { log4cpp::PropertyConfigurator::configure("./log4cpp.conf"); } catch (log4cpp::ConfigureFailure& f) { std::cout << "Configure Problem " << f.what() << std::endl; } log4cpp::Category& root = log4cpp::Category::getRoot(); log4cpp::Category& sub3 = log4cpp::Category::getInstance(std::string("sub3")); for(int i = 0; i < 100; i++) { sub3.fatal("some test"); } } void thread2_foo() { int i = 0; while(i++ < 2000) { if(cb.empty()) { continue; } int a = cb[0]; cb.pop_front(); { lock_guard<std::mutex> lock(g_mutex); cout<< "thread2 read : "<< a << endl; } } } #define LOGFILE "./test.log" int main() { /*Setting up Appender, layout and Category*/ // log4cpp::Appender *appender = new log4cpp::FileAppender("FileAppender",LOGFILE);//第一个参数是appender的名字,第二个是log文件的名字 // log4cpp::Layout *layout = new log4cpp::SimpleLayout(); // //log4cpp::Layout *layout = new log4cpp::BasicLayout(); // log4cpp::Category& category = log4cpp::Category::getInstance("abc"); // // appender->setLayout(layout); // category.setAppender(appender); // category.setPriority(log4cpp::Priority::INFO); // // /*The actual logging*/ // category.info("This is for tracing the flow"); // category.notice("This is to notify certain events"); // category.warn("This is to generate certain warnings"); log_test(); return 0; }
g++ -std=c++11 -I/usr/local/include -I/users/jiangxf/3rdParty/boost -o log_test log_test.cpp liblog4cpp.a
# 定义了3个category sub1, sub2, sub3 # 其中sub2和sub3设置了additivity属性为false;sub1的additivity属性默认为true rootCategory=DEBUG, rootAppender category.sub1=,A1 category.sub2=INFO, A2 additivity.sub2=false category.sub3=ERROR, A3 additivity.sub3=false # 定义rootAppender类型和layout属性,这里使用了BasicLayout appender.rootAppender=org.apache.log4cpp.ConsoleAppender appender.rootAppender.layout=org.apache.log4cpp.BasicLayout #定义A1的属性, 这里使用了 SimpleLayout appender.A1=org.apache.log4cpp.FileAppender appender.A1.fileName=./log/A1.log appender.A1.layout=org.apache.log4cpp.SimpleLayout #定义A2的属性,这里使用了 PatternLayout appender.A2=org.apache.log4cpp.ConsoleAppender appender.A2.layout=org.apache.log4cpp.PatternLayout appender.A2.layout.ConversionPattern=The message ‘%m‘ at time %d%n #定义A3的属性 #appender.A3=org.apache.log4cpp.RollingFileAppender appender.A3=org.apache.log4cpp.ConsoleAppender appender.A3.fileName=./log/A3.log appender.A3.maxFileSize=50 appender.A3.maxBackupIndex=3 appender.A3.backupPattern=%Y-%m-%d appender.A3.layout=org.apache.log4cpp.PatternLayout #appender.A3.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} [%p]: [%c] %m%n appender.A3.layout.ConversionPattern=%d,%p,%m%n #%c sub3 #%p fatal #%m 日志内容 #%n 回车换行
log4cpp学习
http://blog.csdn.net/liuhong135541/article/category/1496383
原文地址:https://www.cnblogs.com/cthon/p/9192787.html