Linux项目日志管理log4cpp的安装与使用【结合sample】

news2024/12/25 9:00:44

文章目录

  • 前言
  • log4cpp安装
  • log4cpp的使用
    • 设置类别输出的(category)和日志优先级(priority)
    • 定义一个宏用于输出
    • 日志配置文件
  • 使用log4cpp的栗子
  • 结语

前言

我们都清楚对于一个项目来说它的日志信息是非常重要的,那么我们应该如何进行日志管理呢?可以使用重定向去输入日志到日志文件中,但是这样一种处理方式,还是有很多不足,比如没有办法输出到多个文件,没有办法设置日志文件大小,不太方便设置日志的级别,如果想远程输出到日志服务器怎么办呢?等等这些问题怎么解决呢?
这里就要引入一个开源库了,也是这篇文章要讲的🐂🍺闪闪的log4cpp


log4cpp是一个C++编写的日志管理库,它提供了多种灵活的日志记录方式和级别控制功能。相比传统的通过重定向将日志文件输出到文件的方法,使用log4cpp进行项目日志管理的优势主要有以下几个方面:

  • 灵活性:log4cpp提供了多种不同的日志记录方式,包括输出到文件、输出到控制台、通过网络发送、通过邮件发送等多种方式,用户可以根据自己的需求选择最合适的日志记录方式。同时,用户可以根据不同的情况配置不同的日志级别,从而更加灵活地控制日志的输出。

  • 可定制性:log4cpp的各个组件可以通过继承和重载的方式进行定制,用户可以根据自己的需求进行扩展和定制,从而实现更加个性化的日志记录功能。

  • 高效性:log4cpp采用了多线程和缓冲区技术,可以有效地减少日志记录对程序性能的影响。同时,log4cpp还支持异步日志记录,可以将日志记录任务交给后台线程异步处理,从而提高程序的性能和响应速度。

  • 可移植性:log4cpp是一个跨平台的日志管理库,可以在多种操作系统和开发环境下使用,从而提高项目的可移植性。

综上所述,使用log4cpp进行项目日志管理可以提高日志记录的灵活性、可定制性、高效性和可移植性,从而更加方便地管理和分析日志信息,为项目的开发和维护提供更好的支持。

在这里插入图片描述


log4cpp安装

log4cpp的官网是:http://log4cpp.sourceforge.net/

wget https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz
tar xzvf log4cpp-1.1.3.tar.gz
cd log4cpp-1.1.3
# 我写的是./configure --prefix=/home/sqh/C++_QN/shared_bike/third
# 这里可以指定安装路径如./configure --prefix = 你想要安装的路径(必须是绝对路径),后续生成include和lib库的地方
./configure 
make
make install

最后third文件夹下的效果如下👇
在这里插入图片描述
我们只需要它的lib和include
进入到include下的log4cpp
在这里插入图片描述
进入到lib中,如果关于log4cpp的库没放在一个文件夹中,那么自己创建一下文件夹log4cpp然后将所有有关的库放到里面
在这里插入图片描述


log4cpp的使用

设置类别输出的(category)和日志优先级(priority)

log4cpp::Category &root = log4cpp::Category::getRoot();
root.setPriority(log4cpp::Priority::NOTICE);
root.addAppender(appender);

日志的级别总共有:NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT < FATAL = EMERG。日志级别的意思是低于该级别的日志不会被记录。,一般当日志文件出现WARN级别的时候就是有问题了,所以如果是要进行生产环境下测试软件的话一般会把日志级别设置为WARN。


定义一个宏用于输出

使用宏主要目的就是为了省事,宏的设置一般是👇
#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << \_\_FILE\_\_ << " " << \_\_LINE\_\_ << ": "
1、当然我们也同样可以使用Category定义的函数:

