6.8日志系统

当做大型项目的时候,出了bug可能需要借助于日志检查,小项目一般是打断点。

服务器是一直在运行的,不能停止,可以借助于日志检查错误。

日志分为两种:业务级别的日志(供用户分析业务过程),系统级别的日志(用来供程序员分析)

因为日志文件占据的存储空间很大,会打印很多的信息,难以检查错误信息,所以需要进行合理的设计。

本章节主要学习日志记录系统log4cpp。

日志系统包含四类信息:分别是:记录器、过滤器、格式化器、输出器四部分。

记录器:记录信息的来源,时间,优先级,位置。

过滤器:并不是把所有的        信息都保存下来。有时候把不重要的信息过滤掉。

格式化器:将日志信息设置布局,这样更方便查看。

输出器:设置日志目的地,例如存储到文件。

ostreamAppender是一个Appender的派生类

基类指针指向派生类对象

基类引用访问派生类对象(std::getline返回一个istream,使之与iftream绑定)

ostreamAppender的第一个参数只是给程序员一个提醒内容无关紧要,第二个参数是ostream* 这个地方就是使用了&cout,当然也可以绑定文件流也就是派生类。

basiclayout 将距离1970年。。有多少秒,所以说我们在自己用的时候不用这个。

root节点是通过单例模式进行创建在栈上的对象

当日志优先级比系统优先级要低就直接过滤掉。

然后就是创建叶子级别的catgr对象,继承父节点的优先级和目的地

如果没有创建根对象,直接使用getInstance创建叶对象,会先隐式地创建一个Root对象。

通过.来显示分级

后面的sub1代表日志的来源,也就是输出在终端的字符串内容

如果修改节点的写入目的地,那么会将信息写入到自定义的文件中。

如果是root对象调用的就只是保存到root的目的地,如果(子节点继承根节点目的地时)是sub子节点对象那么根节点和子节点的目的地都保存。

也可以设置不同目的地不同日志文件系统级别。

有四种形式可以写入终端

直接调用函数

//sub1.error()

函数+流的方式

#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/Priority.hh"

//Category 日志记录器                                                                          
//Appender 表示输出器目的地
//Layout 表示显示格式格式化器
//Priority 表示优先级过滤器

int main(int argc, char** argv) {
    log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);
    //OstreamAppender 是Appender的派生类
    //其中的第一个参数只是给用户看的,内容是什么无关紧要,“console”表示控制台也就是屏幕终端显示
    //第二个参数很重要表示将打印信息输出到的位置
    appender1->setLayout(new log4cpp::BasicLayout());
    //本行命令表示的是输出格式BasicLayout表示的是将时间输出为从19701月1号开始的的秒数
    //一般我们不会使用这个,因为秒数不能很好的辨识时间

    log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log");
    //同上只是表示将输出写到日志文件program.log中
    //注意这样是以追加的方式写入
    appender2->setLayout(new log4cpp::BasicLayout());
    
    log4cpp::Category& root = log4cpp::Category::getRoot();
    //创建category对象的时候首先先创建一个单例的root对象,
    //并在下面的语句中设置根对象的系统级别以及输出目的地
    root.setPriority(log4cpp::Priority::WARN);
    root.addAppender(appender1);

    //设置叶节点,前面的&引用sub1就是表示返回一个在栈上的这个节点,                        
    //后面的这个sub1就是用于打印的时候显示
    //并且设置目的输出地,当然也可以额外设置输出的系统等级,如果都不设置的话都是跟随根节点
    //当然可以不创建root节点直接创建叶节点,系统会自动隐式创建一个根节点
    log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));
