开源C++类库,提供了C++程序中使用日志和跟踪调试的功能

  1. 提供应用程序运行上下文,方便跟踪调试
  2. 可扩展的、多种方式记录日志,包括命令行、文件、回卷文件、内存、syslog服务器、Win事件日志等
  3. 可动态控制日志记录级别,在效率和功能中进行调整
  4. 所有配置可以通过配置文件进行动态调整
  5. 多语言支持,包括Java(log4j)、C++(log4cpp、log4cplus)、C(log4c)、python(log4p)等

相关链接

  1. log4cpp官网
  2. log4cpp源码地址
  3. log4cpp使用手册
  4. log4cpp快速使用
  5. log4cpp详细介绍

三个组件

Log4cpp有三个主要的组件:类别(Category)、附加目的地(Appender,即输出源)、布局(Layout)。

类别 职责 说明
Category 负责向日志写入信息
1. 系统中可以有多个Category,它们都是继承自同一个根,每个Category负责记录自己的日志
1. 每个Category可以添加多个Appender
1. 当Category记录一条日志时,该日志被写入所有附加到此Category的Appender
Appender 负责指定日志的输出地点
1. 每个Appender指定一个日志的目的地,例如文件、字符流或者Windows日志
1. 每个Append都包含一个Layout,该Layout定义了这个Appender上的日志格式
Layout 负责设定日志的格式

类别(Category)

【说明】每个Category都有一个优先级,该优先级可以由setPriority方法设置,或者从其父的Category中继承而来。
【优先级】如果日志优先级高于Category的优先级,该日志被记录,否则被忽略。
日志优先级:DEBUG < INFO < WARN < ERROR < FATAL

  1. 如果配置文件中设置的级别是DEBUG,则任意的log都能打印出来
  2. 如果配置的级别是ERROR,则只有高于ERROR优先级的日志才可以打印出来
    1. typedefenum {
    2. EMERG = 0,
    3. FATAL = 0,
    4. ALERT = 100,
    5. CRIT = 200,
    6. ERROR = 300,
    7. WARN = 400,
    8. NOTICE =500,
    9. INFO = 600,
    10. DEBUG = 700,
    11. NOTSET = 800
    12. }PriorityLevel;
    【补充】Log4cpp中有一个总是可用并实例化好的Category,即根Category。使用log4cpp::Category::getRoot()可以得到根Category。在大多数情况下,一个应用程序只需要一个日志种类(Category),但是有时也会用到多个Category,此时可以使用根Category的getInstance方法来得到子Category。不同的子Category用于不同的场合
    【例子】这个例子中共有三个Category,分别是根、sub1和sub2,其中sub1记录了一条日志,sub2记录了两条日志。Sub2另外两个日志由于优先级不够未能记录。 ```cpp log4cpp::OstreamAppender*osAppender1 = new log4cpp::OstreamAppender(“osAppender1”,&cout); osAppender1->setLayout(newlog4cpp::BasicLayout());

log4cpp::OstreamAppender*osAppender2 = new log4cpp::OstreamAppender(“osAppender2”,&cout); osAppender2->setLayout(newlog4cpp::BasicLayout());

log4cpp::Category& root =log4cpp::Category::getRoot(); root.setPriority(log4cpp::Priority::DEBUG);

log4cpp::Category& sub1 =root.getInstance(“sub1”); sub1.addAppender(osAppender1); sub1.setPriority(log4cpp::Priority::DEBUG);

sub1.error(“suberror”);

log4cpp::Category& sub2 =root.getInstance(“sub2”); sub2.addAppender(osAppender2); sub2.setPriority(101);

sub2.warn(“sub2warning”); sub2.fatal(“sub2fatal”); sub2.alert(“sub2alert”); sub2.crit(“sub2crit”);

log4cpp::Category::shutdown();

  1. <a name="0Aact"></a>
  2. ## 输出源(Appender)
  3. 输出源用来输出日志(被layout格式化后)到一些设备上,比如文件、命令行、内存等。也可以自定义appender,以输出到别的设备上。<br />log4cpp中可以直接使用的Appender列表如下:
  4. | **类别** | **职责** |
  5. | --- | --- |
  6. | log4cpp::IdsaAppender | 发送到Idsa服务 |
  7. | log4cpp::FileAppender | 输出到文件 |
  8. | log4cpp::RollingFileAppender | 输出到回卷文件,即当文件到达某个大小后回卷 |
  9. | log4cpp::OstreamAppender | 输出到一个ostream类 |
  10. | log4cpp::RemoteSyslogAppender | 输出到远程syslog服务器。需要与Syslog配合使用 |
  11. | log4cpp::StringQueueAppender | 内存队列 |
  12. | log4cpp::SyslogAppender | 本地syslog。需要与Syslog配合使用 |
  13. | log4cpp::Win32DebugAppender | 发送到缺省系统调试器 |
  14. | log4cpp::NTEventLogAppender | 发送到win事件日志 |
  15. 补充:Syslog是类Unix系统的一个核心服务,用来提供日志服务,在Windows系统中并没有直接提供支持,当然可以用相关工具()提供Windows系统中的syslog服务。
  16. <a name="jy2La"></a>
  17. ### OstreamAppender
  18. 【功能】将日志记录成一个流,如果该流恰好是cout,则会在标准控制台上输出。比printf优越的是,除了输出消息外,还可以轻松的输出时间、时钟数、优先级等大量有用信息。<br />【使用】
  19. ```cpp
  20. log4cpp::OstreamAppender* osAppender = newlog4cpp::OstreamAppender("osAppender", &cout);
  21. //第一个参数指定OstreamAppender的名称
  22. //第二个参数指定它关联的流的指针。

