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; //线程id
        std::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

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

在这里插入图片描述

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

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

相关文章

【详识JAVA语言】方法签名

方法签名 在同一个作用域中不能定义两个相同名称的标识符。比如&#xff1a;方法中不能定义两个名字一样的变量&#xff0c;那为什么类中就可以定义方法名相同的方法呢&#xff1f; 方法签名即&#xff1a;经过编译器编译修改过之后方法最终的名字。具体方式&#xff1a; 方…

python3.x的在线与离线安装纯净版

由于计划搭建一套使用python自动分析日志的流程&#xff0c;发现我们的测试环境CentOS 7仍然没有安装python3&#xff0c;无法使用这些新的库。Python 3在设计上着重提升了语言的一致性和易用性&#xff0c;它引入了许多关键改进&#xff0c;此外&#xff0c;Python 3环境拥有丰…

Javaweb之SpringBootWeb案例之自动配置以及常见方案的详细解析

3.2 自动配置 我们讲解了SpringBoot当中起步依赖的原理&#xff0c;就是Maven的依赖传递。接下来我们解析下自动配置的原理&#xff0c;我们要分析自动配置的原理&#xff0c;首先要知道什么是自动配置。 3.2.1 概述 SpringBoot的自动配置就是当Spring容器启动后&#xff0c…

项目-SERVER模块-Buffer模块

Buffer模块 一、Buffer模块是什么&#xff1f;实现思想是什么&#xff1f;二、代码实现如何设计&#xff1a;1.成员变量&#xff1a;2.构造函数&#xff1a;3.获取地址和空间大小4.读写偏移向后移动5.扩容函数6.写入函数7.读取函数8.获取地址和空间大小9.获取地址和空间大小10.…

springboot自写插件封包

在Spring Boot中自写插件或封包&#xff08;通常指的是创建自定义的starter&#xff09;是一种常见的做法&#xff0c;用于将一系列相关的配置和组件打包成一个独立的模块&#xff0c;从而简化依赖管理和配置过程。以下是一个简单的步骤&#xff0c;指导你如何创建一个自定义的…

如何高效管理项目:从规划到执行

导语&#xff1a;项目管理是一项复杂而重要的工作&#xff0c;涉及多个方面&#xff0c;包括规划、执行、监控和收尾。本文将介绍如何高效管理项目&#xff0c;从规划到执行&#xff0c;帮助您成功完成项目目标。 一、项目规划 项目规划是项目成功的关键。在规划阶段&#xff0…

JVM原理-基础篇

Java虚拟机&#xff08;JVM, Java Virtual Machine&#xff09;是运行Java应用程序的核心组件&#xff0c;它是一个抽象化的计算机系统模型&#xff0c;为Java字节码提供运行环境。JVM的主要功能包括&#xff1a;类加载机制、内存管理、垃圾回收、指令解释与执行、异常处理与安…

[每周一更]-(第89期):开源许可证介绍

开源代码本就是一种共享精神&#xff0c;一种大无畏行为&#xff0c;为了发扬代码的魅力&#xff0c;创造更多的价值&#xff0c;让爱传递四方&#xff0c;让知识惠及更多人&#xff1b; 写文章也是一种共享精神&#xff0c;让知识传播出去。 介绍下开源中不同许可证的内容限…

