当前位置: 首页 > news >正文

【Linux C++】log4cpp日志库的安装和使用详解

log4cpp 是一个开源的 C++ 日志库,灵感来源于 Java 的 log4j。它提供了灵活的日志记录功能,可以帮助开发者在 C++ 应用程序中记录、管理和格式化日志信息。log4cpp 支持多种日志记录策略和输出目标,可以满足各种不同的需求。

1.安装

下载压缩包

下载地址:https://sourceforge.net/projects/log4cpp/files/

安装步骤

$ tar xzvf log4cpp-1.1.4rc3.tar.gz$ cd log4cpp$ ./configure  //进行自动化构建,自动生成makefile$ make$ sudo make install //安装  把头文件和库文件拷贝到系统路径下//安装完后
//默认头文件路径:/usr/local/include/log4cpp
//默认lib库路径:/usr/local/lib

打开log4cpp官网:https://log4cpp.sourceforge.net/

拷贝simple example的内容,编译运行

#include "log4cpp/Category.hh"       // 引入 log4cpp 库的 Category 类
#include "log4cpp/Appender.hh"       // 引入 log4cpp 库的 Appender 基类
#include "log4cpp/FileAppender.hh"   // 引入 log4cpp 库的 FileAppender 类,用于将日志写入文件
#include "log4cpp/OstreamAppender.hh" // 引入 log4cpp 库的 OstreamAppender 类,用于将日志输出到流(如 std::cout)
#include "log4cpp/Layout.hh"          // 引入 log4cpp 库的 Layout 基类
#include "log4cpp/BasicLayout.hh"     // 引入 log4cpp 库的 BasicLayout 类,用于简单的布局格式
#include "log4cpp/Priority.hh"        // 引入 log4cpp 库的 Priority 类,用于设置日志优先级int main(int argc, char** argv) {// 创建一个 OstreamAppender 对象,日志输出到标准输出流(std::cout)log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);appender1->setLayout(new log4cpp::BasicLayout()); // 设置日志布局为 BasicLayout// 创建一个 FileAppender 对象,日志输出到文件 "program.log"log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log");appender2->setLayout(new log4cpp::BasicLayout()); // 设置日志布局为 BasicLayout// 获取根日志类别并设置其优先级为 WARN(警告)log4cpp::Category& root = log4cpp::Category::getRoot();root.setPriority(log4cpp::Priority::WARN);root.addAppender(appender1); // 将 OstreamAppender 添加到根类别// 获取名为 "sub1" 的日志类别,并将 FileAppender 添加到该类别log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));sub1.addAppender(appender2);// 使用根类别记录错误和信息消息root.error("root error"); // 记录错误级别的日志,输出到 std::coutroot.info("root info");  // 记录信息级别的日志,输出将被忽略(因根类别的优先级为 WARN)// 使用 "sub1" 类别记录错误和警告消息sub1.error("sub1 error"); // 记录错误级别的日志,输出到 "program.log"sub1.warn("sub1 warn");   // 记录警告级别的日志,输出到 "program.log"// 使用 printf 风格记录日志消息root.warn("%d + %d == %s ?", 1, 1, "two"); // 格式化日志消息并记录到 std::cout// 使用流的方式记录日志消息root << log4cpp::Priority::ERROR << "Streamed root error"; // 记录错误级别的日志,输出到 std::coutroot << log4cpp::Priority::INFO << "Streamed root info";  // 记录信息级别的日志,输出将被忽略(因根类别的优先级为 WARN)sub1 << log4cpp::Priority::ERROR << "Streamed sub1 error"; // 记录错误级别的日志,输出到 "program.log"sub1 << log4cpp::Priority::WARN << "Streamed sub1 warn";  // 记录警告级别的日志,输出到 "program.log"// 使用 errorStream() 记录错误级别的日志消息root.errorStream() << "Another streamed error"; // 记录错误级别的日志,输出到 std::coutreturn 0; // 程序结束
}

编译指令:** g++ log4cppTest.cc -llog4cpp -lpthread**

可能报错:找不到动态库

解决方法:

cd /etc

sudo vim ld.so.conf

将默认的lib库路径写入,再重新加载

sudo ldconfig

让动态链接库为系统所共享

ld.so.cache 执行了sudo ldconfig之后,会更新该缓存文件,会将所有动态库信息写入到该文件。当可执行程序需要加载相应动态库时,会从这里查找。

完成这些操作后,再使用上面的编译指令去编译示例代码

2.日志系统的设计

日志系统的设计,一般而言要抓住最核心的一条,就是日志从产生到到达最终目的地期间的处理流程。一般而言,为了设计一个灵活可扩展,可配置的日志库,主要将日志库分为4个部分去设计,分别是:记录器、过滤器、格式化器、输出器四部分。

