C++ Log4cpp跨平台日志库的使用小结

2025-07-07 17:50

本文主要是介绍C++ Log4cpp跨平台日志库的使用小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下...

项目中,最重要的模块之一就是日志了,今天这篇博客记录项目中log4cpp的用法!

Log4cpp是c++类库,用于灵活地记录文件、syslog、IDSA和其他目的地。它是在Log4j Java库之后建模的,尽可能地接近它们的API。

一、介绍

1. log4cpp的日志方式

log4cpp::FileAppender                            // 输出到文件(常用)
log4cpp::RollingFileAppender                 // 输出到回卷文件,即当文件到达某个大小后回卷(常用)
log4cpp::OstreamAppender                   // 输出到一个ostream类(常用)
log4cpp::RemoteSyslogAppender          // 输出到远程syslog服务器
log4cpp::StringQueueAppender             // 内存队列
log4cpp::SyslogAppender                      // 本地syslog
log4cpp::Win32DebugAppender            // 发送到缺省系统调试器
log4cpp::NTEventLogAppender             // 发送到win 事件日志

2.设置日志输出的格式

log4cpp::FileAppender* appender = new log4cpp::FileAppender("appender", "text.log");     

例如:

PatternLayout:自定义日志格式

log4cpp::PatternLayout *patternLayout = new log4cpp::PatternLayout();
patternLayout->setConversionPattern("%d [%p] - %m%n");
appender->setLayout(patternLayout);

PatternLayout支持以下一组格式字符:

  • %% - 一个百分号;
  • %c - the category;
  • %d - date日期格式:日期格式字符后面可以跟着花括号括起来的日期格式说明符。例如,%d         China编程     {% H: % M: % S、l %}或% d {% d % M H % Y %: % M: % S、l %}。如果没有给出日期          格式说明符,则使用以下格式:"Wed Jan 02 02:03:55 1980"。日期格式说明符承认与              ANSI C函数strftime相同的语法,只是增加了1个。加号是以毫秒为单位的说明符%l,用          0填充为3位数字;
  • %m - 你要输出的日志信息;
  • %n - 换行符;
  • %p - 优先级;
  • %r - 该布局创建后的毫秒数;
  • %R - 从1970年1月1日0时开始到目前为止的秒数;
  • %u - 进程开始到目前为止的时钟周期数;
  • %x - the NDC;
  • %t - 线程的名字;
  • 默认情况下,PatternLayout的ConversionPattern设置为“%m%n”。

3. 设置日志的输出优先级

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

日志的级别总共有:

NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT < FATAL = EMERG

日志级别的意思是低于该级别的日志不会被记录。

二、Window

1. 下载log4cpp

log4cpp官网:

Log for C++ Project

C++ Log4cpp跨平台日志库的使用小结

C++ Log4cpp跨平台日志库的使用小结

下载后解压进入msvc10

C++ Log4cpp跨平台日志库的使用小结

C++ Log4cpp跨平台日志库的使用小结

因为官方提供的是vs2010编译的项目,所以根据自己电脑装的vs去打开即可,例如我这里使用vs2017去打开,打开后会提示升级,升级即可。

C++ Log4cpp跨平台日志库的使用小结

2. 编译

C++ Log4cpp跨平台日志库的使用小结

3. 报错解决1

 不出意外的话,会报错。

解决方法:①在log4cpp项目工程中找到NTEventLogCategories.mc文件,选择该文件上然后右键选择属性,在弹出窗口中找到“配置属性 - 自定义生成工具 - 常规 - 命令行”中修改编译命令,设置为如下命令:

if not exist $(OutDir) md $(OutDir)
mc.exe -h $(OutDir) -r $(OutDir) $(ProjectDir)..\%(Filename).mc
RC.exe -r -fo $(OutDir)%(Filename).res $(OutDir)%(Filename).rc
link.exe /MACHINE:IX86 -dll -noentry -out:$(OutDir)NTEventLogAppender.dll $(OutDir)%(Filename).res

C++ Log4cpp跨平台日志库的使用小结

C++ Log4cpp跨平台日志库的使用小结