//og4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1.sub11"));
//这样就可以在sub1下面实现再连接一个sub11叶节点
    sub1.addAppender(appender2);

    // use of functions for logging messages
    root.error("root error");//ok等级大于warn会被输出到根节点设置的屏幕
    root.info("root info");//error等级低
    sub1.error("sub1 error");//ok等级足够,会被同时打印到根节点设置的屏幕和叶节点设置的文件
    sub1.warn("sub1 warn");//ok等级足够会被输出到文件中去和屏幕中

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

    // use of streams for logging messages
    root << log4cpp::Priority::ERROR << "Streamed root error";
    root << log4cpp::Priority::INFO << "Streamed root info";
    sub1 << log4cpp::Priority::ERROR << "Streamed sub1 error";
    sub1 << log4cpp::Priority::WARN << "Streamed sub1 warn";
 
     // or this way:
     root.errorStream() << "Another streamed error";
 
     return 0;
 }

【注意】这个地方可以将前面的一大长串的变量设置为auto类型。这个地方更加深入了解auto,auto是可以推导出变量类型,也可以推导出指针类型。但是auto不能推导出引用类型。

log4cpp官网 Log for C++ Project

日志目的地

主要关注三个目的地类分别是

• OstreamAppender C++通用输出流(如 cout)

• FileAppender 写到本地文件中

• RollingFileAppender 写到回卷文件中

  • OstreamAppender的构造函数传入两个参数:目的地名(随便写)、输出流指针
  • FileAppender的构造函数传入两个参数:目的地名、保存日志的文件名(后面两个参数使用默认值即可,分别表示以结尾附加的方式的保存日志,当前用户读写-其他用户只读)

RollingFileAppender使用场景就是比如说是因为系统不断产生文件,如果对于存储空间不加限制会大量的占用空间,所以说划分一块区域保存最新的一部分日志文件

【注意】RollingFileAppender构造函数的参数如上图,其中要注意的是回卷文件个数,如果这一位传入的参数是9,那么实际上会有10个文件保存日志。

回卷的机制是:先生成一个wd.log文件,该文件存满后接着写入日志,那么wd.log文件改名为wd.log.1,然后再创建一个wd.log文件,将日志内容写入其中,wd.log文件存满后接着写入日志,wd.log.1文件改名为wd.log.2,wd.log改名为wd.log.1,再创建一个wd.log文件,将最新的日志内容写入。以此类推,直到wd.log和wd.log.1、wd.log.2、... wd.log.9全都存满后再写入日志,wd.log.9(其中实际上保存着最早的日志内容)会被舍弃,编号在前的回卷文件一一进行改名,再创建新的wd.log文件保存最新的日志信息。

日志布局

本来的默认布局时BasicLayout,这种方式是表示距离1970.1.1的秒数不方便观察。

因此调用的时候可以使用PatrrenLayout对象来定制化格式

设置日志布局的方式

PatternLayout * ptn1 = new PatternLayout();
ptn1->setConversionPattern("%d %c [%p] %m%n"); 

该字符串的含义:

%d %c [%p] %m%n

时间 模块名 优先级 消息本身 换行符

【注意】日志系统有多个日志目的地的时候,每一个目的地Appender都需要设置一个布局Layout(一对一的关系)

日志记录器

创建category对象时,可以先使用getRoot创建root模块对象,对于root模块对象设置优先级和目的地。

再用getInstance创建叶模块,叶模块会继承root模块的优先级和目的地,当然也可以重新设置

如果没有创建根对象直接使用getInstance创建叶对象,会隐式创建一个跟对象

//官网示例分开创建的方式
log4cpp::Category& root = log4cpp::Category::getRoot();
root.setPriority(log4cpp::Priority::WARN);
root.addAppender(appender1);

log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1")); //传入的字符串sub1就会是日志中记录下的日志来源
sub1.addAppender(appender2);
//直接创建叶对象的方式
log4cpp::Category& sub1 = log4cpp::Category::getRoot().getInstance("salesDepart"); //记录的日志来源会是salesDepart
sub1.setPriority(log4cpp::Priority::WARN);
sub1.addAppender(appender1);

前面的sub1本质是绑定到category的引用,在代码中可以使用sub1设置优先级添加目的地以及记录日志。

getIInstance中的参数salesDepart表示的是日志信息中记录的category的名称,也就是打印信息中的日志来源对应%c

在使用的时候这两者的名称取同一个名称,可以清楚该日志是来自于salesDepart这个模块