StringQueueAppender

【背景】“在调试多线程程序时,不能随意使用printf”。因为printf导致IO中断,会使得本线程挂起,其花费的时间比一条普通指令多数千倍。若多个线程同时运行,则严重干扰了线程间的运行方式。
【功能】将日志记录到一个字符串队列中,该字符串队列使用了STL中的两个容器,即字符串容器std::string和队列容器std::queue
【原理】

  1. std::queue<std::string> _queue;
  2. //_queue变量是StringQueueAppender类中用于具体存储日志的内存队列
  3. //StringQueueAppender的使用方法与OstreamAppender类似
  4. //数只接收一个参数“名称”,记录完成后需要程序员自己从队列中取出每条日志

【示例】

  1. og4cpp::StringQueueAppender* strQAppender = newlog4cpp::StringQueueAppender("strQAppender");
  2. strQAppender->setLayout(newlog4cpp::BasicLayout());
  3. log4cpp::Category& root =log4cpp::Category::getRoot();
  4. root.addAppender(strQAppender);
  5. root.setPriority(log4cpp::Priority::DEBUG);
  6. root.error("Hello log4cpp in a Error Message!");
  7. root.warn("Hello log4cpp in a WarningMessage!");
  8. cout<<"Get message from MemoryQueue!"<<endl;
  9. cout<<"-------------------------------------------"<<endl;
  10. queue<string>& myStrQ =strQAppender->getQueue();
  11. while(!myStrQ.empty())
  12. {
  13. cout<<myStrQ.front();
  14. myStrQ.pop();
  15. }
  16. log4cpp::Category::shutdown();

FileAppender和RollingFileAppender

【说明】FileAppender和RollingFileAppender是log4cpp中最常用的两个Appender,其功能是将日志写入文件中。
【两者的区别】它们之间唯一的区别就是前者会一直在文件中记录日志(直到操作系统承受不了为止),而后者会在文件长度到达指定值时循环记录日志,文件长度不会超过指定值(默认的指定值是10M byte)。

  1. //FileAppender创建函数
  2. FileAppender(const std::string& name, //名称
  3. const std::string& fileName, //日志文件名
  4. bool append = true, //是否在日志文件后继续记入日志,还是清空原日志文件再记录
  5. mode_tmode = 00644); //文件的打开方式
  6. //RollingFileAppender的创建函数
  7. RollingFileAppender(const std::string&name,
  8. const std::string&fileName,
  9. size_t maxFileSize =10*1024*1024, //回滚文件的最大值
  10. unsigned intmaxBackupIndex = 1, //回滚文件所用的备份文件的最大个数
  11. boolappend = true,
  12. mode_t mode =00644);

