6.8日志系统

news2024/11/17 15:35:04

当做大型项目的时候,出了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_是在,

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

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

相关文章

基于springboot实现教学资料管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现教学资料管理系统演示 摘要 使用旧方法对教学资料管理系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在教学资料管理系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存…

【ARM Coresight Debug 系列 -- ARMv8/v9 Watchpoint 软件实现地址监控详细介绍】

请阅读【嵌入式开发学习必备专栏 】 文章目录 ARMv8/v9 Watchpoint exceptionsWatchpoint 配置信息读取Execution conditionsWatchpoint data address comparisonsSize of the data accessWatchpoint 软件配置流程Watchpoint Type 使用介绍WT, Bit [20]: Watchpoint TypeLBN, B…

《一头扎进》系列之Python+Selenium框架实战篇23- 价值好几K的框架,呵!这个框架有点意思啊!!!

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 前面文章&#xff0c;我们实现了框架的一部分功能&#xff0c;包括日志类和浏览器引擎类的封装&#xff0c;今天我们继续封装一个基类和介绍如何实现POM。关于基类&#xff0c;…

JAVA小知识17:数组,从0基础到掌握

数组&#xff0c;无论在哪种编程语言当中都是最基础&#xff0c;最广泛使用的一种线性表数据结构&#xff0c;这篇文章将从多个角度来从浅入深的讲述数组。 本文讲述了数组的概念&#xff0c;定义&#xff0c;初始化方法以及如何遍历数组&#xff0c;如何赋值&#xff0c;关于数…

基于WPF技术的换热站智能监控系统03--实现左侧加载动画

1、左侧布局规划 左侧分5行&#xff0c;每行的高度通过height属性来指定&#xff0c;1.2*表示占1.2倍的宽度 2、创建用户控件 在WPF中想要进行个性化处理&#xff0c;主要可以通过三个方面来实现&#xff1a;控件模板&#xff08;控件模板、数据模板、数据容器模板&#xff09…

EDEX-UI这个终端模拟器

eDEX-UI 是一款开源、免费、跨平台的全屏终端模拟器和系统监视器&#xff0c;外观和操作界面极其科幻&#xff0c;灵感来自电影《创战纪》的会议室特效场景。作者倾注了大量心血&#xff0c;使得它不仅拥有酷炫的操作界面&#xff0c;还具备清晰爽脆的音效。 优点&#xff1a; …

【车载AI音视频电脑】4路AHD 130万像素双卡车载录像机

产品主要特点&#xff1a; -支持4路实时高清AHD 720P录像 -SD卡记录数据&#xff08;可支持2张大容量SD卡,最大支持单张256G&#xff09; -支持GPS全球定位, 可选模块 -支持WIFI高速自动下载功能, 可选模块 -内置3/4G模块&#xff0c;实时预览和远程管理&#xff0c; 可选…

打造你的专属扭蛋机:淘宝扭蛋机小程序搭建全攻略

想要在互联网娱乐领域大展拳脚吗&#xff1f;淘宝扭蛋机小程序或许是你的不二选择。本文将为你提供详细的搭建教程&#xff0c;帮助你轻松打造属于自己的扭蛋机小程序。 一、了解扭蛋机小程序的基本原理 在开始搭建之前&#xff0c;我们需要了解扭蛋机小程序的基本原理。扭蛋机…

收藏一些毕业论文技术路线图

*信息来源&#xff1a;xhs 立青Jill 原文链接https://mp.weixin.qq.com/s?__bizMzUyNzczMTI4Mg&mid2247693272&idx3&snf6c8513eaee894c5158dc5c3620bf93c&chksmfa76ace5cd0125f3169b2782c137f6308c6d201d3a845db1be8b397758a1f11e3719524e601b&token18515…

图片转Excel表格:提升数据处理效率的利器