日志优先级

主要注意两个优先级分别是日志记录器的优先级(即系统优先级)和日志的优先级(某一条日志信息的优先级)。

只有当日志信息的优先级高于等于系统的优先级的时候,这一条日志信息才会被打印出来,否则这条日志会被过滤掉。

class LOG4CPP_EXPORT Priority {
public:
	typedef enum {
			EMERG = 0,
			FATAL = 0,
			ALERT = 100,
			CRIT = 200,
			ERROR = 300,
			WARN = 400,
			NOTICE = 500,
			INFO = 600,
			DEBUG = 700,
			NOTSET = 800 //这个不代表可以使用的优先级
	} PriorityLevel;
	//......
};  //数值越小,优先级越高;数值越大,优先级越低

日志布局:

PatternLayout * ptn1 = new PatternLayout();
ptn1->setConversionPattern("%d %c [%p] %m%n"); 

%d %c [%p] %m%n

时间 模块名 优先级 消息本身 换行符

%d设置时间地格式

头文件:输出到终端

使用自定义格式地头文件

记录器,过滤器

【了解】如果是使用根节点的话那么在布局中%c位置就不会有打印信息。

【重点】前面的sub1是用来进行使用接下来的绑定操作,在后面的sub1用来显示打印信息,同时还有显示父子叶节点关系“(后面的)sub1.sub11”。注意这个地方是用的后面的sub1!!子节点的信息不仅会打印到自己的输出位置中,还需要输出到父节点的输出目的地中。

表示通过getRoot创建根节点,通过getInstance创建叶节点。

也可以不加上getroot这样的话就就隐式的创建根节点。

这样做的话可能需要再额外定义一个root节点才能再继续进行操作根节点,

3.结束以后基本就将所有的信息绑定在一起

【了解】1.log4cpp在设计的时候有一个bug就是enum设计两个类型都是一个0表示都会视为下面那个fatal,反正这两种都是需要立即进行执行

2. 了解官网给的版本就是没有shutdown函数,但是可能也不会有内存泄漏,也有可能泄漏进行了优化。

日志目的地

【注意】shutdown回收资源,对于delete的封装,无论在日志系统中前面new多少次的话。

【重点】需要将目的地和格式绑定,然后将记录器和目的地绑定,记得两次绑定

布局对象和目的地对象需要一一对应,这样的话不会出现段错误

创建目的地的对象是文件对象的时候,可以有两种方式:

一种是通过oftream ofs。绑定在原本的&cout位置。当然也可以使用fileAppender,直接相应的位置输入文件名字符串

【注意】日志文件在fileAppender方式下,是以追加的方式进行添加

日志文件在OstreamAppender方式下,是以截断添加的方式添加

还有一种文件目的地,就是回卷文件

就是将空间分为几个文件,然后不断循环保存最新的内容

例如:下例中就是最新的文件一直都是wd.log

先生成一个wd.log文件,该文件存满后接着写入日志,那么wd.log文件改名为wd.log.1,然后再创建一个wd.log文件,将日志内容写入其中,wd.log文件存满后接着写入日志,wd.log.1文件改名为wd.log.2,wd.log改名为wd.log.1,再创建一个wd.log文件,将最新的日志内容写入。以此类推,直到wd.log和wd.log.1、wd.log.2、... wd.log.9全都存满后再写入日志,wd.log.9(其中实际上保存着最早的日志内容)会被舍弃,编号在前的回卷文件一一进行改名,再创建新的wd.log文件保存最新的日志信息。

【注意】回卷文件的个数如果是是5,实际的文件的个数就是6

log4cpp主要是使用category这个引用对象,所以说在private的位置保存一个category的引用。

【重点】获取文件名称和调用函数以及所在的列数的时候,使用的时候c的宏,这个处理是是在预处理阶段来实现的,所以说这个拼接字符串的操作是不能使用普通的函数的这样的话只会显示这个定义拼接字符串函数的文件和行号。可能会想到inline进行替换但是是在编译阶段实现使用的_FILE_是在,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/704840.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pioneer电源维修PM33213BP-10P-1-6PH-H