然后再次右键log4cpp,选择重新编译!

 不出意外的话,再次报错。

4. 报错解决2

C++ Log4cpp跨平台日志库的使用小结

解决方法:由于log4cpp中对snprintf进行了重新实现,visual studio的c库对snprintf也有实现,Windows中在链接时会报snprintf函数冲突,所以需要设置log4cpp的预编译项,选择使用visual stuido中c库的实现,在log4cpp工程上点右键选属性,在”配置属性 - C/C++ - 预处理器 - 预处理器定义"中增加一条预处理定义 。

HAVE_SNPRINTF

C++ Log4cpp跨平台日志库的使用小结

C++ Log4cpp跨平台日志库的使用小结

再次编译!

5. 编译成功

不出意外的话,编译通过!

C++ Log4cpp跨平台日志库的使用小结

进入路径log4cpp-1.1.3\log4cpp\msvc10\log4cpp\Debug,编译好的库就在这里。

C++ Log4cpp跨平台日志库的使用小结

头文件路径:log4cpp-1.1.3\log4cpp 

C++ Log4cpp跨平台日志库的使用小结

 注意,这是编译x86(Win32)的库,如果需要编译x64的库,在项目中添加x64的库后进行编译即可;编译好的库路径:log4cpp-1.1.3\log4cpp\msvc10\x64\Debug

C++ Log4cpp跨平台日志库的使用小结

 Release库编译方式与上面方式一样!

6. 测试

官方例子,稍作修改

新建项目,将上面编译好的 log4cpp.dll 和 log4cpp.lib 和 /include 文件夹拷贝到项目路径中去

#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/Priority.hh"
#include "log4cpp/PatternLayout.hh"


int main(void) {

	/* 1.日志输出到控制台 */
	{
		log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);
		appender1->setLayout(new log4cpp::BasicLayout());	// 默认配置

		log4cpp::Category& root = log4cpp::Category::getRoot();
		root.setPriority(log4cpp::Priority::WARN);
		root.addAppender(appender1);

		// 1.use of functions for logging messages	
		root.debug("root debug");
		root.warn("root warn");
		root.error("root error");
		root.info("root info");

		// 2.printf-style for logging variables
		root.warn("%d + %d == %s ?", 1, 1, "two");

		// 3.use of streams for logging messages
		root << log4cpp::Priority::ERROR << "Streamed root error";
		root << log4cpp::Priority::INFO << "Streamed root info";

		// 4.or this way:
		root.errorStream() << "Another streamed error";
		root.debugStream() << "Another streamed debug";
	}
	
	/* 2.日志输出到控制台和本地文件 */
	{
		log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log");
		appender2->setLayout(new log4cpp::BasicLayout());

		log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));
		sub1.addAppender(appender2);

		sub1.error("sub1 error");
		sub1.warn("sub1 warn");

		sub1 << log4cpp::Priority::ERROR << "Streamed sub1 error";
		sub1 << log4cpp::Priority::WARN << "Streamed sub1 warn";
	}

	/* 3.日志输出到本地文件 */
	{
		std::string logFileName = "test.log";

		// 优先级
		log4cpp::Priority::PriorityLevel logPri = log4cpp::Priority::DEBUG;		
		
		// 自定义布局
		log4cpp::PatternLayout* logLayout = new log4cpp::PatternLayout();
		logLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] : %m%n");

		// 日志输出到本地文件
		log4cpp::FileAppender* logFile = new log4cpp::FileAppender("default", logFileName);
		logFile->setLayout(logLayout);	// 设置自定义布局

		// 输出日志的操作类
		log4cpp::Category& logCat = log4cpp::Category::getInstance("logCat");
		logCat.addAppender(logFile);
		
		编程China编程//设置优先级
		logCat.setPriority(logPri);

		logCat.error("测试 error");	
		logCat.debug("测试 debug");

		logCat.warn("%d + %d == %s ?", 1, 1, "two");

		logCat << log4cpp::Priority::ERROR << "Streamed root error";
		logCat << log4cpp::Priority::INFO << "Streamed root info";

		logCat.errorStream() << "Another streamed error";
		logCat.debugStream() << "Another streamed debug";
	}

	// 关闭日志
	log4cpp::Category::shutdown();

	return 0;
}

