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

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__)


}


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

在这里插入图片描述

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

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

相关文章

云手机运行在云端?安全性有保障吗

随着云计算技术的不断发展&#xff0c;云手机作为一种新兴的移动终端形态&#xff0c;逐渐成为人们关注的焦点。然而&#xff0c;对于许多人来说&#xff0c;云手机 是一个相对陌生的概念&#xff0c;安全性成为了他们最为关心的问题之一。本文将就云手机运行在云端的特点以及其…

JWT身份验证

在实际项目中一般会使用jwt鉴权方式。 JWT知识点 jwt&#xff0c;全称json web token &#xff0c;JSON Web令牌是一种开放的行业标准RFC 7519方法&#xff0c;用于在两方安全地表示声明。具体网上有许多文章介绍&#xff0c;这里做简单的使用。 1.数据结构 JSON Web Token…

#include<ros/ros.h>头文件报错

快捷键 ctrl shift B 调用编译&#xff0c;选择:catkin_make:build&#xff09;(要先在vscode上添加扩展&#xff1a;ros) 可以点击配置设置为默认&#xff0c;修改.vscode/tasks.json 文件 修改.vscode/tasks.json 文件&#xff0c;否则ros.h头文件会报错 内容修改为以下内…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:拖拽控制)

设置组件是否可以响应拖拽事件。 说明&#xff1a; 从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 ArkUI框架对以下组件实现了默认的拖拽能力&#xff0c;支持对数据的拖出或拖入响应&#xff0c;开发者只需要将这些组件…

残差网宽度残差网

目录 from # 从ResNet说起 # 更深的网络 # 理解shortcut # WRN之宽度残差块 # 退化现象 from WideResNet(宽残差网络)算法解析-鸟类识别分类-Pytorch实战-CSDN博客 # 前言 ResNet可以训练出更深的CNN模型ResNet模型的核心是建立前面层和后面层之间“短路链接”&#xff…

【Proteus仿真】【Arduino单片机】坐姿矫正提醒器设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶显示模块、HC-SR04超声波模块、蜂鸣器、按键、人体红外传感器等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示超声…

java——2024-03-03

String类的对象能被修改吗&#xff1f;如果不能需要用什么修改&#xff1f;StringBuilder和StringBuffer的区别&#xff1f;equals和区别谈谈对面向对象的理解重载和重写的区别说一下ArrayList&#xff0c;LinkedList底层实现以及区别什么是哈希冲突&#xff1f;hashMap和conCu…

tomcat动静分离和负载均衡

目录 引言 1.实验环境搭建 2.部署Nginx服务器及配置静态页面Web服务 3.部署Tomcat服务及配置动态页面Web服务 4.实验验收 动态页面 静态页面 引言 tomcat服务既可以处理动态页面&#xff0c;也可以处理静态页面&#xff1b;但其处理静态页面的速度远远不如nginx和apache…

笨办法学 Python3 第五版(预览)(三)

原文&#xff1a;Learn Python the Hard Way, 5th Edition (Early Release) 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 练习 30&#xff1a;假如 这是你将要输入的下一个 Python 脚本&#xff0c;它向你介绍了if语句。输入这个代码&#xff0c;确保它能够完美运行…

gin gorm学习笔记

代码仓库 https://gitee.com/zhupeng911/go-advanced.git https://gitee.com/zhupeng911/go-project.git 1. gin介绍 Gin 是使用纯 Golang 语言实现的 HTTP Web框架&#xff0c;Gin接口设计简洁&#xff0c;提供类似Martini的API&#xff0c;性能极高&#xff0c;现在被广泛使用…

基于ZYNQ PS-SPI的Flash驱动开发

本文使用PS-SPI实现Flash读写&#xff0c;PS-SPI的基础资料参考Xilinx UG1085的文档说明&#xff0c;其基础使用方法是&#xff0c;配置SPI模式&#xff0c;控制TXFIFO/RXFIFO&#xff0c;ZYNQ的IP自动完成发送TXFIFO数据&#xff0c;接收数据到RXFIFO&#xff0c;FIFO深度为12…