开关电源出现不启振的时候&#xff0c;我们通常需要查看开关频率是否正确、保护电路是否断路、电压反馈电路、电流反馈电路又没问题&#xff0c;开关管是否击穿等。 电源维修实践中&#xff0c;有许多开关电源采用UC38系列8脚PWM组件&#xff0c;大多数电源不能工作都是因为电…

基于单片机的多功能智能小车设计

第一章 绪论 1.1 课题背景和意义 随着计算机、微电子、信息技术的快速发展,智能化技术的发展速度越来越快,智能化与人们生活的联系也越来越紧密,智能化是未来社会发展的必然趋势。智能小车实际上就是一个可以自由移动的智能机器人,比较适合在人们无法工作的地方工作,也可…

JVM产生FullGC的原因有哪些?

JVM产生FullGC的原因有哪些&#xff1f; 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;垃圾回收&#xff08;Garbage Collection&#xff0c;简称GC&#xff09;是一个非常重要的机制。GC的目的是自动管理内存&#xff0c;回收不再使用的对象&#xff0c;防止内存泄…

python数据分析-房价数据集聚类分析

一、研究背景和意义 随着房地产市场的快速发展&#xff0c;房价数据成为了人们关注的焦点。了解房价的分布特征、影响因素以及不同区域之间的差异对于购房者、房地产开发商、政府部门等都具有重要的意义。通过对房价数据的聚类分析&#xff0c;可以深入了解房价的内在结构和规…

Android低代码开发 - 直接创建一个下拉刷新列表界面

看了我Android低代码开发 - 让IDE帮你写代码这篇文章的小伙伴&#xff0c;大概都对Dora全家桶开发框架有基本的认识了吧。本篇文章将会讲解如何使用dora-studio-plugin快捷创建一个下拉刷新列表界面。 效果演示 这样直接通过图形界面的方式就创建好了下拉刷新上拉加载空态界面…

如何高效管理和监控 Elasticsearch 别名及索引?

0、引言 在 Elasticsearch 项目中&#xff0c;管理和监控索引是开发者的一项重要任务。 尤其是当我们需要在项目的管理部分展示索引和别名的统计信息时&#xff0c;了解如何有效地列出这些别名和索引显得尤为重要。 本篇博客将介绍几种在 Elasticsearch 中列出别名和索引的方法…

用表头设置控制表格内列的排序和显示隐藏