/**
         * Log a message with the specified priority.
         * @param priority The priority of this log message.
         * @param stringFormat Format specifier for the string to write
         * in the log file.
         * @param ... The arguments for stringFormat
         **/
        virtual void log(Priority::Value priority, const char* stringFormat,
                         ...) throw();

        /**
         * Log a message with the specified priority.
         * @param priority The priority of this log message.
         * @param message string to write in the log file
         **/
        virtual void log(Priority::Value priority,
                         const std::string& message) throw();

       void debug(const char* stringFormat, ...) throw();
	   void debug(const std::string& message) throw();
	   void info(const char* stringFormat, ...) throw();
	   ...

2、如果使用了宏进行日志输出,我们就可以:是不是就方便多了😂

LOG(DEBUG) << "i am happy.";
LOG(INFO)  << "oh, you happy, we happy.";
LOG(NOTICE)<< "please do not contact me. ";
LOG(WARN)  << "i am very busy now.";
LOG(ERROR) << "oh, what happed?";

日志配置文件

在实际工程上应用,我们是使用日志配置文件去控制日志记录的。接下来让我们先配置一个日志配置文件

#定义Root category的属性,类别叫做RootLog,级别为DEBUG
log4cpp.rootCategory=DEBUG, RootLog

#定义RootLog属性
#以什么样的方式输出日志RollingFileAppender(滚动的形式)
log4cpp.appender.RootLog=RollingFileAppender
log4cpp.appender.RootLog.layout=PatternLayout

#输出信息的格式
#log4cpp.appender.RootLog.layout.ConversionPattern=%d{% m-%d %H:%M:%S %l} [%t][%p]%m%n
log4cpp.appender.RootLog.layout.ConversionPattern=%d{%m-%d %H:%M:%S %l} [%t][%p]%m%n

#输出日志的文件名
log4cpp.appender.RootLog.fileName=/var/log/qiniu_bike.log

#日志文件
log4cpp.appender.RootLog.maxFileSize=268435456 #256MB

#滚动输出以后文件满了以后创建的文件
log4cpp.appender.RootLog.fileNamePattern=qiniu_bike_%i.log

#最大备份数
log4cpp.appender.RootLog.maxBackupIndex=256

配置文件详细解释👇

1、log4cpp.rootCategory=DEBUG, RootLog
这行代码是log4cpp中的配置文件,它的作用是设置根日志记录器的输出级别和输出目的地。具体来说,该行代码的含义如下:

  • log4cpp.rootCategory:表示设置根日志记录器的配置信息。
  • DEBUG:表示根日志记录器的输出级别为DEBUG级别,即输出DEBUG及以上级别的日志信息。
  • RootLog:表示将根日志记录器的日志输出目的地设置为名为RootLog的appender(日志输出器),这个appender需要在后面的配置文件中进行具体的定义和配置。

2、log4cpp.appender.RootLog=RollingFileAppender
表示为名为RootLog的appender设置RollingFileAppender的方式进行日志输出。这意味着日志信息将会被写入到一个文件中,同时如果该文件达到一定的大小限制,就会自动滚动(即将旧的日志文件备份并创建新的日志文件继续写入),从而保证日志文件大小的控制和管理。
除了RollingFileAppender类型还有👇

  • FileAppender:将日志信息输出到一个固定的文件中,如果文件不存在则会自动创建。

  • OstreamAppender:将日志信息输出到一个std::ostream对象中,例如输出到控制台、输出到网络流等。

  • SyslogAppender:将日志信息输出到系统的syslog中,通常用于Unix/Linux系统的日志输出。

  • SocketAppender:将日志信息通过网络发送到远程主机上的一个TCP/UDP端口。

  • NTEventLogAppender:将日志信息输出到Windows的Event Log中,通常用于Windows系统的日志输出。

  • NTConsoleAppender:将日志信息输出到Windows的控制台中,通常用于Windows系统的日志输出。

3、log4cpp.appender.RootLog.layout=PatternLayout
表示为名为RootLog的appender设置输出格式为PatternLayout格式。PatternLayout是log4cpp提供的一种输出格式,它可以根据用户指定的模式(Pattern)将日志信息进行格式化输出。用户可以根据自己的需求定义输出格式,例如输出日志信息的级别、时间、线程ID等信息。