【补充】

  1. 所谓备份文件,是用来保存回滚文件中因为空间不足未能记录的日志,备份文件的大小仅比回滚文件的最大值大1kb。所以如果maxBackupIndex取值为3,则回滚文件(假设其名称是rollwxb.log,大小为100kb)会有三个备份文件,其名称分别是rollwxb.log.1,rollwxb.log.2和rollwxb.log.3,大小为101kb。
  2. 如果maxBackupIndex取值为0或者小于0,则回滚文件功能会失效,其表现如同FileAppender一样,不会有大小的限制。这也许是一个bug。

【示例】程序运行后会产生两个日志文件wxb.log和rollwxb.log,以及一个备份文件rollwxb.log.1。wxb.log的大小为7kb,记录了所有100条日志;rollwxb.log大小为2kb,记录了最新的22条日志;rollwxb.log.1大小为6kb,记录了旧的78条日志。

  1. log4cpp::PatternLayout* pLayout1 = newlog4cpp::PatternLayout();
  2. pLayout1->setConversionPattern("%d: %p %c%x: %m%n");
  3. log4cpp::PatternLayout* pLayout2 = newlog4cpp::PatternLayout();
  4. pLayout2->setConversionPattern("%d: %p %c%x: %m%n");
  5. log4cpp::Appender* fileAppender = newlog4cpp::FileAppender("fileAppender","wxb.log");
  6. fileAppender->setLayout(pLayout1);
  7. log4cpp::RollingFileAppender* rollfileAppender = newlog4cpp::RollingFileAppender( "rollfileAppender","rollwxb.log",5*1024,1);
  8. rollfileAppender->setLayout(pLayout2);
  9. log4cpp::Category& root =log4cpp::Category::getRoot().getInstance("RootName");
  10. root.addAppender(fileAppender);
  11. root.addAppender(rollfileAppender);
  12. root.setPriority(log4cpp::Priority::DEBUG);
  13. for (int i = 0; i < 100; i++)
  14. {
  15. string strError;
  16. ostringstream oss;
  17. oss<<i<<":RootError Message!";
  18. strError = oss.str();
  19. root.error(strError);
  20. }
  21. log4cpp::Category::shutdown();

Win32DebugAppender

【功能】Win32DebugAppender是一个用于调试的Appender,其功能是向Windows的调试器中写入日志,目前支持MSVC和Borland中的调试器

  1. log4cpp::PatternLayout* pLayout1 = newlog4cpp::PatternLayout();
  2. pLayout1->setConversionPattern("%d: %p %c%x: %m%n");
  3. log4cpp::Appender* debugAppender = newlog4cpp::Win32DebugAppender("debugAppender");
  4. debugAppender->setLayout(pLayout1);
  5. log4cpp::Category& root =log4cpp::Category::getRoot().getInstance("RootName");
  6. root.addAppender(debugAppender);
  7. root.setPriority(log4cpp::Priority::DEBUG);
  8. root.error("Root Error Message!");
  9. root.warn("Root Warning Message!");
  10. log4cpp::Category::shutdown();

NTEventLogAppender

【功能】该Appender可以将日志发送到windows的日志,在运行程序后可以打开windows的计算机管理->系统工具->事件查看器->应用程序

  1. log4cpp::PatternLayout* pLayout1 = newlog4cpp::PatternLayout();
  2. pLayout1->setConversionPattern("%d: %p %c%x: %m%n");
  3. log4cpp::Appender* ntAppender = newlog4cpp::NTEventLogAppender("debugAppender","wxb_ntlog");
  4. ntAppender->setLayout(pLayout1);
  5. log4cpp::Category& root =log4cpp::Category::getRoot().getInstance("RootName");
  6. root.addAppender(ntAppender);
  7. root.setPriority(log4cpp::Priority::DEBUG);
  8. root.error("Root Error Message!");
  9. root.warn("Root Warning Message!");
  10. log4cpp::Category::shutdown();