【leetcode】随机链表的复制

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家刷题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 点击查看题目 思路: struct Node* copyRandomList(struct Node* head) {struct Node* curhead;//1.copy原链…

【矩阵】【方向】【素数】3044 出现频率最高的素数

作者推荐 动态规划的时间复杂度优化 本文涉及知识点 素数 矩阵 方向 LeetCode 3044 出现频率最高的素数 给你一个大小为 m x n 、下标从 0 开始的二维矩阵 mat 。在每个单元格&#xff0c;你可以按以下方式生成数字&#xff1a; 最多有 8 条路径可以选择&#xff1a;东&am…

Nginx基础知识

文章目录 简介安装Ubuntu安装CentOS安装windows 常用命令配置文件 nginx.confnginx -V 反向代理 & 负载均衡 简介 Web服务器&#xff0c;高性能&#xff0c;Http与反向代理的服务器。启动后浏览器输入 http://localhost/ 显示欢迎页面就是启动成功了。在nginx安装目录下cm…

【AntDesign】解决嵌套section或layout中,h1字体比h2小问题

问题&#xff1a;以下情况均会导致h1比h2小&#xff0c;具体原因是浏览器默认样式里面&#xff0c;对h1不同层级设置了特殊的样式&#xff0c; <section class"css-dev-only-do-not-override-12q8zf4 ant-layout"><section class"css-dev-only-do-not…

THINKPHP 跨域报错解决方案

报错&#xff1a;has been blocked by CORS policy: Response to preflight request doesnt pass access control check: No Access-Control-Allow-Origin header is present on the requested resource. 环境&#xff1a;thinkphp6 nginx 今天和VUE配合调用接口的时候发现跨…

Maven-私服(黑马学习笔记)

前面我们在讲解多模块开发的时候&#xff0c;我们讲到我们所拆分的模块是可以在同一个公司各个项目组之间进行资源共享的。这个模块的资源共享&#xff0c;就需要通过我们接下来所讲解的Maven的私服来实现。 首先我们先介绍一下什么是私服&#xff0c;以及它的作用是什么。再来…

瑞吉苍穹外卖如何拓展?已经经过不同公司多轮面试。项目中会问到哪些问题?以及问题如何解决?

别催了&#xff0c;别催了&#xff0c;先收藏吧。 作者大大正在加班加点完成。 文章会尽快发布&#xff0c;关注收藏&#xff0c;尽请期待。 想要加入并查阅作者的知识库可以联系作者 不要白嫖&#xff0c;通过后&#xff0c;附上关注和收藏截图。 已有众多小伙伴加入 目前…

mysql读写分离方案

什么是读写分离&#xff1f; 读写分离就是将对数据库的读操作和写操作分散到不同的数据库节点上 如何实现读写分离&#xff1f; 因为更多的读多写少&#xff0c;所以为了缓解主库的读能力从而引入了从库&#xff0c;这样就可以减少主库的负担&#xff0c;从而解决了应用的并发…

【教程】移动互联网时代的APP上架流程和要点

目录 摘要 引言 正文 一、应用商店注册 二、准备APP材料 三、打包上传App 摘要 本文将介绍移动应用程序上架的基本流程和要点&#xff0c;包括应用商店注册、APP材料准备、打包上传App、APP审核以及发布APP的详细步骤。此外&#xff0c;还会提到利用appuploder工具简化i…

【JavaScript】面试手撕节流

引入 上篇我们讲了防抖&#xff0c;这篇我们就谈谈防抖的好兄弟 – 节流。这里在老生常谈般的提一下他们两者之间的区别,顺带给读者巩固下。 PS: 开源节流中节流与这个技术上的节流&#xff0c;个人认为本质上是一样的。 开源节流的节流指的是节省公司的金钱开支。前端技术上的…

Windows的Docker-Desktop安装与问题总结

目录 Docker-Desktop安装步骤 环境配置 Docker-Desktop安装问题总结 问题1&#xff1a;docker-desktop setting界面一直加载转圈 问题2&#xff1a;docker镜像的存储位置变更&#xff08;防止C盘空间不足&#xff09; 参考文献&#xff1a; Docker-Desktop安装步骤 环境…

Unity(第十八部)物理力学,碰撞,触发、关节和材质

1、重力 刚体组件 英文中文描述RigidBody刚体组件physics->rigidbody &#xff0c;刚体组件使一个物体有了质量&#xff0c;重力等。&#xff0c;use gravity 勾选后&#xff0c;物体才会受到重力&#xff0c;会自动下落&#xff0c;取消勾选就不会。&#xff0c;&#xf…