三、Linux

1. 下载Log4cpp

可以通过上面的官网去下载,然后再拷入Linux系统中!

或者根据自己系统的特性,使用下面链接去下载,

https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz

例如Ubuntu: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 -zxvf log4cpp*.tar.gz 去解压。

2. 编译安装

然后 cd log4cpp* 进入文件夹

然后执行 ./configure

然后执行 make

然后执行 make install 

即可安装成功!

命令汇总:

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 
make
make install

安装完毕后,log4cpp库路径在 /usr/local/lib

可以使用命令 mv -if /usr/local/lib/liblog4cpp.* 自己的项目路径 拷贝到自己的项目路径中去;例如,我会在项目路径中创建一个lib文件夹,将刚刚安装的log4cpp库拷贝到此文件夹中

log4cpp头文件路径在 /usr/local/include/log4cpp

可以使用命令 mv -if /usr/local/include/log4cpp 自己的项目路径 拷贝到自己的项目路径中去;例如,我会在项目路径中创建一个include文件夹,将刚刚安装的log4cpp头文件拷贝到此文件夹中

C++ Log4cpp跨平台日志库的使用小结

3. 测试

#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#javascriptinclude "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/Priority.hh"
#include "log4cpp/PatternLayout.hh"


int main(int argc, char **argv) {

	/* 1.日志输出到控制台 */
	{
		log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);
		appender1->setLayout(new log4cpp::BasicLayout());	// 默认配置

		log4cpp::Category& root = log4cpp::Category::getRoot();
		root.setPriority(log4cpp::Priority::WARN);
		root.addAppender(appender1);

		// 1.use of functions for logging messages	
		root.debug("root debug");
		root.warn("root warn");
		root.error("root error");
		root.info("root info");

		// 2.printf-style for logging variables
		root.warn("%d + %d == %s ?", 1, 1, "two");

		// 3.use of streams for logging messages
		root << log4cpp::Priority::ERROR << "Streamed root error";
		root << log4cpp::Priority::INFO << "Streamed root info";

		// 4.or this way:
		root.errorStream() << "Another streamed error";
		root.debugStream() << "Another streamed debug";
	}
	
	/* 2.日志输出到控制台和本地文件 */
	{
		log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log");
		appender2->setLayout(new log4cpp::BasicLayout());

		log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));
		sub1.addAppender(appender2);

		sub1.error("sub1 error");
		sub1.warn("sub1 warn");

		sub1 << log4cpp::Priority::ERROR << "Streamed sub1 error";
		sub1 << log4cpp::Priority::WARN << "Streamed sub1 warn";
	}

	/* 3.日志输出到本地文件 */
	{
		std::string logFileName = "test.log";

		// 优先级
		log4cpp::Priority::PriorityLevel logPri = log4cpp::Priority::DEBUG;		
		
		// 自定义布局
		log4cpp::PatternLayout* logLayout = new log4cpp::PatternLayout();
		logLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] : %m%n");

		// 日志输出到本地文件
		log4cpp::FileAppender* logFile = new log4cpp::FileAppender("default", logFileName);
		logFile->setLayout(logLayout);	// 设置自定义布局

		// 输出日志的操作类
		log4cpp::Category& logCat = log4cpp::Category::getInstance("logCat");
		logCat.addAppender(logFile);
		
		//设置优先级
		logCat.setPriority(logPri);

		logCat.error("测试 error");	
		logCat.debug("测试 debug");

		logCat.warn("%d + %d == %s ?", 1, 1, "two");

		logCat << log4cpp::Priority::ERROR << "Streamed root error";
		logCat << log4cpp::Priority::INFO << "Streamed root info";

		logCat.errorStream() << "Another streamed error";
		logCat.debugStream() << "Another streamed debug";
	}

	// 关闭日志
	log4cpp::Category::shutdown();

	return 0;
}

编译:

g++ test_log4cpp.cpp -I ./inlcude/ -L ./lib/  -llog4cpp1 -lpthread -o test_log4cpp