布局(Layout)

【介绍】布局用来显示样式,表示让用户根据类似于C语言printf函数的转换模式来输出格式。
【Layout类】Layout本身是一个虚类,共有三个子类

类别 说明 例子
BasicLayout
1. 以“时间戳”为优先级
1. NDC标签:日志信息
1248337987 ERROR: ..
PatternLayout
1. 让用户根据类似于printf方式输出
1. 如果不选择扩展Layout,建议使用PatternLayout,从而达到理想的输出格式
2009-07-24 15:59:55,703:INFO
SimpleLayout
1. 以“日志信息”为优先级

PatternLayout

PatternLayout使用setConversionPattern函数来设置日志的输出格式。该函数的声明如下:

  1. void log4cpp::PatternLayout::setConversionPattern(const std::string& conversionPattern)
  2. throw (ConfigureFailure) [virtual]

参数const std::string& conversionPattern用格式化字符串来描述格式,如%c、%d、%p等,具体说明请见下文“ConversionPattern的参数含义”。

总结

这三种类型的组件一起工作使得系统可以根据信息的类型和级别记录它们,并且在运行时控制这些信息的输出格式和位置。
三者关系:

  1. Category和Appender的关系是:多个Appender可以附加到一个Category上,这样一个日志消息可以同时输出到多个设备上
  2. Appender和Layout的关系是:Layout附加在Appender上,appender调用layout处理完日志消息后,记录到某个设备上。

    相关概念

    除了三个组件,还有以下概念:Priority优先级,NDC嵌套的诊断上下文(nested diagnostic contexts)

  3. 「Priority」:被用来指定Category的优先级和日志的优先级

  4. 「NDC」:用来区分不同场景中交替出现的日志的手段

    NDC

    【NDC介绍】NDC是nested DiagnosticContext的缩写,意思是“嵌套的诊断上下文”。NDC是一种用来区分不同源代码中交替出现的日志的手段
    【背景】当一个服务端程序同时记录好几个并行客户时,输出的日志会混杂在一起难以区分。但如果不同上下文的日志入口拥有一个特定的标识,则可以解决这个问题。NDC就是在这种情况下发挥作用。注意NDC是以线程为基础的,每个线程拥有一个NDC,每个NDC的操作仅对执行该操作的线程有效。
    【使用】NDC的几个有用的方法是:push、pop、get和clear。注意它们都是静态函数

  5. Push可以让当前线程进入一个NDC,如果该NDC不存在,则根据push的参数创建一个NDC并进入;如果再调用一次push,则进入子NDC;

  6. Pop可以让当前线程从上一级NDC中退出,但是一次只能退出一级。
  7. Clear可以让当前线程从所有嵌套的NDC中退出。
  8. Get可以得到当前NDC的名字,如果有嵌套,则不同级别之间的名字用空格隔开

【例子】在记录日志的时候,可以从NDC中得知当前线程的嵌套关系。

  1. std::cout<< "1.empty NDC: " <<NDC::get()<< std::endl;
  2. NDC::push("context1");
  3. std::cout<< "2.push context1: " <<NDC::get()<< std::endl;
  4. NDC::push("context2");
  5. std::cout<< "3.push context2: " <<NDC::get()<< std::endl;
  6. NDC::push("context3");
  7. std::cout<< "4.push context3: " <<NDC::get()<< std::endl;
  8. std::cout<< "5.get depth: " <<NDC::getDepth() <<std::endl;
  9. std::cout<< "6.pop: " << NDC::pop()<< std::endl;
  10. std::cout<< "7.after pop:"<<NDC::get()<<std::endl;
  11. NDC::clear();
  12. std::cout<< "8.clear: " << NDC::get() <<std::endl;

配置文件

