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

news2024/11/18 18:48:22

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

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

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

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

主要内容完成单例日志器管理类的实现,以及全局接口的设计与实现

在这里插入图片描述

文章目录

  • C++基于多设计模式下的同步&异步日志系统day6
    • 1.单例日志器管理类设计
      • 1.1日志器管理类的实现
      • 1.2全局建造者的实现
    • 2.全局接口的设计与实现
      • 2.1全局接口的设计

1.单例日志器管理类设计

⽇志的输出,我们希望能够在任意位置都可以进⾏,但是当我们创建了⼀个⽇志器之后,就会受到⽇志器所在作⽤域的访问属性限制。

因此,为了突破访问区域的限制,我们创建⼀个⽇志器管理类,且这个类是⼀个单例类,这样的话,我们就可以在任意位置来通过管理器单例获取到指定的⽇志器来进⾏⽇志输出了。

基于单例⽇志器管理器的设计思想,我们对于⽇志器建造者类进⾏继承,继承出⼀个全局⽇志器建造者类,实现⼀个⽇志器在创建完毕后,直接将其添加到单例的⽇志器管理器中,以便于能够在任何位置通过⽇志器名称能够获取到指定的⽇志器进⾏⽇志输出。

作用和特性:

​ 作用①:对所有创建的日志器进行管理

​ 特性:将管理器设计为单例

​ 作用②:可以在程序的任意位置,获取相同的单例对象,获取其中的日志器进行日志输出

拓展:单例管理器创建的时候,默认先创建一个日志器(用于进行标准输出的打印)

目的:让用户在不创建任何日志器的情况下,也能进行标准输出的打印,方便用户使用

管理的成员

​ ①默认的日志器

​ ②管理日志器的数组

​ ③互斥锁

提供的接口

​ ①添加日志器管理

​ ②判断是否管理了指定名称的日志器

​ ③获取指定名称的日志器

​ ④获取默认日志器

1.1日志器管理类的实现

   class LoggerManager
    {
    public:
        //单例对象的获取
        static LoggerManager& getInstance()
        {
            //c++11之后,针对静态局部变量,在编译层面已经实现了线程安全
            //当静态局部变量没有完成构造之前,这时候其他的线程进入就会阻塞
            static LoggerManager eton;
            return eton;
        }
        //添加日志器
        void addLogger(Logger::ptr &logger)
        {
            //如果存在就不再添加
            if(hasLogger(logger->name())) return ;
            std::unique_lock<std::mutex> lock;
            _loggers.insert(std::make_pair(logger->name(), logger));
        }
        //查看指定名称的日志器是否存在
        bool hasLogger(const std::string & name)
        {
            std::unique_lock<std::mutex> lock;
            auto it = _loggers.find(name);
            if(it == _loggers.end())
            {
                return  false;
            }
            return true;
        }
        //返回指定名称的日志器
        Logger::ptr getLogger(const std::string & name)
        {
            std::unique_lock<std::mutex> lock;
            auto it = _loggers.find(name);
            if(it == _loggers.end())
            {
                return Logger::ptr();
            }
            return it->second;            
        }
        // 获取默认的日志器
        Logger::ptr rootLogger()
        {
            return _root_logger;
        }

    private:
        LoggerManager()
        {
            std::unique_ptr<xupt::LoggerBuilder> builder(new xupt::LocalLoggerBuilder());
            builder->buildLoggerName("root");
            _root_logger = builder->build();
            _loggers.insert(std::make_pair("root", _root_logger));
        }
    private:
        //互斥锁,防止我们在程序的任意位置获取日志器的时候造成线程安全问题
        std::mutex _mutex;
        //默认的日志器指针
        Logger::ptr _root_logger;
        //管理日志器的数组
        std::unordered_map<std::string, Logger::ptr> _loggers;
    };

1.2全局建造者的实现

    /*设计一个全局日志器建造者---在局部的基础上增加了一个功能:将日志器添加到单例对象中*/
    class GlobalLoggerBuilder : public LoggerBuilder
    {
        public:
            Logger::ptr build() override
            {
                assert(_logger_name.empty() == false); //必须有日志器名称
                if(_formatter.get() == nullptr)
                {
                    _formatter = std::make_shared<Formatter>();
                }
                if(_sinks.empty())
                {
                    buildSink<StdoutSink>();
                }

                Logger::ptr logger;
                if(_logger_type == LoggerType::LOGGER_ASYNC)
                {
                    logger = std::make_shared<AsyncLogger>(_logger_name, _limit_level, _formatter, _sinks);
                }
                else 
                {
                    logger = std::make_shared<SyncLogger>(_logger_name, _limit_level, _formatter, _sinks);
                }

                LoggerManager::getInstance().addLogger(logger);
                //返回同步日志器
                return logger;
            }
    };  

2.全局接口的设计与实现

2.1全局接口的设计

提供全局接口&宏函数,对日志系统接口进行使用便捷性优化

①提供获取指定日志器的全局接口(避免用户自己操作单例对象)