记录器(日志来源):负责产生日志记录的原始信息,比如(原始信息,日志优先级,时间,记录的位置)等等信息。

过滤器(日志系统优先级):负责按指定的过滤条件过滤掉我们不需要的日志。

格式化器(日志布局):负责对原始日志信息按照我们想要的格式去格式化。

输出器(日志目的地):负责将将要进行记录的日志(一般经过过滤器及格式化器的处理后)记录到日志目的地(例如:输出到文件中)。

下面以一条日志的生命周期为例说明日志库是怎么工作的。

一条日志的生命周期:

  1. 产生:info(“log information.”);

  2. 经过记录器,记录器去获取日志发生的时间、位置、线程信息等等信息;

  3. 经过过滤器,决定是否记录;

  4. 经过格式化器处理成设定格式后传递给输出器。例如输出“2018-3-22 10:00:00 [info] log information.”这样格式的日志到文件中。日志的输出格式由格式化器实现,输出目的地则由输出器决定;

  5. 这条日志信息生命结束。

3.log4cpp的核心组件

3.1日志目的地(Appender)

Appender 是 log4cpp 的核心组件之一,负责将日志消息输出到不同的目标,如控制台、文件、网络等。log4cpp 提供了多种类型的 Appender,允许你将日志信息输出到多种地方。

  • FileAppender:将日志消息写入文件。适合持久化日志记录。
  • OstreamAppender :C++通用输出流(如 cout)
  • ConsoleAppender:将日志消息输出到控制台。适用于调试和开发阶段。
  • SyslogAppender:将日志消息发送到系统日志服务。
  • RollingFileAppender:将日志写入文件,并支持日志文件的滚动,避免单个日志文件过大。

3.2日志布局(Layout)

Layout 定义了日志消息的格式。log4cpp 提供了不同类型的 Layout,用于格式化日志消息的输出内容。

  • PatternLayout:最常用的布局,允许自定义格式化模式。例如,可以指定时间戳、日志级别、日志消息等。
  • SimpleLayout:输出简洁的日志格式,通常只包含日志级别和消息。
  • XMLLayout:将日志消息格式化为 XML 格式,适用于需要结构化日志数据的场景。

注意(极易出错):

当日志系统有多个日志目的地时,每一个目的地Appender都需要设置一个布局Layout(一对一关系)

3.3日志记录器(Category)

Category 是日志记录的核心组件,代表一个日志记录器。它管理不同的 Appender 和日志级别。Category 提供了多种方法来记录日志,如 debuginfowarnerrorfatal

  • Root Category:系统默认的根日志记录器,所有日志记录都可以通过根记录器进行管理。
  • 子类 Category:可以创建子类记录器,用于更细粒度的日志记录和管理。

创建Category对象时,可以用getRoot先创建root模块对象,对root模块对象设置优先级和目的地;

再用getInstance创建叶模块对象,叶模块对象会继承root模块对象的优先级和目的地,可以再去修改优先级、目的地

补充:如果没有创建根对象,直接使用getInstance创建叶对象,会先隐式地创建一个Root对象。

子Category可以继承父Category的信息:优先级、目的地

3.4日志优先级(Priority)

对于 log4cpp 而言,有两个优先级需要注意,一个是日志记录器的优先级,另一个就是某一条日志的优先级。Category对象就是日志记录器,在使用时须设置好其优先级;某一行日志的优先级,就是Category对象在调用某一个日志记录函数时指定的级别,如 logger.debug("this is a debug message") ,这一条日志的优先级就是DEBUG级别的。简言之:

日志系统有一个优先级A,日志信息有一个优先级B

只有B高于或等于A的时候,这条日志才会被输出(或保存),当B低于A的时候,这条日志会被过滤;