在日常工作和生活中&#xff0c;我们经常遇到各种数据和信息以图片的形式存在。有时&#xff0c;这些数据图片中包含了重要的表格信息&#xff0c;例如财务报告、统计数据或调研结果。为了对这些数据进行进一步的分析和处理&#xff0c;我们需要将其转换为可编辑的电子表格格式…

Android WebSocket长连接的实现

一、为什么需要 WebSocket 初次接触 WebSocket 的人&#xff0c;都会问同样的问题&#xff1a;我们已经有了 HTTP 协议&#xff0c;为什么还需要另一个协议&#xff1f;它能带来什么好处&#xff1f; 答案很简单&#xff0c;因为 HTTP 协议有一个缺陷&#xff1a;通信只能由客…

程序员职业素养

程序员应该具备的职业素养 一、专业精神1.1、专业精神在程序员职业生涯中的重要性1.2、追求技术的过程1.3、专业精神对团队和项目的影响1.4、专业精神在个人职业发展中的意义 二、沟通能力2.1 沟通能力在程序员职业生涯中的重要性2.2 沟通能力的要素2.2.1. 有效的口头和书面表达…

UPS负载箱的使用注意事项有哪些?

UPS负载箱是用于模拟电网中各种负载的设备&#xff0c;广泛应用于电力系统、通信系统、数据中心等领域。为了保证UPS负载箱的正常运行和使用安全&#xff0c;在使用过程中需要注意以下几点&#xff1a; 1. 选择合适的负载箱&#xff1a;根据实际需求选择合适的负载箱&#xff0…

DevExpress WPF中文教程:Grid - 如何完成列和编辑器配置(设计时)?

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

数据密集型企业是如何选择替代FTP传输文件的系统的?

数据密集型企业是指其发展和运行高度依赖于数据、算法和算力的闭环优化体系的企业。这类企业拥有规模化知识创造者、更广泛的智能工具以及更丰裕的数据要素资源。 毋庸置疑&#xff0c;数据对于数据密集型企业来说是最关键、最核心的资产&#xff0c;但数据密集型企业同样也面临…

航天科技集团与SPACEX公司的思考与分析

近期&#xff0c;中国航天科技集团正式发文与SPACEX对标的认识结果&#xff0c;包括发展理念上、科研生产模式上、关键核心技术上、质量效率效益上存在明显差距与不足。真诚的态度&#xff0c;赢得了社会上的广泛关注和积极评价。真心为老东家能够保持这份清醒而高兴。 从对标管…

WPF学习(1)--类与类的继承

在面向对象编程中&#xff0c;继承是一种机制&#xff0c;允许一个类&#xff08;称为子类或派生类&#xff09;从另一个类&#xff08;称为父类或基类&#xff09;继承属性和方法。继承使我们能够创建一个通用类&#xff0c;然后根据需要扩展或修改它以创建更具体的类。以下是…

关于pip的15个使用小技巧

认识pip 众所周知&#xff0c;pip可以对python的第三方库进行安装、更新、卸载等操作&#xff0c;十分方便。 pip的全称&#xff1a;package installer for python&#xff0c;也就是Python包管理工具。 可能有些人用了很久pip&#xff0c;但还不清楚包管理工具是个啥。 我…

气膜建筑一平多少钱—轻空间

气膜建筑是一种以膜材为主要结构材料&#xff0c;通过空气压力支撑的建筑形式。它广泛应用于体育场馆、展览馆、仓库及临时活动场所等多种领域&#xff0c;具有快速搭建、灵活使用、节能环保等诸多优势。 气膜建筑的成本构成 气膜建筑的成本主要由以下几个部分构成&#xff1a;…

爬虫相关面试题

一&#xff0c;如何抓取一个网站&#xff1f; 1&#xff0c;去百度和谷歌搜一下这个网站有没有分享要爬取数据的API 2, 看看电脑网页有没有所需要的数据&#xff0c;写代码测试调查好不好拿&#xff0c;如果好拿直接开始爬取 3&#xff0c;看看有没有电脑能打开的手机网页&a…