log4cpp1:是log4cpp.a静态库,我将名字改成这样(在上图中可以看到),才可以正常链接到静态库;不知道为什么,链接动态库.so,编译会报错,所以只能链接静态库去完成编译运行。

-I:指定头文件路径,可以使用相对路径
-L:指定库的路径,可以使用相对路径

四、log4cpp项目用法

以下介绍的项目用法,Linux和Window环境均可使用! 

一般来说,日志都是由独立的文件夹去保存的,下面为了方便就直接将日志保存在main函数同级目录了。 

1. 配置文件使用log4cpp

新建项目,在项目路径下新建文件名为:log.conf

粘贴以下配置到log.conf文件中

#定义Root category的属性
log4cpp.rootCategory=DEBUG, RootLog     # 优先级, 当前日志代表变量名

#定义RootLog属性
#log4cpp.appender.RootLog = FileAppender           # 输出到文件
log4cpp.appender.RootLog = RollingFileAppender    # 回卷
log4cpp.appender.RootLog.layout = PatternLayout   # 自定义输出日志格式

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

# 日志名
log4cpp.appender.RootLog.fileName = ./test.log

# 单个日志文件大小
log4cpp.appender.RootLog.maxFileSize = 268435456 #256MB

# 回卷日志个数名
log4cpp.appender.RootLog.fileNamePattern = test_%i.log

# 日志个数
log4cpp.appender.RootLog.maxBackupIndex = 256

# append=true 信息追加到上面指定的日志文件中,false表示将信息覆盖指定文件内容
log4cpp.appender.RootLog.append = true

在项目中新建文件MyLogger.h

#ifndef _MY_LOGGER_H_
#define _MY_LOGGER_H_

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

class MyLogger {
public:
	bool init(const std::string &log_conf_file);			// 指定加载log配置文件
	static MyLogger *instance() { return &_instance; };		// 单例模式,返回自己

	log4cpp::Category *GetHandle() { return _category; };	

private:
	static MyLogger _instance;
	log4cpp::Category *_category;	// 通过此对象可以实现日志写入
};

/* 宏定义,方便调用 */
#define LOG_DEBUG MyLogger::instance()->GetHandle()->debug		// 调试
#define LOG_INFO MyLogger::instance()->GetHandle()->info		// 信息,消息
#define Log_NOTICE MyLogger::instance()->GetHandle()->notice	// 通知
#define LOG_WARN MyLogger::instance()->GetHandle()->warn		// 警告
#define LOG_ERROR MyLogger::instance()->GetHandle()->error		// 错误
#define LOG_FATAL MyLowww.chinasem.cngger::instance()->GetHandle()->fatal		// 致命错误

/*
 * __LINE__ : 文件中的当前行号;
 * __FILE__ : 文件的完整路径和文件名;如果用在包含文件中,则返回包含文件名;
 * __FUNCTION__ : 函数名字。
 */
#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << "[" << __FUNCTION__ << "][" << __LINE__ << "]: "
//#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << "[" << __FILE__ << "][" << __FUNCTION__ << "][" << __LINE__ << "]: "

#endif

在项目中新建文件MyLogger.cpp

#include "MyLogger.h"

#include <IOStream>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/PropertyConfigurator.hh>


// 静态变量,需要在类外部初始化一下
MyLogger MyLogger::_instance;

bool MyLogger::init(const std::string &log_conf_file) {
	try {
		log4cpp::PropertyConfigurator::configure(log_conf_file);	// 初始化log配置文件
	} catch (log4cpp::ConfigureFailure &f) {
		std::cerr << "load log config file " << log_conf_file.c_str() << " failed with result: " << f.what() << std::endl;
		return false;
	}

	// 初始化成功后,使用getRoot()获取操作日志的对象
	_category = &log4cpp::Category::getRoot();
	
	return true;
}

main函数测试

#include "MyLogger.h"