log4cpp支持从一个配置文件中读取Category、Appender和Layout的优先级和相互附属关系。
【例子】

  1. log4cpp.conf ```cpp

    log4cpp配置文件

    定义Root category的属性

    log4cpp.rootCategory=DEBUG, RootLog

定义RootLog属性

log4cpp.appender.RootLog=ConsoleAppender log4cpp.appender.RootLog.layout=PatternLayout log4cpp.appender.RootLog.layout.ConversionPattern=%d [%p] -%m%n

定义sample category的属性

log4cpp.category.sample=DEBUG, sample

定义sample属性

log4cpp.appender.sample=FileAppender log4cpp.appender.sample.fileName=sample.log log4cpp.appender.sample.layout=PatternLayout log4cpp.appender.sample.layout.ConversionPattern=%d [%p] -%m%n

定义sample.soncategory的属性

log4cpp.category.sample.son=DEBUG, son

定义son的属性

log4cpp.appender.son=FileAppender log4cpp.appender.son.fileName=son.log log4cpp.appender.son.layout=PatternLayout log4cpp.appender.son.layout.ConversionPattern=%d[%p] - %m%n

定义sample.daughtercategory的属性

log4cpp.category.sample.daughter=DEBUG,daughter

定义daughter属性

log4cpp.appender.daughter=FileAppender log4cpp.appender.daughter.fileName=daughter.log log4cpp.appender.daughter.layout=PatternLayout log4cpp.appender.daughter.layout.ConversionPattern=%d [%p]- %m%n

  1. 2. log4cpp_test.cpp
  2. ```cpp
  3. #include<iostream>
  4. #include<log4cpp/Category.hh>
  5. #include<log4cpp/PropertyConfigurator.hh>
  6. int main(int argc,char* argv[])
  7. {
  8. try
  9. {
  10. log4cpp::PropertyConfigurator::configure("./log4cpp.conf");
  11. }
  12. catch(log4cpp::ConfigureFailure& f)
  13. {
  14. std::cout<< "Configure Problem "<< f.what()<< std::endl;
  15. return -1;
  16. }
  17. log4cpp::Category& root =log4cpp::Category::getRoot();
  18. log4cpp::Category& sub1 =log4cpp::Category::getInstance(std::string("sub1"));
  19. log4cpp::Category& sub3 =log4cpp::Category::getInstance(std::string("sub1.sub2"));
  20. sub1.info("This is someinfo");
  21. sub1.alert("Awarning");
  22. // sub3 only have A2 appender.
  23. sub3.debug("This debug messagewill fail to write");
  24. sub3.alert("All hands abandonship");
  25. sub3.critStream() <<"This will show up<< as "<< 1 <<" critical message"<<log4cpp::CategoryStream::ENDLINE;
  26. sub3<<log4cpp::Priority::ERROR<<"And this will be anerror" <<log4cpp::CategoryStream::ENDLINE;
  27. sub3.log(log4cpp::Priority::WARN, "This will be a logged warning");
  28. return0;
  29. }

