C++基于多设计模式下的同步异步日志系统day2

📟作者主页:慢热的陕西人

🌴专栏链接:C++基于多设计模式下的同步&异步日志系统

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

主要内容实现了日志代码设计的实用类设计,日志等级设计,日志消息类设计。

在这里插入图片描述

文章目录

  • C++基于多设计模式下的同步&异步日志系统day2
    • 1.日志系统框架设计
      • 1.1模块划分
      • 1.2模块关系图
    • 2.代码设计
      • 2.1实用类设计
      • 2.2日志等级类设计
      • 2.3日志消息类的设计

C++基于多设计模式下的同步&异步日志系统day2

1.日志系统框架设计

本项⽬实现的是⼀个多⽇志器⽇志系统,主要实现的功能是让程序员能够轻松的将程序运⾏⽇志信息落地到指定的位置,且⽀持同步与异步两种⽅式的⽇志落地⽅式。项⽬的框架设计将项⽬分为以下⼏个模块来实现。

1.1模块划分

  • ⽇志等级模块:对输出⽇志的等级进⾏划分,以便于控制⽇志的输出,并提供等级枚举转字符串功能。

    1. OFF:关闭
    2. DEBUG:调试,调试时的关键信息输出
    3. INFO:提示,普通的提示性日志信息
    4. WARN:警告,不影响运行,但是需要注意一下的日志
    5. ERROR:错误,程序运行出现错误的日志
    6. FATAL:致命,一般是代码异常导致程序无法继续推进的运行的日志
  • 日志消息模块:中间存储日志输出所需的个各项要素信息

    1. 时间:描述本条日志的输出时间
    2. 线程ID:描述本条日志是哪个线程输出的
    3. 日志等级:描述本条日志的等级
    4. 日志数据:本条日志的有效载荷数据
    5. 日志文件名:描述本条日志在哪个源码文件中输出的
    6. 日志行号:描述本条日志在源码文件的哪一行输出的
  • ⽇志消息格式化模块:设置⽇志输出格式,并提供对⽇志消息进⾏格式化功能

    1. 系统的默认⽇志输出格式:%d{%H:%M:%S}%T[%t]%T[%p]%T[%c]%T%f:%l%T%m%n
    2. ->13:26:32 [2343223321] [FATAL] [root] main.c:76套接字创建失败\n
    3. %d{%H:%M:%S}:表⽰⽇期时间,花括号中的内容表⽰⽇期时间的格式
    4. %T:表⽰制表符缩进
    5. %t:表⽰线程ID
    6. %p:表⽰⽇志级别
    7. %c:表⽰⽇志器名称,不同的开发组可以创建⾃⼰的⽇志器进⾏⽇志输出,⼩组之间互不影响
    8. %f:表⽰⽇志输出时的源代码⽂件名
    9. %l:表⽰⽇志输出时的源代码⾏号
    10. %m:表⽰给与的⽇志有效载荷数据
    11. %n:表⽰换⾏
    12. 设计思想:设计不同的⼦类,不同的⼦类从⽇志消息中取出不同的数据进⾏处理
  • ⽇志消息落地模块:决定了⽇志的落地⽅向,可以是标准输出,也可以是⽇志⽂件,也可以滚动⽂
    件输出…

    1. 标准输出:表⽰将⽇志进⾏标准输出的打印
    2. ⽇志⽂件输出:表⽰将⽇志写⼊指定的⽂件末尾
    3. 滚动⽂件输出:当前以⽂件⼤⼩进⾏控制,当⼀个⽇志⽂件⼤⼩达到指定⼤⼩,则切换下⼀个⽂件进⾏输出
    4. 后期,也可以扩展远程⽇志输出,创建客⼾端,将⽇志消息发送给远程的⽇志分析服务器
    5. 设计思想:设计不同的⼦类,不同的⼦类控制不同的⽇志落地⽅向
  • ⽇志器模块:

    1. 此模块是对以上⼏个模块的整合模块,⽤⼾通过⽇志器进⾏⽇志的输出,有效降低⽤⼾的使⽤难度
    2. 包含有:⽇志消息落地模块对象,⽇志消息格式化模块对象,⽇志输出等级
  • ⽇志器管理模块:

    1. 为了降低项⽬开发的⽇志耦合,不同的项⽬组可以有⾃⼰的⽇志器来控制输出格式以及落地⽅向,因此本项⽬是⼀个多⽇志器的⽇志系统
    2. 管理模块就是对创建的所有⽇志器进⾏统⼀管理。并提供⼀个默认⽇志器提供标准输出的⽇志输出
  • 异步线程模块:

    1. 实现对⽇志的异步输出功能,⽤⼾只需要将输出⽇志任务放⼊任务池,异步线程负责⽇志的落地输出功能,以此提供更加⾼效的⾮阻塞⽇志输出