int main(void) {
	if (!MyLogger::instance()->init("log.conf")) {
		fprintf(stderr, "init log module failed.\n");
		return -1;
	}

	LOG_DEBUG("测试 debug.");
	LOG_INFO("测试 inof.");
	Log_NOTICE("测试 notice.");
	LOG_WARN("测试 warnphp.");
	LOG_ERROR("测试 error.");
	LOG_FATAL("测试 fatal.");

	LOG_DEBUG("%d + %c == %s", 1, 'a', "1a");

	LOG(DEBUG) << "123";
	LOG(ERROR) << "ERROR";

    // 关闭日志
	log4cpp::Category::shutdown();

	return 0;
}

运行结果:

C++ Log4cpp跨平台日志库的使用小结

 在运行一次项目:

C++ Log4cpp跨平台日志库的使用小结

Linux编译命令:(链接的是静态库)

g++ main.cpp MyLogger.h MyLogger.cpp -std=c++11 -I ./inlcude/ -L ./lib/  -llog4cpp1 -lpthread -o test_log4cpp

2. 纯代码使用log4cpp

网上找的代码,感觉挺不错的,拷贝过来做了修改,改成自己以后做项目可能会这样使用! 

MyLog.h

#ifndef _MY_LOG_H_
#define _MY_LOG_H_

#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/PropertyConfigurator.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/RollingFileAppender.hh>

#include <string>


// 优先级
#define COUNT_PRITY			log4cpp::Priority::INFO;		// 控制台
#define LOG_PRITY			log4cpp::Priority::DEBUG;		// 本地文件


/*采用单例模式设计,包含两个category对象,一个负责输出到屏幕的信息,一个负责记录到日志的信息,
通过设置优先级差别,可以实现所有信息都记录在日志中,遇到error及以上的信息时打印到屏幕上*/
class MyLog {
private:
	MyLog(bool b) {
		outToScreen = b;
	}
	~MyLog() {}
	static MyLog * log;
	bool outToScreen;//是否输出日志信息到屏幕
	static std::string _screenInfo;//屏幕日志信息
	static std::string _logName;//文件日志名称

	static log4cpp::Category& logCat;
	static log4cpp::Category& coutCat;

	static log4cpp::FileAppender* logFile;//文件日志输入
	static log4cpp::OstreamAppender* logScreen;//屏幕日志输入
	static log4cpp::RollingFileAppender *rollLogFile;	/* 回卷用这个 */

	static log4cpp::Priority::PriorityLevel logPri;//文件日志优先级
	static log4cpp::Priority::PriorityLevel coutPri;//屏幕日志优先级

	static log4cpp::PatternLayout* logLayout;//日志布局 
	static log4cpp::PatternLayout* screenLayout;//屏幕布局 
	static log4cpp::PatternLayout* logLayout2;	/* 回卷用这个 */

private:
	// 返回当前年月日时分秒
	static std::string getCurrentTime(std::string& year, std::string& month, std::string& day, std::string& hour, std::string& min, std::string& sec);

public:
	// 初始化日志配置信息
	static bool init(std::string logName = "time", bool toScreen = false);
	//获取日志函数,默认参数选择是否输出到屏幕
	static MyLog* getLog(bool toScreen = false);
	//销毁日志对象
	static void destoryLog();
	//设置日志记录优先级
	static void setPri(log4cpp::Priority::PriorityLevel coutLevel, log4cpp::Priority::PriorityLevel logLevel);
	//记录日志,调用参数 __LINE__ ,__FUNCTION__
	void warn(const char * msg, int line = __LINE__, const char *function = "warn");
	void error(const char * msg, int line = __LINE__, const char *function = "error");
	void debug(const char * msg, int line = __LINE__, const char *function = "debug");
	void info(const char * msg, int line = __LINE__, const char *function = "info");
};

//为避免每次调用都要填写参数__LINE__和__FUNCTION__,可以使用带参数的宏定义
#define  MyLogWARN(msg) MyLog::getLog()->warn(msg,__LINE__,__FUNCTION__);
#define  MyLogINFO(msg) MyLog::getLog()->info(msg,__LINE__,__FUNCTION__);
#define  MyLogERROR(msg) MyLog::getLog()->error(msg,__LINE__,__FUNCTION__);
#define  MyLogDEBUG(msg) MyLog::getLog()->debug(msg,__LINE__,__FUNCTION__);

#endif

MyLog.cpp