4、log4cpp.appender.RootLog.layout.ConversionPattern=%d{%m-%d %H:%M:%S %l} [%t][%p]%m%n
log4cpp.appender.RootLog.layout.ConversionPattern:表示为名为RootLog的appender设置输出格式的具体内容,即日志信息的各个组成部分和它们之间的分隔符等。

  • %d{\%\m-%d %H:%M:%S %l}:表示输出日志信息的时间戳,采用指定的格式进行输出。具体来说,%m-%d表示输出月份和日期,%H:%M:%S表示输出时分秒,%l表示输出函数或者方法名(如果可用)。

  • [%t]:表示输出日志信息所在的线程ID,用方括号括起来。

  • [%p]:表示输出日志信息的级别,用方括号括起来。

  • %m%n:表示输出日志信息的具体内容和换行符。

log4cpp支持的模式字符串非常多,这里列举一些常用的模式字符串:

%d:输出日期时间信息,可以通过指定格式来控制输出格式,例如%d{%m-%d %H:%M:%S.%l}表示输出月份、日期、小时、分钟、秒和毫秒。

%t:输出线程ID。

%p:输出日志级别,例如%p表示输出DEBUG、INFO、WARN、ERROR等级别。

%c:输出Logger名称。

%m:输出日志信息。

%n:输出换行符。

%x:输出与当前线程相关的NDC(Nested Diagnostic Context)信息。

%X:输出与当前线程相关的MDC(Mapped Diagnostic Context)信息。

%F:输出日志所在的源文件名称。

%L:输出日志所在的源文件行号。

%M:输出日志所在的函数或方法名称。

%r:输出日志生成后的时间戳,即从应用程序启动到日志生成的时间间隔。

%u:输出日志生成的线程在应用程序启动后的运行时间,单位为毫秒。

%C:输出日志所在的类名称。

%d{ISO8601}:输出日期时间信息,使用ISO8601标准格式,例如2019-12-31T23:59:59,999。

%d{ABSOLUTE}:输出日期时间信息,使用绝对时间格式,例如23:59:59,999。

%d{DATE}:输出日期信息,例如2019-12-31。

%d{TIME}:输出时间信息,例如23:59:59。

5、log4cpp.appender.RootLog.fileName=/var/log/mybike.log
这个配置指定了日志输出到的文件名为/var/log/mybike.log。也就是说,所有通过RootLogger输出的日志信息都会被写入到该文件中。请注意,在使用该配置前,确保指定的目录和文件名可写。同时,如果该文件不存在,则log4cpp会自动创建该文件。如果该文件已经存在,则日志信息将被追加到该文件的末尾。
6、log4cpp.appender.RootLog.maxFileSize=268435456 #256MB
一个日志文件的大小最大为256MB
7、log4cpp.appender.RootLog.fileNamePattern=mybike_%i.log
这个配置指定了日志输出文件名的模式字符串,滚动输出以后文件满了以后创建的文件,其中%i表示滚动文件的序号,可以通过该模式字符串来控制滚动文件的命名规则。例如,如果设置了该模式字符串为mybike_%i.log,则第一个滚动文件的文件名为mybike_1.log,第二个滚动文件的文件名为mybike_2.log,以此类推。该配置通常与RollingFileAppender一起使用,用于控制滚动文件的命名规则
8、log4cpp.appender.RootLog.maxBackupIndex=256
这个配置指定了滚动文件的最大备份文件数,即在进行日志滚动时最多保留多少个备份文件。例如,如果将该配置设置为256,则log4cpp会在进行日志滚动时保留最近的256个备份文件,并将多余的文件删除。该配置通常与RollingFileAppender一起使用,用于控制滚动文件的最大备份文件数。


使用log4cpp的栗子

当然我们在使用log4cpp的过程中,可以封装一个单例,那么什么是单例嘞?👇
单例指的是一个类仅有一个实例存在于内存中,并且该实例可以被全局访问。单例模式是一种常见的设计模式,其主要目的是确保在系统运行期间,某个类的实例只存在一个。
在这我写了一个名为Logger的类【这个类其实大家都可以拿去自己进行改造成自己想要的样子】
Logger.h