②使用宏函数对日志器的接口进行代理(代理模式)

③提供宏函数直接实现日志的标准输出打印(不用获取日志器了)

提供全局的⽇志器获取接⼝。
使⽤代理模式通过全局函数或宏函数来代理Logger类的log、debug、info、warn、error、fatal等接⼝,以便于控制源码⽂件名称和⾏号的输出控制,简化⽤⼾操作。当仅需标准输出⽇志的时候可以通过主⽇志器来打印⽇志。且操作时只需要通过宏函数直接进⾏输出即可。

#ifndef __M_XUPT_H__
#define __M_XUPT_H__


// ①提供获取指定日志器的全局接口(避免用户自己操作单例对象)

// ②使用宏函数对日志器的接口进行代理(代理模式)

// ③提供宏函数直接实现日志的标准输出打印(不用获取日志器了)

#include"logger.hpp"

namespace xupt
{

    // ①提供获取指定日志器的全局接口(避免用户自己操作单例对象)
    Logger::ptr getLogger(const std:: string& name)
    {
        return xupt::LoggerManager::getInstance().getLogger(name);
    }
    Logger::ptr rootLogger()
    {
        return xupt::LoggerManager::getInstance().rootLogger();
    }

    // ②使用宏函数对日志器的接口进行代理(代理模式)
    #define debug(fmt,...) debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__);
    #define info(fmt,...) info(__FILE__, __LINE__, fmt, ##__VA_ARGS__);
    #define warn(fmt,...) warn(__FILE__, __LINE__, fmt, ##__VA_ARGS__);
    #define error(fmt,...) error(__FILE__, __LINE__, fmt, ##__VA_ARGS__);
    #define fatal(fmt,...) fatal(__FILE__, __LINE__, fmt, ##__VA_ARGS__);

    // ③提供宏函数直接实现日志的标准输出打印(不用获取日志器了)
    #define DEBUG(fmt, ...) rootLogger()->debug(fmt, #__VA_ARGS__)
    #define INFO(fmt, ...) rootLogger()->info(fmt, #__VA_ARGS__)
    #define WARN(fmt, ...) rootLogger()->warn(fmt, #__VA_ARGS__)
    #define ERROR(fmt, ...) rootLogger()->error(fmt, #__VA_ARGS__)
    #define FATAL(fmt, ...) rootLogger()->fatal(fmt, #__VA_ARGS__)


}


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

在这里插入图片描述

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

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

相关文章

JPA generator 生成实体类

1、配置生成实体类 选中表后点击右键 2、 Generate POJOs.groovy 配置 import com.intellij.database.model.DasTable import com.intellij.database.model.ObjectKind import com.intellij.database.util.Case import com.intellij.database.util.DasUtilimport java.text.S…

K次取反后最大化的数组和 加油站 分发糖果 柠檬水找零

1005.K次取反后最大化的数组和 力扣题目链接(opens new window) 给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&a…

类与对象(二)--类的六个默认成员函数超详细讲解

目录 1.类的默认六个成员函数✒️ 2.构造函数 2.1构造函数的概念✒️ 2.2构造函数的特性✒️ 3.析构函数 3.1析构函数的概念✒️ 3.2析构函数的特征✒️ 4.拷贝构造函数 4.1拷贝构造函数的概念✒️ 4.2拷贝构造函数的特征✒️ 4.3思考❓ 4.4深拷贝和浅拷贝⭐️…

嵊州吃喝玩乐篇

1. 豆腐馒头 胖大姐豆腐馒头&#xff08;推荐&#xff09; 地址: 嵊州市越秀路96-98号 高德地图搜 “胖大姐黄泽豆腐馒头” 黄泽豆腐馒头 地址&#xff1a;嵊州市越秀路111号 高德地图搜 “嵊州市玉英豆腐馒头店” 2. 烧烤 老张烧烤&#xff08;推荐&#xff09; 地址&a…

3.5作业

1.使用write 和 read 实现 文件夹拷贝功能&#xff0c;不考虑递归拷贝 #include<stdio.h> #include<string.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> int main(in…

#stm32学习总结GPIO

1、 GPIO 1.1、简介 就是通用输入输出口 2&#xff0c; STM32 GPIO简介&#xff08;了解&#xff09; 2.1&#xff0c;GPIO特点 1&#xff0c;不同型号&#xff0c;IO口数量可能不一样&#xff0c;可通过选型手册快速查询 2&#xff0c;快速翻转&#xff0c;每次翻转最快只…

PTA L2-009 抢红包

题目&#xff1a; 没有人没抢过红包吧…… 这里给出N个人之间互相发红包、抢红包的记录&#xff0c;请你统计一下他们抢红包的收获。 输入格式&#xff1a; 输入第一行给出一个正整数N&#xff08;≤104&#xff09;&#xff0c;即参与发红包和抢红包的总人数&#xff0c;则…

【网站项目】121开放式教学评价管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

EtherCAT运动控制器在ROS上的应用(上)

