基于log4cpp封装日志类

2024-03-14 14:20
文章标签 日志 封装 log4cpp

本文主要是介绍基于log4cpp封装日志类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、log4cpp的使用

1. 下载log4cpp

log4cpp官方下载地址

2. 安装log4cpp

第一步:解压 tar zxvf log4cpp-1.1.4.tar.gz
在这里插入图片描述

第二步:进入log4cpp文件夹并执行 ./configure
在这里插入图片描述

tips:如果是ARM架构的芯片可能会失败,如下面这种情况,重新执行 ./configure --build=aarch64-unknown-linux-gnu 即可
在这里插入图片描述

第三步:执行 make
第四步:执行 make check
第五步:执行 make install

3. 查看是否安装成功

安装成功后,在/usr/local/include路径下会多一个log4cpp的文件夹
在这里插入图片描述

4. 更新动态库路径缓存

!!! 不更新缓存,会导致编译时找不到库文件;请执行命令sudo ldconfig
在这里插入图片描述

5. 编写测试代码
#include <iostream>
#include <log4cpp/Category.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/Priority.hh>using namespace std;
using namespace log4cpp;int main(void) {OstreamAppender *osAppender = new OstreamAppender("console", &cout);osAppender->setLayout(new BasicLayout());Category &root = Category::getRoot();root.addAppender(osAppender);root.setPriority(Priority::DEBUG);root.error("this is a error");root.warn("this is a warn");root.shutdown();return 0;
}
6. 编译代码并运行测试

g++ test.cc -llog4cpp
在这里插入图片描述

二、自定义封装的MyLogger类

需要注意的坑: 由于__FILE__、__func____LINE__是编译器提供的预处理宏,它们是在预处理阶段就被替换掉了,如果不封装成宏函数会导致打印的行号等信息不准。

#include <iostream>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Priority.hh>
#include <log4cpp/Category.hh>using namespace std;
using namespace log4cpp;// 定义拼接前缀函数
#define ConcatPrefix(str) (                     \string("[").append(__FILE__).append(",")    \.append(__func__).append(",")               \.append(to_string(__LINE__)).append("]: ")  \.append(str) )// 定义LogWarn宏函数
#define LogWarn(str) {                              \MyLogger *log = MyLogger::getInstance();        \log->warn(ConcatPrefix(str).c_str());           \
}
// 定义LogError宏函数
#define LogError(str) {                             \MyLogger *log = MyLogger::getInstance();        \log->error(ConcatPrefix(str).c_str());          \
}
// 定义LogDebug宏函数
#define LogDebug(str) {                             \MyLogger *log = MyLogger::getInstance();        \log->debug(ConcatPrefix(str).c_str());          \
}
// 定义LogInfo宏函数
#define LogInfo(str) {                              \MyLogger *log = MyLogger::getInstance();        \log->info(ConcatPrefix(str).c_str());           \
}class MyLogger
{
public:static MyLogger *getInstance();static void destroyInstance();void warn(const char *msg);void error(const char *msg);void debug(const char *msg);void info(const char *msg);private:MyLogger();~MyLogger();Category &category;static MyLogger *pInstance;    
};
// 初始化静态对象
MyLogger *MyLogger::pInstance = nullptr;
// 无参构造函数
MyLogger::MyLogger() :category(Category::getInstance("MyLogger")) {// 定义输出到命令行的AppenderOstreamAppender *pConmandLineAppender = new OstreamAppender("comandLine", &cout); // 定义输出到回卷文件的AppenderRollingFileAppender *pRollingAppender = new RollingFileAppender("rollingFile", "mylogger.log", 1024, 3);// 定义日志样式PatternLayout *layout1 = new PatternLayout();layout1->setConversionPattern("%d [%p] %m%n");PatternLayout *layout2 = new PatternLayout();layout2->setConversionPattern("%d [%p] %m%n");// 绑定输出样式pConmandLineAppender->setLayout(layout1);pRollingAppender->setLayout(layout2); // 设置日志过滤等级 category.setPriority(Priority::DEBUG);    // 设置输出位置category.setAppender(pConmandLineAppender);category.setAppender(pRollingAppender);
}
/*** 获取单例对象 
*/
MyLogger *MyLogger::getInstance() {if (pInstance == nullptr) {pInstance = new MyLogger();}return pInstance;
}
/*** 销毁单例对象
*/
void MyLogger::destroyInstance() {if (pInstance != nullptr) {delete pInstance;pInstance = nullptr;}
}
/*** 析构函数
*/
MyLogger::~MyLogger() {category.shutdown();cout << "~MyLogger()" << endl;
}
/*** warn
*/
void MyLogger::warn(const char *msg) {category.warn(msg);
}
/*** error
*/
void MyLogger::error(const char *msg) {category.error(msg);
}
/*** debug
*/
void MyLogger::debug(const char *msg) {category.debug(msg);
}
/*** info
*/
void MyLogger::info(const char *msg) {category.info(msg);
}

