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

news2024/9/22 11:30:32

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

🌴专栏链接: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

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

在这里插入图片描述

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

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

相关文章

防御保护课程笔记

内容安全 防病毒 过滤技术 密码学

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

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

【笔记】深度学习入门:基于Python的理论与实现(六)

深度学习 深度学习是加深了层的深度神经网络 加深网络 本节我们将这些已经学过的技术汇总起来&#xff0c;创建一个深度网络&#xff0c;挑战 MNIST 数据集的手写数字识别 向更深的网络出发 基于33的小型滤波器的卷积层。激活函数是ReLU。全连接层的后面使用Dropout层。基…

Laravel框架: Call to a member function connect() on null 异常报错处理

Laravel框架&#xff1a; Call to a member function connect() on null 异常报错处理 Date: 2024.03.01 21:03:11 author: lijianzhan 原文链接: https://learnku.com/laravel/t/63721 问题&#xff1a; local.ERROR: Call to a member function connect() on null {"…

win安装卸载python3.13

一、安装 访问python官网&#xff1a;https://www.python.org/ 点击“Downloads” 点击“Windows” 找到自己要下载的版本和位数&#xff0c;比如我这个是3.13版本、64位的安装包 下载好了之后&#xff0c;双击安装包 勾选“Add python.exe to PATH”&#xff1a;把python环…

线程安全的集合容器

线程安全的集合容器 List集合中的线程安全的集合容器&#xff1a; 在旧版本中Vector是线程安全的集合容器&#xff0c;在JDK 1.5以后CopyOnWriteArrayList也是线程安全的集合容器&#xff0c;CopyOnWriteArrayList的数据结构是Object类型的数组。 CopyOnWriteArrayList是如何…

【问题记录】pip install遇到“No space left on device“

一、pip安装包的过程中出现以下问题 二、问题溯源 【1】刚开始以为是空间不足&#xff0c;后来 df -h 看了一下&#xff0c;pip安装目录下空间绝对足够&#xff01;明显不是空间不足的问题。 【2】后来查了一下&#xff0c;发现是home目录下的空间满了&#xff0c;pip安装时&…

华为 OD 一面算法原题

2.2 亿彩票公布调查结果 昨天&#xff0c;闹得沸沸扬扬的《10 万中 2.2 亿》的彩票事件&#xff0c;迎来了官方公告。 简单来说&#xff0c;调查结果就是&#xff1a;一切正常&#xff0c;合规合法。 关于福利彩票事件&#xff0c;之前的推文我们已经分析过。 甚至在后面出现《…

车辆管理系统:一套系统掌握车辆的运营、维护和使用情况

hello&#xff0c;我是贝格前端工场&#xff0c;直接给大家介绍了各类通用的B端管理系统&#xff0c;收到了大家的欢迎。本次开始介绍针对具体行业的管理系统该如何设计和开发&#xff0c;欢迎大家持续关注、点赞&#xff0c;如有系统定制需求可以私信我们。 一、什么是车辆管理…

Muduo库核心代码及优秀编程细节剖析

一、前言&#xff1a; Muduo库是陈硕个人开发的Tcp网络编程库&#xff0c;支持Reactor模型。这篇博文对Muduo库中的Multi-reactor架构代码进行逻辑梳理&#xff0c;同时认真剖析了作者每一处精妙的代码设计思想。 目前我只重构并剖析了Muduo库中的核心部分&#xff0c;即Mult…

Qt应用软件【测试篇】cppchecker静态代码检查

文章目录 cppcheker简介下载地址与安装检查项目QT Creator使用CPP Cheker开启检查常见错误总结错误信息说明cppcheker简介 Cppcheck 是一个用于 C/C++ 代码的分析工具。它提供独特的代码分析以检测错误,并专注于检测未定义的行为和危险的编码结构。其目标是仅检测代码中的真实…

【Ai生态开发】Spring AI上架,打造专属业务大模型,AI开发再也不是难事!

大家好 这里是苏泽 后端是工作 ai是兴趣 对于ai的产生我的立场是拥抱ai的 是希望拿他作为提升能力的工具 那么这一篇带大家来学习如何使用ai打造一个专属的业务大模型 需求 就是说假设现在有一个 商城系统 里面有查询订单的api和获取商品购买方式的api 用户只需要输入 “…

ICCV2023:FLatten Transformer: Vision Transformer using Focused Linear Attention

文章目录 摘要引言PreliminaryVision Transformer and Self-AttentionLinear Attention Focused Linear Attention1.Focus ability2.Feature diversity3. Focused linear attention module 实验推理时间 总结 摘要 self-attention 的二次计算复杂度一直是将Transform模型应用于…

打印100-200之间的素数

#include <stdio.h>int prime(int n){int i 1;for(i 2;i < n;i){if(n % i 0)return 0;}return 1; } //打印100-200之间的素数 int main() {int n 0;int j 100;for(j 100;j < 200;j){if(prime(j)){printf("%d是素数\n",j);n;}}printf("100-200…

在此处打开命令窗口 (Open command window here)

在此处打开命令窗口 [Open command window here] 1. 在此处打开命令窗口 (Open command window here)2. .exe 执行References 1. 在此处打开命令窗口 (Open command window here) Shift 鼠标右键 2. .exe 执行 ​​​ 在 .exe 文件所在的文件夹打开命令提示符窗口。如果使用…

【算法】二叉搜索树的插入、删除、转换操作

1 二叉搜索树的插入操作 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c;可能…

ref和reactive用哪个?

ref和reactive用哪个? 1.&#x1f916;GPT&#x1f916;:ref和reactive用哪个根据数据类型而定 ref 用于将基本类型的数据&#xff08;如字符串、数字&#xff0c;布尔值等&#xff09;转换为响应式数据。使用 ref 定义的数据可以通过 .value 属性访问和修改。 reactive 用于…

每日一题——LeetCode1556.千位分隔符

方法一 个人方法&#xff1a; 把n转为字符串&#xff0c;逆序遍历n&#xff0c;把n的每个元素加入res&#xff0c;每三次加入.&#xff0c;最后将res翻转再转为字符串即为符合题目要求的结果 var thousandSeparator function(n) {nlet res[],lenn.length-1for(let ilen;i>…

1、jQuery介绍、css()、选择器、事件、动画

一、jQuery介绍&#xff1f; 1、什么是jQuery&#xff1f; 是一个JavaScript函数库 2、jQuery特点 写的少&#xff0c;做的多 3、jQuery的安装 直接下载引入 <script src"jquery-1.10.2.min.js"></script>通过cdn引入 <script src"https…

2369. 检查数组是否存在有效划分(动态规划)

2024-3-1 文章目录 [2369. 检查数组是否存在有效划分](https://leetcode.cn/problems/check-if-there-is-a-valid-partition-for-the-array/)思路&#xff1a;代码&#xff1a; 2369. 检查数组是否存在有效划分 思路&#xff1a; 1.状态定义:f[i]代表考虑将[0,i]是否能被有效划…