【配置文件使用总结】

  1. category 是”log4cpp.category.” + “categoryname”
  2. category 名字可以用”.”分隔,以标识包含关系
  3. appender 是”log4cpp.appender.” + “appendername”
  4. appender 名字 不能用 “.” 分隔,即是说 appender 是没有包含关系的

    快速使用

    下载

  5. 方式一:资源链接

  6. 方式二:官网

    编译安装(windows)

  7. 下载cmake(下载地址

  8. 解压压缩包,进入目录,创建build目录,运行cmake ```bash C:\Users\geodoer>cmake —version cmake version 3.17.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).

C:\Users\geodoer>d:

D:>cd D:\Cpp3D\3Log\log4cpp

D:\Cpp3D\3Log\log4cpp>mkdir build

D:\Cpp3D\3Log\log4cpp>cd build

D:\Cpp3D\3Log\log4cpp\build>cmake ../ — Building for: Visual Studio 15 2017 — Selecting Windows SDK version 10.0.17763.0 to target Windows 10.0.18363. — The C compiler identification is MSVC 19.16.27038.0 — The CXX compiler identification is MSVC 19.16.27038.0 — Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe — Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe - works — Detecting C compiler ABI info — Detecting C compiler ABI info - done — Detecting C compile features — Detecting C compile features - done — Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe — Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe - works — Detecting CXX compiler ABI info — Detecting CXX compiler ABI info - done — Detecting CXX compile features — Detecting CXX compile features - done CMake Warning (dev) in CMakeLists.txt: No cmake_minimum_required command is present. A line of code such as

  1. cmake_minimum_required(VERSION 3.17)

should be added at the top of the file. The version specified may be lower if you wish to support older CMake versions for this project. For more information run “cmake —help-policy CMP0000”. This warning is for project developers. Use -Wno-dev to suppress it.

— Configuring done — Generating done — Build files have been written to: D:/Cpp3D/3Log/log4cpp/build

  1. 3. vs打开.sln文件,生成`ALL_BUILD`项目。此版本默认是debugwin32
  2. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1465826/1592895217605-2ecfebc1-7832-44af-93ee-f565aedc6672.png#crop=0&crop=0&crop=1&crop=1&height=253&id=Jf7y6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=506&originWidth=1426&originalType=binary&ratio=1&size=83674&status=done&style=none&width=713)
  3. <a name="Ht9Di"></a>
  4. ## 导入库
  5. 工程目录<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1465826/1592895488835-75cd31e1-e898-4b27-b280-71d4ee46faba.png#crop=0&crop=0&crop=1&crop=1&height=174&id=SmHeg&margin=%5Bobject%20Object%5D&name=image.png&originHeight=347&originWidth=598&originalType=binary&ratio=1&size=21847&status=done&style=none&width=299)
  6. 1. 在工程目录下创建include文件夹,并把log4cpp\include\log4cpp整个文件夹复制进去
  7. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1465826/1592895587618-94f25628-00ba-4371-93d4-548c2a286f58.png#crop=0&crop=0&crop=1&crop=1&height=88&id=F8kXl&margin=%5Bobject%20Object%5D&name=image.png&originHeight=176&originWidth=584&originalType=binary&ratio=1&size=9835&status=done&style=none&width=292)
  8. 2. 在工程目录下创建lib文件夹,并把编译好的log4cpp.lib放进去(路径可查看编译时生成的结果)
  9. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1465826/1592895595586-f3449552-d62e-4a21-a98e-374f369b7184.png#crop=0&crop=0&crop=1&crop=1&height=90&id=KaJNc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=179&originWidth=495&originalType=binary&ratio=1&size=9013&status=done&style=none&width=247.5)
  10. 3. 右键工程,添加头文件路径:`$(SolutionDir)include`
  11. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1465826/1592896122437-62c6f720-ad73-4ec3-89e4-979ef937a949.png#crop=0&crop=0&crop=1&crop=1&height=457&id=qveIz&margin=%5Bobject%20Object%5D&name=image.png&originHeight=914&originWidth=1802&originalType=binary&ratio=1&size=180562&status=done&style=none&width=901)
  12. 4. 添加lib路径:`$(SolutionDir)lib`
  13. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1465826/1592896245655-963500aa-27af-4b6c-b5fe-022a9432d815.png#crop=0&crop=0&crop=1&crop=1&height=413&id=nLnsQ&margin=%5Bobject%20Object%5D&name=image.png&originHeight=826&originWidth=1492&originalType=binary&ratio=1&size=114141&status=done&style=none&width=746)
  14. 5. 添加lib文件名
  15. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1465826/1592896293761-f71cf767-c34c-4779-8cac-0779fe64ef44.png#crop=0&crop=0&crop=1&crop=1&height=440&id=aay28&margin=%5Bobject%20Object%5D&name=image.png&originHeight=880&originWidth=1796&originalType=binary&ratio=1&size=153202&status=done&style=none&width=898)
  16. <a name="kzy5V"></a>
  17. ## 配置文件log4cpp.conf
  18. ```python
  19. #-------定义rootCategory的属性-------
  20. #指定rootCategory的log优先级是ERROR,其Appenders有两个,分别是console,TESTAppender
  21. log4cpp.rootCategory=DEBUG, console, TESTAppender
  22. #-------定义console属性-------
  23. #consoleAppender类型:控制台输出
  24. #下面这三条语句表示控制台输出的log输出的布局按照指定的格式;输出格式是:[%p] %d{%H:%M:%S.%l} (%c): %m%n
  25. log4cpp.appender.console=ConsoleAppender
  26. log4cpp.appender.console.layout=PatternLayout
  27. log4cpp.appender.console.layout.ConversionPattern=[%p] %d{%H:%M:%S.%l} (%c): %m%n
  28. #-------定义TESTAppender的属性-------
  29. #RollingFileAppender类型:输出到回卷文件,即文件到达某个大小的时候产生一个新的文件
  30. #下面的语句表示文件输出到指定的log文件,输出的布局按照指定的格式,输出的格式是:[%d{%Y-%m-%d %H:%M:%S.%l} - %p] (%c): %m%n
  31. log4cpp.appender.TESTAppender=RollingFileAppender
  32. #当日志文件到达maxFileSize大小时,将会自动滚动
  33. log4cpp.appender.TESTAppender.maxFileSize=1024000
  34. #maxBackupIndex指定可以产生的滚动文件的最大数
  35. log4cpp.appender.TESTAppender.maxBackupIndex=40
  36. #fileName指定信息输出到logs/irismatch.log文件
  37. log4cpp.appender.TESTAppender.fileName=/home/qilimi/log.log
  38. #PatternLayout 表示可以灵活指定布局模式
  39. log4cpp.appender.TESTAppender.layout=PatternLayout
  40. #append=true 信息追加到上面指定的日志文件中,false表示将信息覆盖指定文件内容
  41. log4cpp.appender.TESTAppender.append=true
  42. log4cpp.appender.TESTAppender.layout.ConversionPattern=[%d{%Y-%m-%d %H:%M:%S.%l} - %p] (%c): %m%n

【ConversionPattern的参数含义】

符号 说明
%c 输出日志信息所属的类目,通常就是所在类的全名
%d 输出日志时间点的日期或时间,日期参照ANSI C函数的strftime
示例:%d{%Y-%m-%d %H:%M:%S.%l}。输出:2017-02-14 09:25:00.953
%p 优先级,即DEBUG,INFO等
%m 输出log的具体信息
%n 换行符,会根据平台的不同而不同,但对于用户透明
%r 自从layout被创建后的毫秒数
%R 从1970年1月1日0时开始到目前为止的秒数
%u 进程开始到目前为止的时钟周期数
%x NDC

Clog4Util日志工具

Clog4Util.hpp文件:

  1. #pragma once
  2. #include "log4cpp/Category.hh"
  3. #include "log4cpp/Appender.hh"
  4. #include "log4cpp/FileAppender.hh"
  5. #include "log4cpp/OstreamAppender.hh"
  6. #include "log4cpp/Layout.hh"
  7. #include "log4cpp/BasicLayout.hh"
  8. #include "log4cpp/Priority.hh"
  9. #include "log4cpp/PropertyConfigurator.hh"
  10. #include <string>
  11. namespace LogUtil {
  12. int init(const std::string& initfilename);
  13. void close();
  14. void debug(const std::string& tag, const std::string& msg);
  15. void debug(const std::string& msg);
  16. void info(const std::string& tag, const std::string& msg);
  17. void info(const std::string& msg);
  18. void error(const std::string& tag, const std::string& msg);
  19. void error(const std::string& msg);
  20. }
  21. namespace LogUtil {
  22. int init(const std::string& cfg_fp)
  23. {
  24. try
  25. {
  26. log4cpp::PropertyConfigurator::configure(cfg_fp);
  27. }
  28. catch(log4cpp::ConfigureFailure&f)
  29. {
  30. std::cout << "Configure Problem " << f.what() << std::endl;//失败
  31. return -1;
  32. }
  33. return 0;
  34. }
  35. void close()
  36. {
  37. try
  38. {
  39. log4cpp::Category::shutdown();
  40. }
  41. catch(...)
  42. {
  43. }
  44. }
  45. void debug(const std::string& tag, const std::string& msg)
  46. {
  47. try
  48. {
  49. log4cpp::Category& t_debug = log4cpp::Category::getInstance(tag);
  50. t_debug.debug(msg);
  51. }
  52. catch(...)
  53. {
  54. }
  55. }
  56. void debug(const std::string& msg)
  57. {
  58. try
  59. {
  60. log4cpp::Category& t_debug = log4cpp::Category::getInstance(std::string("Debug"));
  61. t_debug.debug(msg);
  62. }
  63. catch(...)
  64. {
  65. }
  66. }
  67. void info(const std::string& tag, const std::string& msg)
  68. {
  69. try
  70. {
  71. log4cpp::Category& t_debug = log4cpp::Category::getInstance(tag);
  72. t_debug.info(msg);
  73. }
  74. catch(...)
  75. {
  76. }
  77. }
  78. void info(const std::string& msg)
  79. {
  80. try
  81. {
  82. log4cpp::Category& t_info = log4cpp::Category::getInstance(std::string("Info"));
  83. t_info.info(msg);
  84. }
  85. catch(...)
  86. {
  87. }
  88. }
  89. void error(const std::string& tag, const std::string& msg)
  90. {
  91. try
  92. {
  93. log4cpp::Category& t_debug = log4cpp::Category::getInstance(tag);
  94. t_debug.error(msg);
  95. }
  96. catch(...)
  97. {
  98. }
  99. }
  100. void error(const std::string& msg)
  101. {
  102. try
  103. {
  104. log4cpp::Category& t_error = log4cpp::Category::getInstance(std::string("Error"));
  105. t_error.error(msg);
  106. }
  107. catch(...)
  108. {
  109. }
  110. }
  111. }

使用

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <signal.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <errno.h>
  7. #include <thread>
  8. #include <time.h>
  9. #include "Clog4Util.h"
  10. int main(int argc, char *argv[])
  11. {
  12. if(argc < 2){
  13. printf("Usage: %s base exponent \n", argv[0]);
  14. return 1;
  15. }
  16. log4Util::Init(argv[1]);
  17. printf("test log4cpp\n");
  18. //存放日志信息
  19. char strLog_[1024] = { 0 };
  20. //建日志写到strLog_中
  21. sprintf(strLog_, "test error log, %s:%d.", __FILE__, __LINE__);
  22. //写入日志
  23. log4Util::Error(strLog_);
  24. //赋空
  25. memset(strLog_, 0, 1024);
  26. //建日志写到strLog_中
  27. sprintf(strLog_, "test error log, %s:%d.", __FILE__, __LINE__);
  28. //写入日志
  29. log4Util::Debug(strLog_);
  30. //赋空
  31. memset(strLog_, 0, 1024);
  32. //建日志写到strLog_中
  33. sprintf(strLog_, "test error log, %s:%d.", __FILE__, __LINE__);
  34. //写入日志
  35. log4Util::Info(strLog_);
  36. //赋空
  37. memset(strLog_, 0, 1024);
  38. //建日志写到strLog_中
  39. sprintf(strLog_, "test error log,tag:1 %s:%d.", __FILE__, __LINE__);
  40. //写入日志
  41. log4Util::Error("1", strLog_);
  42. //赋空
  43. memset(strLog_, 0, 1024);
  44. //建日志写到strLog_中
  45. sprintf(strLog_, "test error log,tag:2 %s:%d.", __FILE__, __LINE__);
  46. //写入日志
  47. log4Util::Debug("2", strLog_);
  48. //赋空
  49. memset(strLog_, 0, 1024);
  50. //建日志写到strLog_中
  51. sprintf(strLog_, "test error log,tag:3 %s:%d.", __FILE__, __LINE__);
  52. //写入日志
  53. log4Util::Info("3", strLog_);
  54. log4Util::close();
  55. return 0;
  56. }