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

目录

一、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.mzph.cn/bicheng/30733.shtml

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

相关文章

nacos 配置修改.代码实时刷新

再类上用 RefreshScope 更新Value(“${uniqlo.privacy.url:https://wsurl.cc/yourls-api.php}”) private String shortLinkGenerateUrl;的数据可以实时更新 2.再配置类上次用 ConfigurationProperties(prefix “test.privacy”) 和nacos的配置一直 Data Component Configu…

华为云EI生态

1、人工智能技术趋势 2、华为AI发展思路 3、华为云EI&#xff1a;让企业更智能 4、华为云服务全景图 5、基础平台类服务 6、MLS:解决特性到模型应用的完整过程 7.DLS 8.GES超大规模一体化图分析与查询 9、EI视觉认知 10、EI语音语义 11、OCR&#xff1a;提供高精度光学文字自动…

在Apache Flink中,Java UDF(用户自定义函数)的使用涉及几个关键步骤

在Apache Flink中&#xff0c;Java UDF&#xff08;用户自定义函数&#xff09;的使用涉及几个关键步骤&#xff1a;创建UDF类、注册UDF、以及在Flink作业中使用UDF。以下是一些具体的使用案例&#xff1a; ### 1. 创建项目和配置POM 首先&#xff0c;创建一个Maven项目&…

Kubernetes Pod 健康问题:CrashLoopBackoff

搭建 Prometheus 的过程中&#xff0c;alertmanager-main 的 Status状态为CrashLoopBackoff. 我的alertmanager-main svc下有三个alertmanager-main-0 alertmanager-main-1 alertmanager-main-2 1.检查状态 kubectl describe pod alertmanager-main-0 -n monitoring输出的关键…

C++初学者指南第一步---9.函数

C初学者指南第一步—9.函数 文章目录 C初学者指南第一步---9.函数1.输入和输出1.1第一个例子1.2返回类型1.3函数参数常量参数默认值参数 1.4函数重载 2.函数执行2.1递归2.2 声明和定义 3.函数设计3.1约定3.2 特性[[nodiscard]] &#xff08;C17&#xff09;3.3 不抛出异常保证&…

项目实战—springboot整合微信、支付宝NATIVE扫码支付

目录 微信支付申请微信支付添加依赖WechatConstant配置httpClient生成支付二维码支付成功回调订单退款 支付宝支付申请支付宝支付添加依赖配置AlipayClient生成支付二维码支付成功回调订单退款 可能出现的问题 微信支付 申请微信支付 接入微信支付前需要再微信开放平台、公众…

【Python驯化-01】python中set去重数据每次结果不一致问题解决

【Python驯化-01】python中set去重数据每次结果不一致问题解决 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注…

信息安全系列课程之网络空间测绘与态势感知技术揭秘(一)

今天&#xff0c;我们来讲一下网络安全&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 目前&#xff0c;在信息安全攻防领域&#xff0c;主要分为了两个技术发展方向&#xff0c;分别为渗透测试&#xff08;红队技术&#xff09; 和 安全运维&a…

考研计组chap2数据的表示和运算

3一、进位计数制 1.r进制 第i位表示r进制的权为i 2.进制转换 &#xff08;1&#xff09;r->10 对应位置数*权值 &#xff08;2&#xff09;2 -> 16 or 8 每三位2进制数可表示1位16进制 每四位2进制数可表示1位16进制 so 分开之后转为16进制即可 eg&#xff1a;1…

江苏省SAP代理商之选:无锡哲讯为企业信息化管理开启新篇章

江苏省&#xff0c;作为中国东部沿海的经济重镇&#xff0c;拥有众多行业领先企业。随着数字化转型的浪潮&#xff0c;SAP代理商在这片热土上扮演着至关重要的角色。无锡哲讯智能科技有限公司&#xff08;iP-Solutions&#xff09;&#xff0c;作为SAP在华东地区的金牌合作伙伴…

基于51单片机恒温箱设计

基于51单片机恒温箱设计 &#xff08;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 本设计由STC89C52单片机电路数字温度传感器DS18B20电路按键电路蜂鸣器报警电路继电器控制电路LCD1602液晶显示电路电源电路组成。 1.LCD1602液…

Spring源码中是如何使用设计模式六大原则的

设计模式的六大原则&#xff0c;通常指的是SOLID原则&#xff0c;它们是面向对象设计中用于提高代码可维护性、灵活性和可扩展性的五个指导原则&#xff0c;学习六大原则&#xff0c;可以让你的代码变得高级而优雅&#xff0c;今天的内容 V 哥结合 Spring源码中如何运用六大原则…

偏微分方程算法之抛物型方程差分格式编程示例四(Richardson外推)

目录 一、研究问题 二、C++代码 三、结果分析 一、研究问题 已知其精确解为。分别取以下三种步长: ①

流程引擎框架

SpiffWorkflow python 流程引擎框架哪个好 Camunda 核心表介绍 https://zhuanlan.zhihu.com/p/645786758 camunda流程引擎基本使用&#xff08;笔记&#xff09; https://blog.csdn.net/weixin_46949627/article/details/129255647 python连接FastDfs服务封装类 https://blog.c…

树形dp,CF 1926 G - Vlad and Trouble at MIT

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - G - Codeforces 二、解题报告 1、思路分析 考虑每个结点最终状态只可能为和P连通或者和S连通 我们我们自然而然的将问题划分为这样的状态 f[x][0]代表结点x和P连通需要割掉最少的边 f[x][1]代…

Windows Server配置NFS,做ESXI共享存储

1:登录wINDOWS系统&#xff0c;点击添加角色和功能。 2:根据向导提示&#xff0c;一路下一步。在服务器角色中选择文件和存储服务器在文件和iSCSI服务中勾选NFS服务器。 3&#xff1a;按照提示一路下一步&#xff0c;安装NFS。 4&#xff1a;安装完成后关闭安装界面。 5&#x…

代码随想录算法训练营第六十五天 | 岛屿数量 深搜、岛屿数量 广搜、岛屿的最大面积

岛屿数量 深搜 题目链接&#xff1a;99. 岛屿数量 文字讲解&#xff1a;99. 岛屿数量 | 代码随想录 解题思路 本题已经说明&#xff0c;只有水平方向和竖直方向才能组成岛屿 本题思路&#xff0c;是遇到一个没有遍历过的节点陆地&#xff0c;计数器就加一&#xff0c;然后把…

为电脑小白推荐的5款实用工具软件

​ 电脑上的各类软件有很多&#xff0c;除了那些常见的大众化软件&#xff0c;还有很多不为人知的小众软件&#xff0c;专注于实用功能&#xff0c;简洁干净、功能强悍。 1.磁盘空间分析——TreeSize Free ​ TreeSize Free是一款免费的磁盘空间分析工具&#xff0c;能够扫描…

Sip协议(四) -注册流程

Sip协议(四) -注册流程 本文主要介绍下sip协议中, agent的注册流程. 一: 流程图 简单的流程图如下: agent发起注册fs 返回401 ,并携带WWW-Authenticateagent第二次发起注册,增加Authorizationfs返回授权成功, 或者失败. 二: sip流程 发起注册REGISTER 首先agent发起注册请求…

重磅!鹅厂大牛带你30分钟玩转AI智能结对编程!

在大模型时代&#xff0c;人工智能技术的突破性进展正重塑着软件开发的面貌。AI的融入不仅优化了代码编写过程&#xff0c;更开启了智能编程的新纪元&#xff0c;为开发者带来了前所未有的工作效率和创新可能。AI结对编程不仅能够极大提升研发效率&#xff0c;还能通过智能分析…