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

文章目录

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

前言

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


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

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

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

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

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

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

Linux项目日志管理log4cpp的安装与使用【结合sample】_第1张图片


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文件夹下的效果如下
Linux项目日志管理log4cpp的安装与使用【结合sample】_第2张图片
我们只需要它的lib和include
进入到include下的log4cpp
Linux项目日志管理log4cpp的安装与使用【结合sample】_第3张图片
进入到lib中,如果关于log4cpp的库没放在一个文件夹中,那么自己创建一下文件夹log4cpp然后将所有有关的库放到里面
Linux项目日志管理log4cpp的安装与使用【结合sample】_第4张图片


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 
#include 

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 
#include 
#include 
#include 
#include 
#include 

//外部的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  !\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)

运行结果:
Linux项目日志管理log4cpp的安装与使用【结合sample】_第5张图片


结语

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

你可能感兴趣的:(Linux环境下代码调试工具,Linux,linux,服务器,运维)