class LOG4CPP_EXPORT Priority {
public:typedef enum {EMERG = 0,FATAL = 0,ALERT = 100,CRIT = 200,ERROR = 300,WARN = 400,NOTICE = 500,INFO = 600,DEBUG = 700,NOTSET = 800 //这个不代表可以使用的优先级} PriorityLevel;//......
};  //数值越小,优先级越高;数值越大,优先级越低

4.使用示例

4.1将日志输出到屏幕

#include <iostream>
#include <fstream>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/Priority.hh>
using std::cout;
using std::endl;
using std::ofstream;
using namespace log4cpp;void test0(){//1.创建布局对象PatternLayout * ptn1 = new PatternLayout();ptn1->setConversionPattern("%d %c [%p] %m%n");//2.创建目的地对象OstreamAppender* appender1 = new OstreamAppender("output",&cout);/* ofstream ofs("wd.log",std::ios::app); *//* OstreamAppender* appender1 = new OstreamAppender("output",&ofs); *///目的地绑定布局appender1->setLayout(ptn1);//3.创建记录器/* Category & sub1 = Category::getRoot(); */Category & sub1 = Category::getRoot().getInstance("sub1");//4.设置系统的优先级sub1.setPriority(Priority::WARN);//5.记录器添加目的地sub1.addAppender(appender1);//6.写日志sub1.emerg("this is an emerg msg");sub1.fatal("this is a fatal msg");sub1.alert("this is an alert msg");sub1.crit("this is a crit msg");sub1.error("this is an error msg");sub1.warn("this is a warn msg");sub1.notice("this is a notice msg");sub1.info("this is an info msg");sub1.debug("this is a debug msg");//7.关闭资源Category::shutdown();}int main(void){test0();return 0;
}

编译:g++ 01-log4cppPattern.cpp -llog4cpp -lpthread

4.2将日志输出到屏幕和保存到日志文件中

#include <iostream>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/Priority.hh>
using std::cout;
using std::endl;
using namespace log4cpp;void test0(){//1.创建布局对象PatternLayout * ptn1 = new PatternLayout();ptn1->setConversionPattern("%d %c [%p] %m%n");PatternLayout * ptn2 = new PatternLayout();ptn2->setConversionPattern("%d %c [%p] %m%n");//2.创建目的地对象OstreamAppender* appender1 = new OstreamAppender("output",&cout);//目的地绑定布局appender1->setLayout(ptn1);FileAppender * appender2 = new FileAppender("fileApp","wd.log");appender2->setLayout(ptn2);//目的地与布局一对一进行绑定//3.创建记录器/* Category & sub1 = Category::getRoot(); */Category & sub1 = Category::getRoot().getInstance("sub1");//4.设置系统的优先级sub1.setPriority(Priority::WARN);//5.记录器添加目的地sub1.addAppender(appender1);sub1.addAppender(appender2);//6.写日志sub1.emerg("this is an emerg msg");sub1.fatal("this is a fatal msg");sub1.alert("this is an alert msg");sub1.crit("this is a crit msg");sub1.error("this is an error msg");sub1.warn("this is a warn msg");sub1.notice("this is a notice msg");sub1.info("this is an info msg");sub1.debug("this is a debug msg");//7.关闭资源Category::shutdown();//不要这样使用/* delete ptn1; */
}int main(void){test0();return 0;
}

4.3将日志输出保存到回滚文件

#include <iostream>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/Priority.hh>
using std::cout;
using std::endl;
using namespace log4cpp;void test0(){//1.创建布局对象PatternLayout * ptn1 = new PatternLayout();ptn1->setConversionPattern("%d %c [%p] %m%n");PatternLayout * ptn2 = new PatternLayout();ptn2->setConversionPattern("%d %c [%p] %m%n");PatternLayout * ptn3 = new PatternLayout();ptn3->setConversionPattern("%d %c [%p] %m%n");//2.创建目的地对象OstreamAppender* appender1 = new OstreamAppender("output",&cout);//目的地绑定布局appender1->setLayout(ptn1);FileAppender * appender2 = new FileAppender("fileApp","wd.log");appender2->setLayout(ptn2);//目的地与布局一对一进行绑定auto appender3 = new RollingFileAppender("rolling","ROLL.log",5 * 1024,9); appender3->setLayout(ptn3);//3.创建记录器/* Category & sub1 = Category::getRoot(); */Category & sub1 = Category::getRoot().getInstance("sub1");//4.设置系统的优先级sub1.setPriority(Priority::DEBUG);//5.记录器添加目的地sub1.addAppender(appender1);sub1.addAppender(appender2);sub1.addAppender(appender3);//6.写日志int count = 0;while(count < 30){sub1.emerg("this is an emerg msg");sub1.fatal("this is a fatal msg");sub1.alert("this is an alert msg");sub1.crit("this is a crit msg");sub1.error("this is an error msg");sub1.warn("this is a warn msg");sub1.notice("this is a notice msg");sub1.info("this is an info msg");sub1.debug("this is a debug msg");count++;}//7.关闭资源Category::shutdown();//不要这样使用/* delete ptn1; */
}int main(void){test0();return 0;
}

4.4log4cpp配置文件读取

#include <log4cpp/Category.hh>          // 引入 log4cpp 库的 Category 类,用于日志记录
#include <log4cpp/PropertyConfigurator.hh> // 引入 log4cpp 库的 PropertyConfigurator 类,用于从配置文件中配置日志int main(int argc, char* argv[])
{// 指定配置文件名,通常是 log4cpp 的配置文件std::string initFileName = "log4cpp.properties";// 从配置文件中配置 log4cpp 的日志系统log4cpp::PropertyConfigurator::configure(initFileName);// 获取根日志类别log4cpp::Category& root = log4cpp::Category::getRoot();// 获取名为 "sub1" 的日志类别log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));// 获取名为 "sub1.sub2" 的日志类别log4cpp::Category& sub2 = log4cpp::Category::getInstance(std::string("sub1.sub2"));// 使用根类别记录警告消息root.warn("Storm is coming");// 使用 "sub1" 类别记录调试和信息消息sub1.debug("Received storm warning");sub1.info("Closing all hatches");// 使用 "sub1.sub2" 类别记录调试和错误消息sub2.debug("Hiding solar panels");sub2.error("Solar panels are blocked");sub2.debug("Applying protective shield");sub2.warn("Unfolding protective shield");sub2.info("Solar panels are shielded");// 使用 "sub1" 类别记录信息消息sub1.info("All hatches closed");// 使用根类别记录信息消息root.info("Ready for storm.");// 关闭 log4cpp 日志系统log4cpp::Category::shutdown();return 0; // 程序结束
}
//log4cpp.properties
log4cpp.rootCategory=DEBUG, rootAppender
log4cpp.category.sub1=DEBUG, A1, A2
log4cpp.category.sub1.sub2=DEBUG, A3log4cpp.appender.rootAppender=ConsoleAppender
log4cpp.appender.rootAppender.layout=PatternLayout
log4cpp.appender.rootAppender.layout.ConversionPattern=%d [%p] %m%n log4cpp.appender.A1=FileAppender
log4cpp.appender.A1.fileName=A1.log
log4cpp.appender.A1.layout=BasicLayoutlog4cpp.appender.A2=FileAppender
log4cpp.appender.A2.threshold=WARN
log4cpp.appender.A2.fileName=A2.log
log4cpp.appender.A2.layout=PatternLayout
log4cpp.appender.A2.layout.ConversionPattern=%d [%p] %m%n log4cpp.appender.A3=RollingFileAppender
log4cpp.appender.A3.fileName=A3.log
log4cpp.appender.A3.maxFileSize=200
log4cpp.appender.A3.maxBackupIndex=1
log4cpp.appender.A3.layout=PatternLayout
log4cpp.appender.A3.layout.ConversionPattern=%d [%p] %m%n 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++初学(16)
  • Windows系统上进行项目管理工具VisualSVN Server服务端的保姆级安装教程与配置和SVN客户端保姆级安装教程和使用
  • 【项目】云备份系统笔记
  • 部署SAM2遇到的问题
  • JVM理论篇(一)
  • 项目策划书六度自由双足机器人
  • 云计算day33
  • Docker Desktop镜像路径修改一直报错
  • Linux环境下配置jdk、Tomcat和Mysql详解
  • 高性能web服务器4——Nginx反向代理A
  • 工业数采边缘网关: 直击行业痛点,GXF222-4G助您解忧
  • Cesium 全球视角 和 多方案镜头切换
  • webserver使用webbench工具连续压测失败
  • java grpc 使用
  • 关于tresos Studio(EB)的MCAL配置之ADC
  • @jsonView过滤属性
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Intervention/image 图片处理扩展包的安装和使用
  • Java新版本的开发已正式进入轨道,版本号18.3
  • Lsb图片隐写
  • Nodejs和JavaWeb协助开发
  • Python语法速览与机器学习开发环境搭建
  • session共享问题解决方案
  • SQLServer之创建数据库快照
  • Theano - 导数
  • vue自定义指令实现v-tap插件
  • 码农张的Bug人生 - 初来乍到
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 使用SAX解析XML
  • 说说动画卡顿的解决方案
  • 小程序 setData 学问多
  • 优化 Vue 项目编译文件大小
  • 终端用户监控:真实用户监控还是模拟监控?
  • 【云吞铺子】性能抖动剖析(二)
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • #数据结构 笔记三
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (windows2012共享文件夹和防火墙设置
  • (附源码)php新闻发布平台 毕业设计 141646
  • (理论篇)httpmoudle和httphandler一览
  • (全注解开发)学习Spring-MVC的第三天
  • (算法)Travel Information Center
  • (五)网络优化与超参数选择--九五小庞
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (转载)深入super,看Python如何解决钻石继承难题
  • *Django中的Ajax 纯js的书写样式1
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .net core 控制台应用程序读取配置文件app.config
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置