1.2模块关系图

image-20240301151659398

2.代码设计

2.1实用类设计

提前完成⼀些零碎的功能接⼝,以便于项⽬中会⽤到

  • 获取系统时间
  • 判断⽂件是否存在
  • 获取⽂件的所在⽬录路径
  • 创建⽬录
/*实用工具类的实现:1.获取系统时间2.判断文件是否存在3.获取文件所在路径4.创建目录
*/#include<iostream>
#include<ctime>
#include<unistd.h>
#include<sys/stat.h>namespace xupt
{namespace util{class Date{public:static size_t GetTime(){return (size_t)time(nullptr);}    };class File{public:static bool exist(const std::string &pathname){//确保平台移植性,我们不是用这个接口//return (access(pathname.c_str(), F_OK) == 0); //F_OK,文件存在且权限允许,返回0,struct st;if(stat(pathname.c_str(), &st) < 0){return false;}return true;}static std::string path(const std::string &pathname){size_t pos = pathname.find_last_of("/\\"); /*从路径字符串的后面开始寻找第一个/或者\ */if(pos == std::string.npos) return "."; //如果没有找到,那么证明这个文件就在当前的目录return pathname.substr(0, pos + 1); //输出包含最后一个/的位置的字符串}static void CreateDirectory(const std::string &pathname){size_t pos = 0, idx = 0;while(idx < pathname.size()){pos = pathname.find_first_of("/\\"); //寻找第一个/或者\if(pos == std::string.npos){mkdir(pathname, 0777); //如果没有分隔符,那么就直接创建,并且设置权限为0777}std::string parent_dir = pathname.substr(0, idx + pos + 1); //截取包含从开始到/的父目录if(exist(parent_dir) == true) { idx = pos + 1; continue; } //如果当前的目录存在了,那么就跳过去找下一个mkdir(parent_dir, 0777);idx = pos + 1;}}};}
}

2.2日志等级类设计

①日志等级总共分为7个等级,分别为:

  • UNKNOW表示未知错误
  • DRBUG进⾏debug时候打印⽇志的等级
  • INFO打印⼀些⽤⼾提⽰信息
  • WARN打印警告信息
  • ERROR打印错误信息
  • FATAL打印致命信息-导致程序崩溃的信息
  • OFF关闭所有日志输出

每一个项目中都会设置一个默认的日志输出等级,只有输出的日志等级大于等于默认限制等级的时候才可以进行输出

②提供一个接口,将对应等级的枚举,转换为一个对应的字符串。

/*1.定义枚举类,枚举出日志等级2.提供转换接口:将枚举转换为对应字符串
*/
#ifndef __M_LEVEL_H__
#define __M_LEVEL_H__namespace xupt
{class LogLevel{public:enum class value{UNKOWN = 0,DEBUG,INFO,WARN,ERROR,FATAL,OFF};static const char* toString(LogLevel::value level){switch (level){case LogLevel::value::DEBUG: return "DEBUG";case LogLevel::value::INFO: return "INFO";case LogLevel::value::WARN: return "WARN";case LogLevel::value::ERROR: return "ERROR";case LogLevel::value::FATAL: return "FATAL";case LogLevel::value::OFF: return "OFF";}return "UNKOWN";}};
}#endif

2.3日志消息类的设计

⽇志消息类主要是封装⼀条完整的⽇志消息所需的内容,其中包括⽇志等级、对应的loggername
印⽇志源⽂件的位置信息(包括⽂件名和⾏号)、线程ID时间戳信息具体的⽇志信息等内容

定义日志消息类,进行日志中间信息的存储:1.日志的输出时间   用于过滤日志输出时间2.日志等级        用于进行日志过滤分析3.源文件名称 4.源代码行号      用于定位出现错误的代码位置5.线程ID          用于过滤出错的线程6.日志主体消息7.日志器名称  (当前支持多日志器的同时使用)
*/
#ifndef __M_MESSAGE_H__
#define __M_MESSAGE_H__#include"util.hpp"
#include"level.hpp"
#include<iostream>
#include<string>
#include<thread>namespace xupt
{struct LogMsg{size_t _ctime; //日志产生的时间LogLevel::value _level; //日志等级size_t _line;  //行号std::thread::id _tid; //线程idstd::string _file; //文件名std::string _logger; //日志器名称std::string _payload; //有效消息处理//对应的构造函数LogMsg(LogLevel::value level,size_t line,std::string file,std::string logger,std::string msg):_ctime(util::Date::now()),_level(level),_line(line),_tid(std::this_thread::get_id()),_file(file),_logger(logger),_payload(msg){}};}#endif

到这本篇博客的内容就到此结束了。
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正

在这里插入图片描述

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

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

相关文章

11.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-接管游戏接收网络数据包的操作

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;接管游戏发送数据的操作 码云地址&#xff08;master 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/titan 码云版本号&#xff1a;8256eb53e8c16281bc1a29cb8d26d352bb5bbf4c 代…

软件测试最重要的事之【编写用例】

软件测试用例得出软件测试用例的内容&#xff0c;其次&#xff0c;按照软件测试写作方法&#xff0c;落实到文档中&#xff0c;两者是形式和内容的关系&#xff0c;好的测试用例不仅方便自己和别人查看&#xff0c;而且能帮助设计的时候考虑的更周。 一个好的测试用例必须包含…

【HTML】HTML基础系列文章小小总结,运用标签写出网页!

宇宙级声明&#xff01;这次只运用了一些基础标签&#xff0c;希望不要丑到大家~ 目录 效果预览&#xff1a;​编辑​编辑 点击百度百科 点击图片 点击下载 标签说明 源代码 效果预览&#xff1a; 点击百度百科 点击图片 点击下载 标签说明 标题 加粗文字 下划线 换行 分…

IO-DAY2

用发write、fread将一张随意图片修改成德国国旗 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<unistd.h> int main(int argc, char *argv[]) {FILE* fpfopen("./122.bmp","r");int w 0,h 0;fseek(fp,18,…

leetcode:860.柠檬水找零

题意&#xff1a;按照支付顺序&#xff0c;进行支付&#xff0c;能够正确找零。 解题思路&#xff1a;贪心策略&#xff1a;针对支付20的客人&#xff0c;优先选择消耗10而不是消耗5&#xff0c;因为5可以用来找零10或20. 代码实现&#xff1a;有三种情况&#xff08;代表三种…

tomcat 搭建博客 及破解数据库密码

一 tomcat 搭建博客 &#xff08;一&#xff09;博客安装包 1&#xff0c; 把博客war包 放到 webapps 文件夹下 2&#xff0c;会自动解压 3&#xff0c;做个软连接 方便后续操作 可以注意到 因为war包 是又tomcat 自己解压的 所以属主数组还是 tomcat &#xff08…

如何跳过格式化打开u盘文件?介绍几种实用方法

在使用U盘时&#xff0c;有时会遇到需要格式化才能打开文件的情况。但是&#xff0c;格式化会导致数据丢失&#xff0c;让人很头疼。那么&#xff0c;如何跳过格式化打开U盘文件&#xff1f;本文将介绍一些实用方法来解决这个问题。 方法1&#xff1a;检查USB驱动器 如果你的…

NodeJs 版本升级时Vue工程报错

最近把nodejs 的版本更新了&#xff0c;原来用的 16.15.1 现在用的 18.16.1&#xff0c;结果所有的vue工程都启不动了&#xff0c;一直报错。 1.报错截图 2.原因分析 error:03000086:digital envelope routines::initialization error &#xff0c;这个是nodejs版本的问题&am…

什么是生成式人工智能?

近年来&#xff0c;人工智能取得了重大进展&#xff0c;其中发展迅速的领域之一就是生成式人工智能。生成式人工智能是人工智能和深度学习的一个子领域&#xff0c;主要使用机器学习技 术根据现有数据训练算法和模型&#xff0c;生成诸如图像、文本、音乐、视频等新内容。 要更…

升级 Vue版本从 2.5.x 到 2.6.x

升级 Vue版本从2.5.x到2.6.x start 最近项目中需要使用某些第三方插件&#xff0c;但是第三方插件对 vue 的版本有要求。 插件要求 vue版本为 vue2.6.x 的&#xff0c;而我现有的环境是 vue2.5.x 的。 记录一下 升级 Vue 版本从 2.5.x 到 2.6.x 的过程。 正文 1. 更改 pack…

线程池的相关参数

在Java中线程池是一种池化技术&#xff0c;用于管理和复用线程&#xff0c;提高线程的利用率和性能。下面是一些常见的线程池的参数及其解释&#xff1a; 一&#xff1a;线程池的七大参数 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTim…

UDP数据报套接字编程入门

目录 1.TCP和UDP的特点及区别 1.1TCP的特点 1.2UDP的特点 1.3区别 2.UDP Socket的api的介绍 2.1DatagramSocket API 2.2DatagramPacket API 3.回显客户端与服务器 3.1回显服务器 3.1.1UdpEchoServer类的创建 3.1.2服务器的运行方法start() 3.1.3main部分 3.1.4.完整…