本文以正运动技术EtherCAT运动控制器ZMC432和ZMC408CE为例&#xff0c;介绍正运动技术运动控制器在ROS上的应用开发。 在正式学习之前&#xff0c;我们先了解一下正运动技术的EtherCAT运动控制器ZMC432和ZMC408CE。这两款产品分别是32轴&#xff0c;8轴EtherCAT运动控制器。 …

分享Web.dev.cn中国开发者可以正常访问

谷歌开发者很高兴地宣布&#xff0c;web.dev 和 Chrome for Developers 现在都可以通过 .cn 域名访问&#xff0c;这将帮助中国的开发者更加容易获取我们的内容。 在 .cn 域名上&#xff0c;我们已向您提供所有镜像后的内容&#xff0c;并提供支持的语言版本。 Web.dev 中国开…

【Unity】使用ScriptableObject存储数据

1.为什么要用ScriptableObject&#xff1f; 在游戏开发中&#xff0c;有大量的配置数据需要存储&#xff0c;这个时候就需要ScriptableObject来存储数据了。 很多人会说我可以用json、xml、txt&#xff0c;excel等等 但是你们有没有想过&#xff0c;假设你使用的是json&#x…

CSS全局样式的设置,JavaScript运算符

面试题&#xff1a; Html 1&#xff0c;html语义化 2&#xff0c;meta viewport相关 3&#xff0c;canvas 相关 CSS 1&#xff0c;盒模型 1.1&#xff0c;ie盒模型算上border、padding及自身&#xff08;不算margin&#xff09;&#xff0c;标准的只算上自身窗体的大小 c…

相机类型的分辨率长宽、靶面尺寸大小、像元大小汇总

镜头的靶面尺寸大于等于相机靶面尺寸。 相机的芯片长这样&#xff0c;绿色反光部分&#xff08;我的手忽略&#xff09;&#xff1a; 基本所有像素的相机的靶面大小都可以在这个表格里面找到。 镜头的靶面尺寸在镜头外表上可以找到&#xff0c;选型很重要&#xff01;

Android logcat系统

一 .logcat命令介绍 android log系统: logcat介绍 : logcat是android中的一个命令行工具&#xff0c;可以用于得到程序的log信息. 二.C/Clogcat访问接口 Android系统中的C/C日志接口是通过宏来使用的。在system/core/include/android/log.h定义了日志的级别&#xff1a; /…

信息安全系列04-安全启动介绍

本文框架 1. 基本概念1.1 基本概念回顾1.2 数字签名及验签流程 2. 安全启动实施2.1 信任根选择2.1.1 使用HSM作为信任根2.1.2 使用最底层Bootloader作为信任根 2.2 校验方法确认2.2.1 基于非对称加密算法&#xff08;数字签名&#xff09;2.2.2 基于对称加密算法 2.3 安全启动方…

三星成功研发出业界首款12层堆叠HBM3E

三星电子有限公司成功研发出业界首款12层堆叠HBM3E DRAM——HBM3E 12H&#xff0c;这是迄今为止容量最大的HBM产品。这款新型HBM3E 12H内存模块提供了高达1,280GB/s的史上最高带宽&#xff0c;并拥有36GB的存储容量&#xff0c;相较于之前的8层堆叠HBM3 8H&#xff0c;在带宽和…

Java代码审计安全篇-常见Java SQL注入

前言&#xff1a; 堕落了三个月&#xff0c;现在因为被找实习而困扰&#xff0c;着实自己能力不足&#xff0c;从今天开始 每天沉淀一点点 &#xff0c;准备秋招 加油 注意&#xff1a; 本文章参考qax的网络安全java代码审计&#xff0c;记录自己的学习过程&#xff0c;还希望…

怎么把一段音频的人声和背景音乐分开?3种方法分享

怎么把一段音频的人声和背景音乐分开&#xff1f;随着技术的不断发展进步&#xff0c;将音频中的人声和背景音乐分离已成为现实。这种技术不仅提升了音频编辑的效率和准确性&#xff0c;更为我们提供了无限的可能性。例如&#xff0c;音乐制作人可以更容易地提取出纯净的人声或…

【比较mybatis、lazy、sqltoy、mybatis-flex、easy-query、mybatis-mp操作数据】操作批量新增、分页查询(四)

orm框架使用性能比较 比较mybatis、lazy、sqltoy、mybatis-flex、easy-query、mybatis-mp操作数据 环境&#xff1a; idea jdk17 spring boot 3.0.7 mysql 8.0测试条件常规对象 orm 框架是否支持xml是否支持 Lambda对比版本编码方式mybatis☑️☑️3.5.4lambda xml 优化sq…

SAR ADC学习笔记(3)

一、SAR ADC采样电路 1.采样网络的时域响应&#xff1a;采保信号 2.采样网络的KT/C噪声 3.采样抖动 采样开关的种类 1.单MOS管开关 2.传输门开关 3.栅极自举&#xff08;Bootstrap&#xff09;开关 结论&#xff1a;M4的衬底需要和B点短接&#xff0c;保证B点能够到达高压&…