#ifndef DISTRIBUTED_LOGGER_H_
#define DISTRIBUTED_LOGGER_H_

#include <string>
#include <log4cpp/Category.hh>

class Logger
{
public:
	//传log的配置文件
	bool init(const std::string& log_conf_file);
    //返回单例
	static Logger* instance()
	{
		return &instance_;
	}
	
	log4cpp::Category* GetHandle()
	{
		return category_;
	}
	
	
protected:
	//单例
	static Logger instance_;
	//利用category输出日志
	log4cpp::Category* category_;
};

//进行宏的定义,后续方便输出
#define LOG_INFO  Logger::instance()->GetHandle()->info
#define LOG_DEBUG Logger::instance()->GetHandle()->debug
#define LOG_ERROR Logger::instance()->GetHandle()->error
#define LOG_WARN  Logger::instance()->GetHandle()->warn

#endif

Logger.cpp

#include "Logger.h"

#include <iostream>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/RemoteSyslogAppender.hh>
#include <log4cpp/PropertyConfigurator.hh>

//外部的static成员必须声明一下
Logger Logger::instance_;

bool  Logger::init(const std::string& log_conf_file)
{
	try{
		//属性设置
		log4cpp::PropertyConfigurator::configure(log_conf_file);		
	}catch(log4cpp::ConfigureFailure& f)
	{
		//如果出现异常
		std::cerr << " load log config file " << log_conf_file.c_str() << " failed with result : " << f.what()<< std::endl;
        return false;

	}
	//log4cpp::Category* category_;
	category_ = &log4cpp::Category::getRoot();
	return true;
}

main.cpp

#include "Logger.h"

//后续执行命令:xx.exe ./conf/shared_bike.ini
int main(int argc,char** argv)
{
    double a;
    double b;
    if(argc!=3)
    {
        printf("Please input shbk <config file path> <log file config>!\n");
        return -1;
    }
    //使用argv[2]对日志进行配置
    if(!Logger::instance()->init(std::string(argv[2])))
    {
        //初始化日志模块失败
        fprintf(stderr,"init log module failed.\n");
        return -2;
    }
    std::cin>>a;
    std::cin>>b;
    if(b==0)
    {
        LOG_ERROR("b can not zero\n");
        return -1;
    }else
    {
        LOG_INFO("a/b is %lf\n",a/b);
    }
    return 0;
}

注意:要写cmake来包含log4cpp的相关头文件,以及需要链接到log4cpp的lib库
在链接库的时候记得要链接liblog4cpp.a这个库,而不是直接TARGET_LINK_LIBRARIES(myLog log4cpp),因为log4cpp的库有两个,要明确是liblog4cpp.a【如果在书写cmake的时候遇到问题请随时在评论区下留言😀】

TARGET_LINK_LIBRARIES(myLog liblog4cpp.a)
TARGET_LINK_LIBRARIES(myLog pthread)

运行结果:
在这里插入图片描述


结语

总之,log4cpp是一个功能强大的C++日志库,可以帮助开发者轻松地进行项目日志管理。它支持多种日志级别和多种日志输出方式,能够满足不同的日志输出需求。同时,它还支持日志滚动和多线程安全,能够保证日志输出的稳定性和可靠性。在使用log4cpp时,我们需要配置日志级别、日志输出方式、日志格式等参数,以便将日志信息输出到指定的位置,并进行相应的处理
当然,在使用log4cpp时也需要注意一些细节,例如配置文件的路径、日志输出文件的目录是否存在等等。在实际开发中,我们可以根据自己的需求灵活配置log4cpp,并且结合其他工具或框架进行日志输出和分析。总之,良好的日志管理能够帮助我们更好地了解系统的运行情况,及时发现和解决问题,提高代码质量和可维护性。
非常感谢您的观看,希望能够对您有所帮助,谢谢!!!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/418111.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springcloud微服务架构搭建过程