#include "MyLog.h"

#include <time.h>

MyLog* MyLog::log = NULL;
std::string MyLog::_screenInfo = "screenInfo";
std::string MyLog::_logName = "log";

log4cpp::Category& root = log4cpp::Category::getRoot();
log4cpp::Category& MyLog::logCat = root.getInstance(MyLog::_logName);
log4cpp::Category& MyLog::coutCat = root.getInstance(MyLog::_screenInfo);

// 优先级
log4cpp::Priority::PriorityLevel MyLog::coutPri = COUNT_PRITY;		// 控制台
log4cpp::Priority::PriorityLevel MyLog::logPri = LOG_PRITY;		// 本地文件

log4cpp::PatternLayout* MyLog::logLayout = NULL;
log4cpp::PatternLayout* MyLog::screenLayout = NULL;
log4cpp::PatternLayout* MyLog::logLayout2 = NULL;	/* 回卷用这个 */

log4cpp::FileAppender* MyLog::logFile = NULL;//文件日志输入
log4cpp::OstreamAppender* MyLog::logScreen = NULL;//屏幕日志输入
log4cpp::RollingFileAppender *MyLog::rollLogFile;	/* 回卷用这个 */

bool MyLog::init(std::string logName, bool toScreen) {

	// 判断如果传入文件名参数为空,或为默认参数,则使用当前年月日.log作为日志文件名
	if (logName.empty() || logName == "time") {
		std::string year, month, day, hour, min, sec;
		getCurrentTime(year, month, day, hour, min, sec);
		logName = year + month + day + ".log";
	}

	if (MyLog::log == NULL) {
		MyLog::log = new MyLog(toScreen);

		MyLog::_logName = logName;

		log4cpp::Category& logCat = root.getInstance(MyLog::_logName);
		log4cpp::Category& coutCat = root.getInstance(MyLog::_screenInfo);

		logScreen = new log4cpp::OstreamAppender("logScreen", &std::cout);
		logFile = new log4cpp::FileAppender("logFile", MyLog::_logName);								/* 然后注释这个 */
		//rollLogFile = new log4cpp::RollingFileAppender("rollLogFile", MyLog::_logName, 1024*1024, 5);	/* 回卷用这个 */	// 单个日志文件大小1M,5个回卷


		//设置布局
		MyLog::logLayout = new log4cpp::PatternLayout();	/* 然后注释这个 */
		MyLog::screenLayout = new log4cpp::PatternLayout();
		MyLog::logLayout2 = new log4cpp::PatternLayout();	/* 回卷用这个 */
		logLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %m%n");
		screenLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %m%n");
		logLayout2->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %m%n");
		MyLog::logScreen->setLayout(screenLayout);
		MyLog::logFile->setLayout(logLayout);			/* 然后注释这个 */
		//MyLog::rollLogFile->setLayout(logLayout2);	/* 回卷用这个 */


		//追加到目录	
		MyLog::logCat.addAppender(MyLog::logFile);			/* 然后注释这个 */
		//MyLog::logCat.addAppender(MyLog::rollLogFile);	/* 回卷用这个 */
		MyLog::coutCat.addAppender(MyLog::logScreen);
		
		//设置优先级
		MyLog::logCat.setPriority(MyLog::logPri);
		MyLog::coutCat.setPriority(MyLog::coutPri);
	}
	MyLog::log->outToScreen = toScreen;


	return true;
}