Vmware Workstation 不可恢复错误:0xc0000005 has occured

上周打开虚拟机的时候报错&#xff1a;Vmware Workstation 不可恢复错误&#xff1a;0xc0000005 has occured&#xff0c;查看网上资料说是vmware版本太低&#xff0c;需要手动更新本地版本。 由于本地网络不是很好&#xff0c;没能正常更新&#xff0c;无意中出现问题前更改了…

概率基础——极大似然估计

概率基础——极大似然估计 引言 极大似然估计&#xff08;Maximum Likelihood Estimation&#xff0c;简称MLE&#xff09;是统计学中最常用的参数估计方法之一&#xff0c;它通过最大化样本的似然函数来估计参数值&#xff0c;以使得样本出现的概率最大化。极大似然估计在各…

docker单节点搭建在线商城

本文档使用到的软件包以上传到资源中 目录 1. 创建容器并配置基础内容 1.1 将gpmall-repo上传到容器中 1.2 添加yum源 2. 安装基础服务 2.1 安装JAVA环境 2.2 安装Redis缓存服务 2.3 安装Elasticsearch服务 2.4 安装Nginx服务 2.5 安装MariaDB数据库 2.6 安…

数据库分库分表中间件选择

目前分库分表的中间件有三种设计思路&#xff0c;分别是&#xff1a; 采用分散式架构&#xff0c;适用于用Java开发的高性能轻量级OLTP应用程序&#xff0c;以Sharding-JDBC为代表。采用中间层Proxy架构&#xff0c;提供了静态输入和所有语言支持&#xff0c;适用于OLAP应用程…

验证Tomcat进程是否启动成功 ps -ef | grep tomcat

验证Tomcat启动是否成功&#xff0c;有多种方式&#xff1a; 查看启动日志 more /usr/local/apache-tomcat-9.0.86/logs/catalina.out tail -50 /usr/local/apache-tomcat-9.0.86/logs/catalina.out 查看进程 ps -ef | grep tomcat 注意&#xff1a; ps命令是linux下非常强…

《剑指offer》14--剪绳子(整数拆分)[C++]

目录 题目描述 贪心算法 输出结果 题目描述 把一根绳子剪成多段&#xff0c;并且使得每段的长度乘积最大。 给定一个正整数 n&#xff0c;将其拆分为至少两个正整数的和&#xff0c;并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: 输入: 2 输出: 1 解释:…

ZYNQ--PS_PL交互(AXI_HP)

AXI_HP接口 通过AXI_HP接口&#xff0c;可直接通过AXI_FULL协议向DDR中通过DMA传输数据。 BD设计 AXI_HP接口设置 AXI_Master代码 module axi_full_master #(parameter C_M_TARGET_SLAVE_BASE_ADDR 32h40000000,parameter integer C_M_AXI_BURST_LEN 16,parameter …

代码随想录算法训练营第22天|235.二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

目录 一、力扣235.二叉搜索树的最近公共祖先1.1 题目1.2 思路1.3 代码 二、力扣701.二叉搜索树中的插入操作2.1 题目2.2 思路2.3 代码 三、力扣450.删除二叉搜索树中的节点3.1 题目3.2 思路3.3 代码3.4 总结 一、力扣235.二叉搜索树的最近公共祖先 1.1 题目 1.2 思路 利用二叉…

09-Linux部署Redis

Linux部署Redis 简介 Redis&#xff0c;全称为Remote Dictionary Server&#xff08;远程字典服务&#xff09;&#xff0c;是一个开源的、使用ANSI C语言编写的、支持网络连接的、基于内存的、同时支持持久化的日志型Key-Value数据库&#xff0c;并提供多种语言的API。 Red…