项目地址&#xff1a;源代码 仅作为学习用例使用&#xff0c;是我开发过程中的总结、实际的一部分使用方式 开发环境&#xff1a; jdk11 springboot2.7.6 springcloud2021.0.5 alibabacloud 2021.0.4.0 redis6.0 mysql8.0 一、项目搭建 wdz-api&#xff1a;存放远程服务调用相关…

VS for Qt 向MySql 数据库中插入中文

问题&#xff1a; 今天我想向数据库中插入中文&#xff0c;但是&#xff0c;插入的时候会报错&#xff1a; 首先先看报错&#xff1a; QSqlError("1054", "QMYSQL: Unable to execute query", "Unknown column 韩红 in field list")如果错误码…

将Linux服务器上的项目上传至Github

使用git上传项目到github常规的步骤继续上传注意事项参考文章常规的步骤 初始化git空间 git init向缓冲区添加想要上传的文件 git add -f /data/xuhongbo/xuhongbo.code/unbiased_sgg_xuhongbo_BCL/maskrcnn_benchmark/*添加备注信息告诉机器&#xff0c;你真的要添加上述文…

elasticsearch-7.17.9

1、ElasticSearch 1.1、概念 1.1.1、分片(shard) 1、分片 在ES中所有数据的文件块&#xff0c;也是数据的最小单元块&#xff0c;整个ES集群的核心就是对所有分片的分布、索引、负载、路由等达到惊人的速度。 实列场景&#xff1a; 假设 IndexA 有2个分片&#xff0c;向 I…

数据结构 - 计数排序 | C

什么是计数排序 如上图&#xff0c;统计数组中值的个数&#xff1a; 2个[1]&#xff1a;1&#xff0c;1 1个[2]&#xff1a;2 3个[3]&#xff1a;3&#xff0c;3&#xff0c;3 2个[4]&#xff1a;4&#xff0c;4 传给原数组&#xff1a;&#xff08;即完成排序↓&#xff09; …

Fast R-CNN

目录 1. 关于 R-CNN 的缺点 2. Fast R-CNN 3. Fast R-CNN 算法的流程 3.1 CNN 特征提取 3.2 ROI pooling 3.3 Fast R-CNN 的输出 3.4 损失函数 4. Fast R-CNN的不足 1. 关于 R-CNN 的缺点 RCNN算法流程如下 RCNN算法分为四个步骤&#xff1a; SS 算法生成2000个候选框…

解除游戏多开限制,关闭互斥体句柄

游戏限制多开有很多种方法 比如说遍历窗口,遍历进程,配置文件,注册表,互斥体,mac地址,ip,公共文件,内存映射等等.方法很多.但是绝大部分游戏限制多开都是采用的互斥体.这节课我们来讲解一下关闭互斥体句柄来实现多开.例子为CQYH(这里的防护建议是,增加多种多开限制的方法 以及 …

系统安全与应用【上】

文章目录1.账号安全控制1.1 系统账号清理1.2 密码安全控制1.3 命令历史限制1.4 终端自动注销2.系统引导和登录控制2.1 使用su命令切换用户2.2 限制使用su命令的用户3.可插拔式认证模块PAM3.1 linux中的PAM安全认证3.2 PAM认证原理3.3 PAM认证的构成3.4 PAM安全认证流程3.5 使用…

(八)【软件设计师】计算机系统—浮点数

浮点数 浮点数。当机器字长为n时&#xff0c;定点数的补码和移码可表示2的n方个数&#xff0c;而其原码和反码只能表示2"-1个数&#xff08;0的表示占用了两个编码)&#xff0c;因此&#xff0c;定点数所能表示的数值范围比较小&#xff0c;在运算中很容易因结果超出范围而…

实力爆表,日日新成为AI领航者

目录正式发布自建算力SenseChat编程能力图像生成后言上周五&#xff0c;阿里发布大模型通义千问&#xff0c;正式开始邀请内测。本周一&#xff0c;人工智能巨头商汤科技正式发布“日日新”大模型体系&#xff0c;全面丰富的产品体系&#xff0c;多个功能表现超预期&#xff0c…

MobTech MobPush|不同手机厂商推送问题

配置了华为厂商推送&#xff0c;为什么有的华为设备无法接收离线消息 首先&#xff0c;排查配置的华为厂商参数是否正确&#xff1b; 其次&#xff0c;检查华为设备EMUI版本&#xff0c;低于5.0可能不支持&#xff0c;如果低于5.0&#xff0c;可以尝试升级设备里的‘华为移动服…

Google代码覆盖率最佳实践

软件质量保障: 所寫即所思&#xff5c;一个阿里质量人对测试的所感所悟。谷歌一直倡导的领域之一是使用代码覆盖率数据评估风险并识别测试中的真空。然而&#xff0c;代码覆盖率的价值一直是个争议的话题。每次聊到代码覆盖率时&#xff0c;似乎都会引发无尽的争论。由于大家固…

微信小程序开发 | 小程序开发框架

小程序开发框架7.1 小程序模块化开发7.1.1 模块7.1.2 模板7.1.3 自定义组件7.1.4插件7.2 小程序基础样式库—WeUI7.2.1 初识WeUI7.2.2【案例】电影信息展示7.3 使用vue.js开发小程序7.3.1 初识mpvue7.3.2 开发工具7.3.3 项目结构7.3.4【案例】计数器7.4 小程序组件化开发框架7.…

Ztree树状的处理

1.用一个div进行包裹ztree结构&#xff0c;引用相关的js代码和css样式&#xff0c;这里用的样式是awesome.css 所引用的js文件&#xff0c;css文件可以在网上下载&#xff08;这里所用到的jquery-ztree文件放在网盘了&#xff09; <ul id"tree" class"ztre…

企业即时通讯软件开发基本功能有哪些?

即时通讯是基于互联网技术的新型交流沟通方式&#xff0c;是目前最流行的通讯方式&#xff0c;广泛的应用市场使得各种各样的即时通讯软件系统也层出不穷&#xff0c;企业即时通讯就是其中的一种延伸。是一种面向企业终端使用者的网络营销、网络沟通和内容管理的工具服务&#…

mysql基础安装以及问题

mysql 基础安装以及问题安装MySQL8.0的安装&#xff1a;MySQL5.7 版本的安装、配置卸载服务的启动与停止图形化工具推荐安装 官网&#xff1a;https://www.mysql.com MySQL8.0的安装&#xff1a; 这里是写你直接要安装的目录&#xff1a; 之后配置mysql8.0 注意&#x…

不会注册ChatGPT?4个国内网站让你尽情体验

最近火出圈的科技新词非“ChatGPT”莫属了。 但是由于ChatGPT注册起来比较困难&#xff0c;我到现在都还学不会如何注册.... 但是&#xff01;世上无难事&#xff01;只要有心人&#xff01; 我千辛万苦终于找到几个ChatGPT平替的网站了。 AI中文智能对话 地址&#xff1a;…

目标检测入门:发展历史

预备知识 分类classification 输出:物体的类别 评估方法:准确率 定位location 输出:方框在图片中的位置(x,y,w,h) 评估方法:交并比IOU 定位的解决思路: 思路一:看做回归问题 看做回归问题,我们需要预测出(x,y,w,h)四个参数的值,从而得出方框的位置 成为class…

数字证书的相关专业名词(下)---OCSP及其java中的应用

一、前言 上篇文章我们了解了根证书和校验证书有效性中的一个比较重要的渠道–CRL&#xff0c;但是CRL有着时间延迟&#xff0c;网络带宽消耗等缺点&#xff0c;本篇文章我们了解另一种更高效也是目前被广泛应用的校验证书有效性的另一种方式–OCSP&#xff0c;并且我会结合ja…

4年测试工程师经历,下一步转开发还是继续测试?

​测试四年&#xff0c;没有积累编程脚本能力和自动化经验&#xff0c;找工作时都要求语言能力&#xff0c;自动化框架。感觉开发同事积累的经历容易找工作。下一步&#xff0c;想办法转开发岗还是继续测试&#xff1f;&#xff1f;&#xff1f;正常情况下&#xff0c;有了四年…