C++ Log4cpp cross-platform log library usage records (Window and Linux)

In the project, one of the most important modules is the log. Today this blog records the usage of log4cpp in the project!

Log4cpp is a c++ class library for flexible logging to file, syslog, IDSA and other destinations. It is modeled after the Log4j Java library, as close as possible to their API.


Table of contents

1. Introduction

1. The logging method of log4cpp

2. Set the format of the log output

3. Set the output priority of the log

2. Window

1. Download log4cpp

2. Compile

3. Error resolution 1

4. Error resolution 2

5. Compiled successfully

6. Test

3. Linux

1. Download Log4cpp

2. Compile and install

3. Test

 Four, log4cpp project usage

1. The configuration file uses log4cpp

2. Pure code uses log4cpp

V. Summary


1. Introduction

1. The logging method of log4cpp

log4cpp:: FileAppender                            // Output to a file (commonly used)
log4cpp:: RollingFileAppender                 // Output to a rollback file, that is, roll back when the file reaches a certain size (commonly used)
log4cpp:: OstreamAppender                    // Output to an ostream class (commonly used )
log4cpp::RemoteSyslogAppender // output to remote syslog server
log4cpp::StringQueueAppender // memory queue
log4cpp::SyslogAppender // local syslog
log4cpp::Win32DebugAppender // send to default system debugger
log4cpp::NTEventLogAppender // send to win event log

2.  Set the format of the log output

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

For example:

PatternLayout: custom log format

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

PatternLayout supports the following set of formatting characters:

  • %%  - a percent sign;
  • %c - the category;
  • %d  - date format: The date format character may be followed by a date format specifier enclosed in curly braces. For example, %d {% H: % M: % S, l %} or %d {% d %MH % Y %: % M: % S, l %}. If no date format specifier is given, the following format is used: "Wed Jan 02 02:03:55 1980". The date format specifier recognizes the same syntax as the ANSI C function strftime, with just one addition. The plus sign is the specifier %l in milliseconds, padded with 0 to 3 digits;
  • %m  - the log information you want to output;
  • %n  - newline character;
  • %p  - priority;
  • %r  - milliseconds since the layout was created;
  • %R  - the number of seconds since January 1, 1970 at 00:00;
  • %u  - the number of clock cycles since the process started;
  • %x - the NDC;
  • %t  - the name of the thread;
  • By default, the ConversionPattern of PatternLayout is set to "%m%n".

3. Set the output priority of the log

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

There are a total of log levels:

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

The log level means that logs below this level will not be recorded.


2. Window

1. Download log4cpp

log4cpp official website:

After downloading, unzip and enter msvc10

 

Because the official project is compiled by vs2010, you can open it according to the vs installed on your computer. For example, I use vs2017 to open it here. After opening, it will prompt to upgrade, just upgrade.

2. Compile

  

3. Error resolution 1

 If nothing else, an error will be reported.

Solution: ①Find the NTEventLogCategories.mc file in the log4cpp project, select the file and then right-click to select Properties, and in the pop-up window, find the "Configuration Properties - Custom Build Tool - General - Command Line " to modify the compilation command and set it to Command as follows:

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

Then right-click log4cpp again and choose to recompile!

 If nothing else, report an error again.

4. Error resolution 2

Solution: Since snprintf is re-implemented in log4cpp, the c library of visual studio also implements snprintf, and the snprintf function conflict will be reported when linking in windows, so it is necessary to set the precompiled item of log4cpp and choose to use the c library in visual studio For the implementation, right-click on the log4cpp project to select properties, and add a preprocessing definition in " Configuration Properties - C/C++ - Preprocessor - Preprocessor Definition ".

HAVE_SNPRINTF

Compile again!

5. Compiled successfully

If nothing else, the compilation passed!

 Enter the path log4cpp-1.1.3\log4cpp\msvc10\log4cpp\Debug, the compiled library is here.

Header file path: log4cpp-1.1.3\log4cpp 

 Note that this is to compile the x86 (Win32) library. If you need to compile the x64 library, just add the x64 library to the project and compile it; the compiled library path: log4cpp-1.1.3\log4cpp\msvc10\x64\ Debug

 The Release library is compiled in the same way as above!

6. Test

Official example, slightly modified

Create a new project, copy the log4cpp.dll and log4cpp.lib compiled above and the /include folder to the project path

#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);
		
		//设置优先级
		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;
}

3. Linux

1. Download Log4cpp

You can download it through the official website above, and then copy it into the Linux system!

Or according to the characteristics of your own system, use the link below to download,

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

For example 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

After downloading, use the command tar -zxvf log4cpp*.tar.gz  to decompress.

2. Compile and install

Then  cd log4cpp* into the folder

Then execute  ./configure

Then execute make

Then execute  make install 

You can install successfully!

Command summary:

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

After installation, the log4cpp library path is in /usr/local/lib

You can use the command mv -if /usr/local/lib/liblog4cpp.* to copy your own project path  to your own project path; for example, I will create a lib folder in the project path and copy the log4cpp library just installed into this folder

The log4cpp header file path is in /usr/local/include/log4cpp

You can use the command mv -if /usr/local/include/log4cpp to copy your own project path  to your own project path; for example, I will create an include folder in the project path and copy the log4cpp header file just installed to in this folder

3. Test

#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(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;
}

Compile:

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

log4cpp1 : It is a static library of log4cpp.a. I changed the name to this (as you can see in the picture above), so that it can be linked to the static library normally; I don’t know why, but the compilation will report an error when linking the dynamic library.so, so I can only Link the static library to complete the compilation and operation.

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

 Four, log4cpp project usage

The project usage described below can be used in both Linux and Window environments! 

Generally speaking, logs are saved by independent folders. For convenience, the logs are directly saved in the directory at the same level as the main function. 

1. The configuration file uses log4cpp

Create a new project, and create a new file under the project path named: log.conf

Paste the following configuration into the log.conf file

#定义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

Create a new file MyLogger.h in the project

#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 MyLogger::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

Create a new file MyLogger.cpp in the project

#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 function test

#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("测试 warn.");
	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;
}

operation result:

 When running a project:

Linux compilation command: (the link is a static library)

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

2. Pure code uses log4cpp

The code I found on the Internet feels pretty good, I copied it and modified it, and I may use it like this in future projects after changing it! 

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 function test

#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;
}

operation result:

Linux compilation command: (the link is a static library)

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


V. Summary

The log must be used in the project. If you still don’t know how to use the log4cpp log after reading this blog, you can directly copy the above project code to your own project and use it directly!

Guess you like

Origin blog.csdn.net/cpp_learner/article/details/128738417