三、MyLogger的使用示例

方式一:单例对象

void test0()
{MyLogger *log = MyLogger::getInstance();log->warn(ConcatPrefix("The log is warn message").c_str());log->error(ConcatPrefix("The log is error message").c_str());log->debug(ConcatPrefix("The log is debug message").c_str());log->info(ConcatPrefix("The log is info message").c_str());MyLogger::destroyInstance();
}

方式二:宏函数

void test1() 
{LogWarn("The log is warn message");LogError("The log is error message");LogDebug("The log is debug message");LogInfo("The log is info message");
}

生成效果:
在这里插入图片描述

这篇关于基于log4cpp封装日志类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

SpringBoot如何使用TraceId日志链路追踪

《SpringBoot如何使用TraceId日志链路追踪》文章介绍了如何使用TraceId进行日志链路追踪,通过在日志中添加TraceId关键字,可以将同一次业务调用链上的日志串起来,本文通过实例代码... 目录项目场景:实现步骤1、pom.XML 依赖2、整合logback,打印日志,logback-sp

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

我在移动打工的日志

客户:给我搞一下录音 我:不会。不在服务范围。 客户:是不想吧 我:笑嘻嘻(气笑) 客户:小姑娘明明会,却欺负老人 我:笑嘻嘻 客户:那我交话费 我:手机号 客户:给我搞录音 我:不会。不懂。没搞过。 客户:那我交话费 我:手机号。这是电信的啊!!我这是中国移动!! 客户:我不管,我要充话费,充话费是你们的 我:可是这是移动!!中国移动!! 客户:我这是手机号 我:那又如何,这是移动!你是电信!!

JavaSE——封装、继承和多态

1. 封装 1.1 概念      面向对象程序三大特性:封装、继承、多态 。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节 。     比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器, USB 插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU 、显卡、内存等一些硬件元件。

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h#pragma once#include "HashTable.h"

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

Detectorn2预训练模型复现:数据准备、训练命令、日志分析与输出目录

Detectorn2预训练模型复现:数据准备、训练命令、日志分析与输出目录 在深度学习项目中,目标检测是一项重要的任务。本文将详细介绍如何使用Detectron2进行目标检测模型的复现训练,涵盖训练数据准备、训练命令、训练日志分析、训练指标以及训练输出目录的各个文件及其作用。特别地,我们将演示在训练过程中出现中断后,如何使用 resume 功能继续训练,并将我们复现的模型与Model Zoo中的

SSM项目使用AOP技术进行日志记录

本步骤只记录完成切面所需的必要代码 本人开发中遇到的问题: 切面一直切不进去,最后发现需要在springMVC的核心配置文件中中开启注解驱动才可以,只在spring的核心配置文件中开启是不会在web项目中生效的。 之后按照下面的代码进行配置,然后前端在访问controller层中的路径时即可观察到日志已经被正常记录到数据库,代码中有部分注释,看不懂的可以参照注释。接下来进入正题 1、导入m

多数据源的事务处理总是打印很多无用的log日志

之前做了一个项目,需要用到多数据源以及事务处理,在使用事务处理,服务器总是打印很多关于事务处理的log日志(com.atomikos.logging.Slf4jLogger),但是我们根本不会用到这些log日志,反而使得查询一些有用的log日志变得困难。那要如何屏蔽这些log日志呢? 之前的项目是提高项目打印log日志的级别,后来觉得这样治标不治本。 现在有一个更好的方法: 我使用的是log