//获取日志函数,默认参数选择是否输出到屏幕
MyLog* MyLog::getLog(bool toScreen) {
	MyLog::log->outToScreen = toScreen;

	if (NULL == MyLog::log) {
		printf("MyLog::log is NULL, please use MyLog::init!\n");
		return NULL;
	}

	return MyLog::log;
}
//销毁日志对象
void MyLog::destoryLog() {
	log4cpp::Category::shutdown();
	delete MyLog::log;
}
//设置日志记录优先级
void MyLog::setPri(log4cpp::Priority::PriorityLevel coutLevel, log4cpp::Priority::PriorityLevel logLevel) {
	MyLog::logPri = logLevel;
	MyLog::coutPri = coutLevel;
	MyLog::logCat.setPriority(MyLog::logPri);
	MyLog::coutCat.setPriority(MyLog::coutPri);
}
//记录日志,调用参数__FILE__, __LINE__ ,__FUNCTION__
void MyLog::warn(const char * msg, int line, const char *function) {
	char info[4096] = { 0 };
	sprintf(info, "[%s][%d]: %s", function, line, msg);
	if (this->outToScreen) {
		logCat.warn(info);
		coutCat.warn(info);
	} else {
		logCat.warn(info);
	}
}
void MyLog::error(const char * msg, int line, const char *function) {
	char info[4096] = { 0 };
	sprintf(info, "[%s][%d]: %s", function, line, msg);
	if (this->outToScreen) {
		logCat.error(info);
		coutCat.error(info);
	} else {
		logCat.error(info);
	}
}
void MyLog::debug(const char * msg, int line, const char *function) {
	char info[4096] = { 0 };
	sprintf(info, "[%s][%d]: %s", function, line, msg);
	if (this->outToScreen) {
		logCat.debug(info);
		coutCat.debug(info);
	} else {
		logCat.debug(info);
	}
}
void MyLog::info(const char * msg, int line, const char *function) {
	char info[4096] = { 0 };
	sprintf(info, "[%s][%d]: %s", function, line, msg);

	if (this->outToScreen) {
		logCat.info(info);
		coutCat.info(info);
	} else {
		logCat.info(info);
	}
}

std::string MyLog::getCurrentTime(std::string& year, std::string& month, std::string& day, std::string& hour, std::string& min, std::string& sec) {
	// 获取系统时间 - 年月日时分秒
	time_t _time;
	struct tm* target_time;
	time(&_time);
	target_time = localtime(&_time);


	year = std::to_string(target_time->tm_year + 1900);
	month = target_time->tm_mon + 1 > 9 ? std::to_string(target_time->tm_mon + 1) : "0" + std::to_string(target_time->tm_mon + 1);
	day = target_time->tm_mday > 9 ? std::to_string(target_time->tm_mday) : "0" + std::to_string(target_time->tm_mday);
	hour = target_time->tm_hour > 9 ? std::to_string(target_time->tm_hour) : "0" + std::to_string(target_time->tm_hour);
	min = target_time->tm_min > 9 ? std::to_string(target_time->tm_min) : "0" + std::to_string(target_time->tm_min);
	sec = target_time->tm_sec > 9 ? std::to_string(target_time->tm_sec) : "0" + std::to_string(target_time->tm_sec);

	return year + month + day + hour + min + sec;
}

main函数测试

#include "MyLog.h"


int main(void) {

	if (!MyLog::init("")) {
		fprintf(stderr, "init log module failed.\n");
		return -1;
	}

	MyLogWARN("警告");
	MyLogINFO("信息");
	MyLogERROR("错误");
	MyLogDEBUG("调试");
	
    // 关闭日志
	log4cpp::Category::shutdown();

	return 0;
}

运行结果:

C++ Log4cpp跨平台日志库的使用小结

Linux编译命令:(链接的是静态库)

g++ main.cpp MyLog.h MyLog.cpp -std=c++11 -I ./inlcude/ -L ./lib/  -llog4cpp1 -lpthread -o test_log4cpp

五、总结

日志在项目中是必须使用的,如果看完此篇博客还是不太懂log4cpp日志如何使用,直接拷贝上面项目代码去到自己的项目中就可以直接使用了!

到此这篇关于C++ Log4cpp跨平台日志库使用记录(Window与Linux)的文章就介绍到这了,更多相关C++ Log4cpp内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于C++ Log4cpp跨平台日志库的使用小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155320

相关文章

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

Ubuntu如何分配​​未使用的空间

《Ubuntu如何分配​​未使用的空间》Ubuntu磁盘空间不足,实际未分配空间8.2G因LVM卷组名称格式差异(双破折号误写)导致无法扩展,确认正确卷组名后,使用lvextend和resize2fs... 目录1:原因2:操作3:报错5:解决问题:确认卷组名称​6:再次操作7:验证扩展是否成功8:问题已解

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP