Linux和Windows(VS 2019)下安装使用Log4cpp日志库

embedded/2024/10/18 14:24:28/

目录

一、Log4cpp简介

二、Windows下的Log4cpp的安装

1、下载网址

2、解决方案

三、Vistual Studio中使用第三方库

1、拷贝对应下图路径下的include文件进入你的项目目录下面去,并将之前编译好的库文件也放在对应项目目录下面去。

2、打开你的项目,右键项目属性

3、选择常规选项卡,在附加包含目录里面输入你之前对应的log4cpp的include文件夹路径

5、选择链接器选项卡,进行附加依赖性,输入log4cpp.lib

6、测试程序

7、实际开发中可以用的,对于log4cpp单例类

四、Linux下的Log4cpp的安装

1、安装log4cpp,执行如下指令进行编译安装

2、包含头文件

3、初始化日志输出的目的地(appenders)

4、设置日志输出的格式

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

6、定义一个宏,方便我们更好的调用

7、使用宏定义记录日志

8、加载配置ini


一、Log4cpp简介

 Log4cpp是个基于LGPL的开源项目,移植自Java的日志处理跟踪项目log4j,并保持了API上的一致。其类似的支持库还包括Java(log4j),C++(log4cpp、log4cplus),C(log4c),python(log4p)等。

  Log4cpp有如下优点:

  •提供了可扩展的多种日志记录方式;

  •提供了NDC(嵌套诊断上下文),可用于多线程、多场景的跟踪调试;

  •提供了完整的日志动态优先级控制,可随时调整需要记录的日志优先级;

  •可通过配置文件完成所有配置并动态加载;

  •性能优秀,内存占用小,经过编译后的log4cpp.dll大小仅有160kb;

  •代码级的平台无关性,Log4cpp源代码经过编译后,适用于大多数主流的操作系统和开发工具;

  •概念清晰,学习和使用方便,熟练程序员一天之内即可很好地应用log4cpp进行开发。

二、Windows下的Log4cpp的安装

1、下载网址

http://log4cpp.sourceforge.net/icon-default.png?t=N7T8http://log4cpp.sourceforge.net/

选择图片红色圈出来的,进行下载。下载好后,解压文件并打开文件。双击打开下面的没事msvc10.sln

这里使用的是Visutal Studio 2019,注意这里的库只针对Visutal Studio 2017及其以上的IDE。点击确定

右击重新生成

报错

2、解决方案

1.双击log4cpp项目,在log4cpp项目下找到以下红色圈出来的

2.右键属性

3.在常规命令行里面输入以下命令

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

4.继续右击log4cpp项目,选择属性

5.选择C/C++下的预处理器,在预处理器定义里面的最下面添加,然后点击确定保存

HAVE_SNPRINTF

6.选择Log4cpp重新生成,发现程序成功运行

7.进入对应路径,查找我们编译好的库文件,红色圈出来的是对应查找路径,读者对应在该路径查找编译好的库文件,黄色是编译好的库文件

三、Vistual Studio中使用第三方库

1、拷贝对应下图路径下的include文件进入你的项目目录下面去,并将之前编译好的库文件也放在对应项目目录下面去。

2、打开你的项目,右键项目属性

3、选择常规选项卡,在附加包含目录里面输入你之前对应的log4cpp的include文件夹路径

4、选择链接器选项卡,附加库目录,输入对应的库文件路径(Debug路径下装的是编译好的库文件log4cpp.lib和log4cpp.dll)

5、选择链接器选项卡,进行附加依赖性,输入log4cpp.lib

6、测试程序

#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"void testOutputConsole()
{log4cpp::Appender* appender1 = new log4cpp::OstreamAppender("console", &std::cout);appender1->setLayout(new log4cpp::BasicLayout());	// 默认配置log4cpp::Category& root = log4cpp::Category::getRoot();root.setPriority(log4cpp::Priority::DEBUG); //低于WARN类型的日志不记录  NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT < FATAL = EMERGroot.addAppender(appender1);// 1.use of functions for logging messages	1.使用记录消息的函数root.debug("root debug");root.warn("root warn");root.error("root error");root.info("root info");// 2.printf-style for logging variables  2.printf风格的日志变量root.warn("%d + %d == %s ?", 1, 1, "two");// 3.use of streams for logging messages  3.使用流记录消息root << log4cpp::Priority::ERROR << "Streamed root error";root << log4cpp::Priority::INFO << "Streamed root info";// 4.or this way:  4.或者这样说:root.errorStream() << "Another streamed error";root.debugStream() << "Another streamed debug";log4cpp::Category::shutdown();
}

7、实际开发中可以用的,对于log4cpp单例类

头文件

#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

源文件

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

四、Linux下的Log4cpp的安装

1、安装log4cpp,执行如下指令进行编译安装

  • log4cpp的官网是:http://log4cpp.sourceforge.net/icon-default.png?t=N7T8http://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  
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头文件拷贝到此文件夹中

2、包含头文件

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

3、初始化日志输出的目的地(appenders

// 输出到std::cout
log4cpp::Appender *appender = new log4cpp::OstreamAppender("root", &std::cout);
// 输出到log文件
//log4cpp::Appender *appender = new log4cpp::FileAppender("root", "test.log");
appender有以下这些:
log4cpp::FileAppender // 输出到文件
log4cpp::RollingFileAppender // 输出到回卷文件,即当文件到达某个大小后回卷
log4cpp::OstreamAppender // 输出到一个ostream类
log4cpp::RemoteSyslogAppender // 输出到远程syslog服务器
log4cpp::StringQueueAppender // 内存队列
log4cpp::SyslogAppender // 本地syslog
log4cpp::Win32DebugAppender // 发送到缺省系统调试器
log4cpp::NTEventLogAppender // 发送到win 事件日志

  上文,我们说过日志输出到终端或者文件中实际上是很慢的,会引起IO中断,所以我们可以输出到内存里StringQueueAppender,然后从StringQueueAppender输出到其它地方,这样我们的线程执行是比较高效的。

4、设置日志输出的格式

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

日志输出格式控制有: PatternLayout supports following set of format characters:
%% - a single percent sign
%c - the category
%d - the date\n Date format: The date format character may be followed by a date format specifier enclosed between braces. For example, %d{%\H:%M:%S,%l} or %d{%\d %m %Y %H:%\M:%S,%l}. If no date format specifier is given then the following format is used: "Wed Jan 02 02:03:55 1980". The date format specifier admits the same syntax as the ANSI C function strftime, with 1 addition. The addition is the specifier %l for milliseconds, padded with zeros to make 3 digits.
%m - the message
%n - the platform specific line separator
%p - the priority
%r - milliseconds since this layout was created.
%R - seconds since Jan 1, 1970
%u - clock ticks since process start
%x - the NDC
%t - thread name
By default, ConversionPattern for PatternLayout is set to "%m%n".

5、设置类别输出的(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。日志级别的意思是低于该级别的日志不会被记录。

6、定义一个宏,方便我们更好的调用

#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << __FILE__ << " " << __LINE__ << ": "
当然也可以使用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();...

7、使用宏定义记录日志

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的属性
log4cpp.rootCategory=DEBUG, RootLog#定义RootLog属性
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

8、加载配置ini

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;}m_Category = &log4cpp::Category::getRoot();return TRUE;
}


http://www.ppmy.cn/embedded/50718.html

相关文章

AndroidStudio无法新建Java工程解决办法

我用的 AS 版本是 Android Studio Giraffe | 2022.3.1 Build #AI-223.8836.35.2231.10406996, built on June 29, 2023 以往新建工程都是 New project >> Empty Activity &#xff0c; 有个选择 Java 还是 Kotlin 语言的选项&#xff0c; 之后会默认生成一个 MainActi…

[保姆级教程]uniapp实现底部导航栏

文章目录 前置准备工作安装HBuilder-X新建uniapp项目教程使用HBuilder-X启动uniapp项目教程 实现底部导航栏package.json中配置导航栏详细配置内容 前置准备工作 安装HBuilder-X 详细步骤可看上文》》 新建uniapp项目教程 详细步骤可看上文》》 使用HBuilder-X启动uniapp项…

SQL Server几种琐

SQL Server 中的锁类型主要包括以下几种&#xff0c;它们用于控制并发访问和数据一致性&#xff1a; 1. 共享锁&#xff08;Shared Lock&#xff0c;S 锁&#xff09;&#xff1a; - 用于读取操作&#xff08;如 SELECT 语句&#xff09;。 - 允许多个事务同时读取同一资…

使用MyBatisPlus进行字段的自动填充

使用MyBatisPlus进行字段的自动填充 需求场景 当我们往数据库里面插入一条数据&#xff0c;或者是更新一条数据时&#xff0c;一般都需要标记创建时间create_time和更新时间update_time的值&#xff0c;但是如果我们每张表的每个请求&#xff0c;在执行sql语句的时候我们都手…

前端RSA加解密(支持超长分段)

过程不复杂, 只是网上结合后端的RSA加解密资料参差不齐, 比较零散, 而且大多博文都是基于最原始的RSA加解密, 当加解密参数过长的时候, 会报[Message too long for RSA] 解决方案, 找了一圈, 都不大完整, 完整的又很复杂, 加了一堆方法, 看着都头疼! 其实加解密的本质都一样的,…

戏剧之家杂志戏剧之家杂志社戏剧之家编辑部2024年第14期目录

文艺评论 南戏瓯剧跨文化传播研究 陈晓东;高阳;许赛梦; 3-7 论互联网时代的戏剧传播与批评——以西法大剧社和南山剧社为例 邬慧敏; 8-10 “左手荒诞&#xff0c;右手温情”——《西西弗神话》在戏剧《第七天》中的接受探究 赵稳稳; 11-13 戏剧研讨《戏剧之家》投稿…

如何翻译和本地化游戏?翻译访谈

如何翻译和本地化游戏&#xff1f;这个过程的技术细节有哪些&#xff1f;游戏翻译不同于电影翻译。Logrus IT游戏本地化部门负责人阿列克谢费奥多罗夫&#xff08;Alexey Fedorov&#xff09;在接受RUDN语言学系外语系教授和研究人员的采访时谈到了这一点&#xff0c;他是由尤利…

github ssh key的SHA256是什么

github ssh key的SHA256是什么 怎么知道github上自己的公钥指纹和本地的公钥是否一致&#xff1f; 计算方法如下&#xff1a; cat .ssh/id_rsa.pub |awk { print $2 } | # Only the actual key data without prefix or commentsbase64 -d | # decode as base64s…