项目背景 : react ant 需求 : 点击表头设置弹窗 , 拖拽可控制外部表格列的排序 , 开关可控制外部表格列的显示和隐藏 实现效果如下 :注意 : 1. 拖拽效果参考了ant-table中的拖拽效果(这块代码放最后) 2. 后台反了json格式(用is_show控制显示和隐藏 , 我给他传…

【应用案例】如何解决无人驾驶车辆的动力转向问题

埃尔朗根-纽伦堡大学名称为高能赛车运动队(High-Octane Motorsports e.V.)的学生方程式车队都设计、构建和制造具有创新意义且独特的赛车。然后&#xff0c;他们将参加三种不同类别的大学生方程式比赛&#xff1b;该项赛事中的参赛队伍来自于世界各地。 电动、无人驾驶和燃油车…

17.路由配置与页面创建

路由配置与页面创建 官网&#xff1a;https://router.vuejs.org/zh/ Vue Router 和 组合式 API | Vue Router (vuejs.org) 1. 修改index.ts import { RouteRecordRaw, createRouter, createWebHistory } from "vue-router"; import Layout from /layout/Index.vueco…

python长方形周长面积 2024年3月青少年编程电子学会python编程等级考试二级真题解析

目录 python长方形周长面积 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python长方形周长面积 2024年3月 python编程等级考试级编程题 一、…

linux系统宝塔服务器temp文件夹里总是被上传病毒php脚本

目录 简介 上传过程 修复上传漏洞 tmp文件夹总是被上传病毒文件如下图: 简介 服务器时不时的会发送短信说你服务器有病毒, 找到了这个tmp文件, 删除了之后又有了。 确实是有很多人就这么无聊, 每天都攻击你的服务器。 找了很久的原因, 网上也提供了一大堆方法,…

天锐绿盾 | 无感知加密软件、透明加密系统、数据防泄漏软件

摘要&#xff1a;文件加密软件,包含禁止非授权的文件泄密和抄袭复制解决方案即使被复制泄密都是自动加密无法阅读,透明加密,反复制软件,内网监控,文件加密,网络安全方案,透明文件加密,加密文件,图纸加密,知识产权保护,加密数据; 通过绿盾信息安全管理软件&#xff0c;系统在不改…

2024/06/13--代码随想录算法2/17| 62.不同路径、63. 不同路径 II、343. 整数拆分 (可跳过)、96.不同的二叉搜索树 (可跳过)

62.不同路径 力扣链接 动态规划5步曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义&#xff1a; dp[i][j] &#xff1a;表示从&#xff08;0 &#xff0c;0&#xff09;出发&#xff0c;到(i, j) 有dp[i][j]条不同的路径。确定递推公式&#xff0c;dp[i][j] d…

Java——递归

一、递归介绍 1、什么是递归 递归在Java编程中是指一个方法调用自身的编程技巧。 public static void foo() {//...foo();//方法调用自身//...} 2、递归用于什么场景 递归是一种常见的算法设计方法&#xff0c;特别适用于解决那些可以分解为相似子问题的问题。常见的递归问…

诺派克ROPEX控制器维修RES-5008 RES-5006

德国希尔科诺派克ROPEX热封控制器维修型号包括&#xff1a;RES-401&#xff0c;RES-402&#xff0c;RES-403&#xff0c;RES-406&#xff0c;RES-407&#xff0c;RES-408&#xff0c;RES-409&#xff0c;RES-420&#xff0c;RES-440&#xff0c;RES-5008&#xff0c;RES-5006&a…

阿里三面:Redis大key怎么处理?

阿里三面&#xff1a;Redis大key怎么处理&#xff1f; 一、什么是大key&#xff1f; 首先大key不是key很大而是key对应的value值很大,一般而言如果String类型值大于10KB&#xff0c;Hash&#xff0c;Set&#xff0c;Zset&#xff0c;List类型的元素的个数大于5000个都可以称之…

18. 《C语言》——【Nice2016年校招笔试题引发的思考】

亲爱的读者&#xff0c;大家好&#xff01;我是一名正在学习编程的高校生。在这个博客里&#xff0c;我将和大家一起探讨编程技巧、分享实用工具&#xff0c;并交流学习心得。希望通过我的博客&#xff0c;你能学到有用的知识&#xff0c;提高自己的技能&#xff0c;成为一名优…

中国版Sora?快手「可灵」到底行不行?

“可灵”与Sora有相似的技术架构&#xff0c;生成的视频动作流畅、幅度大&#xff0c;对物理世界理解力与还原度很高。可生成120秒、每秒30帧的高清视频&#xff0c;分辨率高达1080p&#xff0c;并且支持多种不同的屏幕比例。 “中国版SORA”到底是不是名副其实&#xff1f;能…

谷歌浏览器124版本Webdriver驱动下载

查看谷歌浏览器版本 在浏览器的地址栏输入&#xff1a; chrome://version/回车后即可查看到对应版本(不要点击帮助-关于Google chrome&#xff0c;因为点击后会自动更新谷歌版本) 114之前版本&#xff1a;下载链接 ​​​​​​123以后版本&#xff1a;下载链接&#xff0…

【机器学习】通用大模型VS垂直大模型,你更加青睐哪一方?

目录 前言AI大模型的战场&#xff1a;通用与垂直的分化通用大模型&#xff1a;广泛适用的利器垂直大模型&#xff1a;深入领域的利器谁能够形成绝对优势&#xff1f;结语通用大模型文章推荐 前言 AI大模型的战场正在分化&#xff1a; 通用大模型在落地场景更广泛毋庸置疑&…