当前位置: 首页 > article >正文

日志与策略模式

什么是设计模式

IT⾏业 ,为了让 菜鸡们不太拖⼤佬的后腿, 于是⼤佬们针对⼀些经典的常⻅的场景, 给定了⼀些对应的解决⽅案, 这个就是  设计模式 

日志认识

计算机中的⽇志是记录系统和软件运⾏中发⽣事件的⽂件,主要作⽤是监控运⾏状态、记录异常信 息,帮助快速定位问题并⽀持程序员进⾏问题修复。它是系统维护、故障排查和安全管理的重要⼯ 具。

⽇志格式以下⼏个指标是必须得有的

  • 时间戳
  • ⽇志等级
  • ⽇志内容

以下几个指标是可选的

  • 文件名行号
  • 进程,线程相关id信息等

⽇志有现成的解决⽅案,如:spdlog、glog、Boost.Log、Log4cxx等等,我们依旧采⽤⾃定义⽇志的方式。

这⾥我们采⽤设计模式-策略模式来进⾏⽇志的设计,

策略模式是一种行为型设计模式,它允许在运行时选择算法或行为。该模式将算法族定义为一组可互换的策略,使得算法可以独立于使用它的客户端变化。

策略模式基于以下设计原则:

  • 封装变化:将易变的算法部分单独封装

  • 面向接口编程:定义策略接口,而不是具体实现

  • 组合优于继承:通过组合策略对象来获得灵活性,而非通过继承

策略模式包含三个主要角色:

  1. Context(上下文)

    • 维护对策略对象的引用

    • 可以定义一个接口让策略访问它的数据

  2. Strategy(策略接口)

    • 定义所有支持的算法的公共接口

    • Context使用这个接口调用具体策略定义的算法

  3. ConcreteStrategy(具体策略)

    • 实现策略接口的具体算法

例子:

#include <iostream>
#include <memory>// 策略接口
class SortingStrategy {
public:virtual void sort(int* data, int size) const = 0;virtual ~SortingStrategy() = default;
};// 具体策略A:快速排序
class QuickSort : public SortingStrategy {
public:void sort(int* data, int size) const override {std::cout << "Sorting using QuickSort\n";// 实际快速排序实现...}
};// 具体策略B:冒泡排序
class BubbleSort : public SortingStrategy {
public:void sort(int* data, int size) const override {std::cout << "Sorting using BubbleSort\n";// 实际冒泡排序实现...}
};// 上下文类
class Sorter {
private:std::unique_ptr<SortingStrategy> strategy;public:explicit Sorter(std::unique_ptr<SortingStrategy> strategy) : strategy(std::move(strategy)) {}void setStrategy(std::unique_ptr<SortingStrategy> newStrategy) {strategy = std::move(newStrategy);}void executeSort(int* data, int size) {strategy->sort(data, size);}
};int main() {int data[] = {5, 2, 7, 1, 9};Sorter sorter(std::make_unique<QuickSort>());sorter.executeSort(data, 5);  // 使用快速排序sorter.setStrategy(std::make_unique<BubbleSort>());sorter.executeSort(data, 5);  // 改为冒泡排序return 0;
}

我们想要的⽇志格式如下:

[可读性很好的时间] [⽇志等级] [进程pid] [打印对应⽇志的⽂件名][⾏号] - 消息内容,⽀持可
变参数
[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [16] - hello world
[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [17] - hello world
[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [18] - hello world
[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [20] - hello world
[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [21] - hello world
[2024-08-04 12:27:03] [WARNING] [202938] [main.cc] [23] - hello world

log.hpp

#pragma once
#include <iostream>
#include <string>
#include "Mutex.hpp"
#include <filesystem> //c++17
#include <fstream>    //c++文件流
#include <sstream>    //c++字符串流
#include <memory>
#include <time.h>//基于策略模式的日志
namespace LogModule
{using namespace LockModule;// 获取时间的函数std::string CurrentTime(){time_t time_stamp = ::time(nullptr); // 获取时间戳struct tm curr;//_r代表可以重入,支持多线程localtime_r(&time_stamp, &curr); // 将时间戳转化成可读性较强的时间信息char buffer[1024];// bugsnprintf(buffer, sizeof(buffer), "%4d-%02d-%02d %02d:%02d:%02d",curr.tm_year + 1900,curr.tm_mon + 1,curr.tm_mday,curr.tm_hour,curr.tm_min,curr.tm_sec);return buffer;}// 日志构成两个阶段: 一.构建日志信息  二.刷新落盘screen / file(向哪里刷新)// 二. 刷新落盘// 1. 日志文件的默认路径和名称const std::string dafaultlogpath = "./log/";const std::string dafaultlogname = "log.txt";// 2. 日志等级enum class LogLevel{DEBUG = 1,INFO, // 正常的WARNNING,ERROR,FATAL // 致命的};std::string Level2String(LogLevel level){switch (level){case LogLevel::DEBUG:return "DEBUG";case LogLevel::INFO:return "INFO";case LogLevel::WARNNING:return "WARNNING";case LogLevel::ERROR:return "ERROR";case LogLevel::FATAL:return "FATAL";default:return "NONE";}}// 3.刷新策略class LogStrategy // 基类{public:virtual ~LogStrategy() = default;   //虚析构函数(保证派生类对象能正确析构):确保通过基类指针删除派生类对象时能正确调用派生类的析构函数virtual void SyncLog(const std::string &message) = 0;//纯虚函数使得基类为抽象类 ,其派生类必须重构此函数才能构建对象};// 3.1控制台策略class ConsoleLogStrategy : public LogStrategy{public:ConsoleLogStrategy(){}~ConsoleLogStrategy(){}void SyncLog(const std::string &message){// 屏幕也是临界资源LockGuard lockguard(_mutex);std::cout << message << std::endl;}private:Mutex _mutex;};// 3.2文件级策略class FileLogStrategy : public LogStrategy{public:FileLogStrategy(const std::string &logpath = dafaultlogpath, const std::string &logname = dafaultlogname): _logpath(logpath),_logname(logname){LockGuard lockguard(_mutex);// 确认_logpath存在if (std::filesystem::exists(_logpath)){return;}try{std::filesystem::create_directories(_logpath);}catch (std::filesystem::filesystem_error &e){std::cerr << e.what() << "\n";}}~FileLogStrategy(){}void SyncLog(const std::string &message){LockGuard lockguard(_mutex);// c++文件操作std::string log = _logpath + _logname;// 创建一个ofstream文件输出流对象,以追加模式打开日志文件std::ofstream out(log, std::ios::app); // 日志是追加写入if (!out.is_open()){return;}out << message << "\n";out.close();}private:std::string _logpath;std::string _logname;Mutex _mutex; // 保证资源安全};// 一. 构建日志信息// 日志类 ,构建日志字符串(内部类实现) ,根据策略进行刷新class Logger{public:Logger(){// 默认使用控制台刷新_strategy = std::make_shared<ConsoleLogStrategy>();}void EnableConsoleLog(){_strategy = std::make_shared<ConsoleLogStrategy>();}void EnableFileLog(){_strategy = std::make_shared<FileLogStrategy>();}~Logger(){}// 定义了内部类   一个logmessage就包含了一条完整的日志信息//  一条完整的日志信息: [2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [16] + 日志的可变部分(<< "hello world" << 3.14 << a << b;)class LogMessage{public:LogMessage(LogLevel level, const std::string &filename, int line, Logger &logger): _currtime(CurrentTime()), _level(level), _pid(getpid()), _src_name(filename), _line(line), _logger(logger){// 用stringstream进行流式拼接std::stringstream ssbuffer;ssbuffer << "[" << _currtime << "] "<< "[" << Level2String(_level) << "] " // 我们想要字符串式的日志等级<< "[" << _pid << "] "<< "[" << _src_name << "] "<< "[" << _line << "] - ";_loginfo = ssbuffer.str();}// LOG(DEBUG) << "hello " << 3.14 << a << b;想要实现需要重载<<template <typename T>LogMessage &operator<<(const T &info) // 返回使用引用 (要保证后面的信息都拼接到同一个LogMessage){std::stringstream ss;ss << info;_loginfo += ss.str();return *this; // 返回自己}~LogMessage(){// 析构时,执行Logger所对应的根据指定策略进行刷新一条方法if (_logger._strategy)//设置策略了就刷新{_logger._strategy->SyncLog(_loginfo);}}private:std::string _currtime; // 时间LogLevel _level;       // 日志等级pid_t _pid;            // 进程pidstd::string _src_name; // 原文件名称int _line;             // 行号Logger &_logger;       // 负责根据不同的策略进行刷新std::string _loginfo;  // 一条完整的日志信息};// 仿函数重载() ,返回一个完整的日志信息// 故意没有写引用 ,就是要拷贝,返回临时的LogMessage??? 临时的LogMessage 自动析构时 自动刷新日志  LogMessage operator()(LogLevel level, const std::string &filename, int line){return LogMessage(level, filename, line, *this);}private:std::shared_ptr<LogStrategy> _strategy; // 日志的刷新方案// LogStrategy是纯虚类 ,不能定义对象,能定义指针};// 使用Logger logger;#define LOG(level) logger(level, __FILE__, __LINE__) //__是预处理符    logger()运算符重载
#define ENABLE_CONSOLE_LOG() logger.EnableConsoleLog()
#define ENABLE_FILE_LOG() logger.EnableFileLog()
}

Main.cc

#include"log.hpp"using namespace LogModule;int main()
{//用C++版的流,实现可变参数//日志输出格式//LOG(DEBUG) << "hello " << 3.14 << a << b;//会被替换成下面格式//logger(level ,__FILE__ ,__LINE__)<< "hello " << 3.14 << a << b;    //()执行完构建一个临时的LogMessage,临时的LogMessage会执行<<//LogMessage<< "hello " << 3.14 << a << b;        //LogMessage重载了<<ENABLE_FILE_LOG();LOG(LogLevel::INFO)<<"hello"<<666;return 0;
}

相关文章:

日志与策略模式

什么是设计模式 IT⾏业 ,为了让 菜鸡们不太拖⼤佬的后腿, 于是⼤佬们针对⼀些经典的常⻅的场景, 给定了⼀些对应的解决⽅案, 这个就是 设计模式 日志认识 计算机中的⽇志是记录系统和软件运⾏中发⽣事件的⽂件&#xff0c;主要作⽤是监控运⾏状态、记录异常信 息&#xff…...

Jenkins 最佳实践

1. 在Jenkins中避免调度过载 过载Jenkins以同时运行多个作业可能导致资源竞争、构建速度变慢和系统性能问题。分配作业启动时间可以防止瓶颈&#xff0c;并确保更顺畅的执行。如何实现&#xff1f; 在Cron表达式中使用H&#xff1a;引入抖动&#xff08;jitter&#xff09;&a…...

天能股份SAP系统整合实战:如何用8个月实现零业务中断的集团化管理升级

目录 天能股份SAP系统整合案例&#xff1a;技术驱动集团化管理的破局之路 一、企业背景&#xff1a;新能源巨头的数字化挑战 二、项目难点&#xff1a;制造业的特殊攻坚战 1. 生产连续性刚性需求 2. 数据整合三重障碍 3. 资源限制下的技术突围 三、解决方案&#xff1a;S…...

搜索引擎的高级语法

文章目录 精确搜索&#xff1a;双引号站内搜索&#xff1a;site通配符搜索&#xff1a;*减号缩小范围&#xff1a;-文档搜索&#xff1a;filetypeURL搜索&#xff1a; inurl标题搜索&#xff1a;intitle正文搜索&#xff1a;intext参考链接 精确搜索&#xff1a;双引号 “ ” …...

uniapp-商城-59-后台 新增商品(属性的选中,进行过滤展示,filter,some,every和map)

前面讲了属性的添加&#xff0c;添加完成后&#xff0c;数据库中已经存在数据了&#xff0c;这时再继续商品的添加时&#xff0c;就可以进行属性的选择了。 在商品添加过程中&#xff0c;属性选择是一个关键步骤。首先&#xff0c;界面需要展示嵌套的属性数据&#xff0c;用户通…...

linux用户切换

在 Linux 系统中&#xff0c;/etc/shadow 文件存储了用户的加密密码和其他安全相关信息&#xff0c;因此默认只有 root 用户 才有权限读取。当你尝试用普通用户身份查看时&#xff0c;会收到 Permission denied 错误。 如何查看 /etc/shadow 文件&#xff1f; 方法 1&#xff…...

B2C 商城转型指南:传统企业如何用 ZKmall模板商城实现电商化

在数字化浪潮席卷全球的当下&#xff0c;传统企业向电商转型已不再是选择题&#xff0c;而是关乎生存与发展的必答题。然而&#xff0c;缺乏技术积累、开发成本高、运营经验不足等问题&#xff0c;成为传统企业转型路上的 “拦路虎”。ZKmall模板商城以其低门槛、高灵活、强适配…...

鸿蒙OSUniApp 实现的二维码扫描与生成组件#三方框架 #Uniapp

UniApp 实现的二维码扫描与生成组件 前言 最近在做一个电商小程序时&#xff0c;遇到了需要扫描和生成二维码的需求。在移动应用开发中&#xff0c;二维码功能已经成为标配&#xff0c;特别是在电商、社交和支付等场景下。UniApp作为一个跨平台开发框架&#xff0c;为我们提供…...

生成树协议 - STP

目录 BPDU STP选举机制 STP端口状态 STP计时器 STP拓扑变更机制 生成树协议&#xff08;Spanning Tree Protocol&#xff09;&#xff0c;简写为STP。 STP是二层网络中用于消除环路的协议&#xff0c;通过阻塞冗余链路&#xff0c;使可用链路在拓扑上呈现出无环的树结构&…...

计算机指令分类和具体的表示的方式

1.关于计算机的指令系统 下面的这个就是我们的一个简单的计算机里面涉及到的指令&#xff1a; m就是我们的存储器里面的地址&#xff0c;可以理解为memory这个意思&#xff0c;r可以理解为rom这样的单词的首字母&#xff0c;帮助我们去进行这个相关的指令的记忆&#xff0c;不…...

mvc-service引入

什么是业务层 1&#xff09;Model1&#xff08;JSP&#xff09;和Model2&#xff08;模糊的mvc&#xff09;: MVC&#xff1a;Model(模型)&#xff0c;View(视图)&#xff0c;Controller&#xff08;控制器&#xff09; 视图层&#xff1a;用于数据展示以及用户交互的界…...

基于微信小程序的城市特色旅游推荐应用的设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

【暗光图像增强】【基于CNN的方法】2020-AAAI-EEMEFN

EEMEFN&#xff1a;Low-Light Image Enhancement via Edge-Enhanced Multi-Exposure Fusion Network EEMEFN&#xff1a;基于边缘增强多重曝光融合网络的低光照图像增强 AAAI 2020 论文链接 0.论文摘要 本研究专注于极低光照条件下的图像增强技术&#xff0c;旨在提升图像亮度…...

【Linux】ssh命令 – 安全的远程连接服务

原创&#xff1a;厦门微思网络 SSH命令的概念 ssh命令的功能是安全地远程连接服务器主机系统&#xff0c;作为OpenSSH套件中的客户端连接工具&#xff0c;ssh命令可以让我们轻松地基于SSH加密协议进行远程主机访问&#xff0c;从而实现对远程服务器的管理工‍作。 语法 ssh 参…...

AT9850B—单北斗导航定位芯片

AT9850B是一款高性能低功耗双频单北斗卫星导航接收机SOC单芯片。芯片集成射频前端和数字基带、多模式卫星信号处理引擎、电源管理功能&#xff0c;集成度高&#xff0c;外围应用电路简洁。 支持中国北斗B1I/B1C单频定位或B1I/B1C/B2a双频定位&#xff0c;支持北斗二号和三号&a…...

【开源Agent框架】CAMEL:角色扮演+任务分解

一、项目概览:重新定义智能体协作范式 CAMEL(Communicative Agents for “Mind” Exploration of Large Language Model Society)是由camel-ai社区开发的开源多智能体框架,致力于探索智能体的规模法则(Scaling Laws)。该项目通过构建包含百万级智能体的复杂社会系统,研…...

工业4G路由器IR5000公交站台物联网应用解决方案

随着城市化进程的加速&#xff0c;公共交通是智慧城市的重要枢纽。城市公共交通由无数的公交站台作作为节点组合而成&#xff0c;其智能化升级成为提升城市出行效率与服务质量的关键。传统公交站台信息发布滞后、缺乏实时性&#xff0c;难以满足乘客对公交信息快速获取的需求&a…...

idea中Lombok失效的解决方案

Lombok 是一个 Java 库&#xff0c;旨在通过注解简化 Java 代码的编写&#xff0c;减少样板代码&#xff0c;提高开发效率。它通过自动生成常见的代码&#xff08;如 getter、setter、构造函数等&#xff09;来减少开发者的手动编码工作。 一般Lombok失效有四步排查方案&#…...

如何借助iPaaS集成平台做好API 版本管理

在当今数字化快速发展的浪潮中&#xff0c;API 作为企业连接内外部系统、实现数据交互与业务协同的关键桥梁&#xff0c;在企业发展进程中扮演着至关重要的角色。它不仅支撑着企业的日常运营&#xff0c;更是企业拓展业务边界、提升竞争力的核心要素之一。然而&#xff0c;API …...

黑马k8s(九)

1.Pod-生命周期概述 2.Pod生命周期-创建和终止 3.Pod生命周期-初始化容器...

【超分辨率专题】一种考量视频编码比特率优化能力的超分辨率基准

这是一个Benchmark&#xff0c;超分辨率视频编码&#xff08;2024&#xff09; 专题介绍一、研究背景二、相关工作2.1 SR的发展2.2 SR benchmark的发展 三、Benchmark细节3.1 数据集制作3.2 模型选择3.3 编解码器和压缩标准选择3.4 Benchmark pipeline3.5 质量评估和主观评价研…...

vs2019及以后版本cmd指定编译环境文件的路径

1、找到文件路径 C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build 2、使用方法&#xff0c;启动cmd,依次输入对应指令&#xff0c;即可切换到相应环境...

【kafka】基本命令

创建 Kafka Topic 的命令 以下是创建 Kafka Topic 的几种常用方法&#xff1a; 1. 使用 kafka-topics.sh 基础命令&#xff08;Kafka 自带工具&#xff09; bin/kafka-topics.sh --create \--bootstrap-server <broker地址:端口> \--topic <topic名称> \--parti…...

提权脚本Powerup命令备忘单

1. 获取与加载 从 GitHub 下载&#xff1a;(New-Object Net.WebClient).DownloadFile("https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Privesc/PowerUp.ps1", "C:\Temp\PowerUp.ps1")本地加载&#xff1a;Import-Module .\Power…...

人工智能 (AI) 在无线接入网络 (RAN) 中的变革性作用

随着电信行业向更智能、更高效的系统迈进&#xff0c;将 AI 集成到 RAN 中已不再是可有可无&#xff0c;而是至关重要。 随着 6G 时代的到来&#xff0c;人工智能 (AI) 有望降低运营成本&#xff0c;并带来更大的盈利机会。AI-RAN 正处于这一变革的前沿&#xff0c;在 RAN 环境…...

一个完整的项目示例:taro开发微信小程序

前一周完成了一个项目&#xff0c;体测成绩转换的工具&#xff0c;没做记录&#xff0c;。这次计划开发一个地图应用小程序&#xff0c;记录一下。方便给使用的人。 一、申请微信小程序&#xff0c;填写相应的信息&#xff0c;取得开发者ID。这个要给腾讯地图使用的。 二、申…...

什么是SMBus

一、SMBus的定义与背景 基本概念 SMBus&#xff08;System Management Bus&#xff0c;系统管理总线&#xff09; 是一种基于IC&#xff08;Inter-Integrated Circuit&#xff09;协议的轻量级两线制串行通信总线&#xff0c;由Intel于1995年提出&#xff0c;主要用于低带宽系统…...

龙虎榜——20250516

上证缩量收阴线&#xff0c;小盘股表现相对更好&#xff0c;上涨的个股大于下跌的&#xff0c;日线已到前期压力位附近&#xff0c;注意风险。 深证缩量收假阳线&#xff0c;临近日线周期上涨末端&#xff0c;注意风险。 2025年5月16日龙虎榜行业方向分析 跨境电商&#xff…...

Python----神经网络(《Inverted Residuals and Linear Bottlenecks》论文概括和MobileNetV2网络)

一、论文 MobileNetV2 论文提出了一种新的移动架构&#xff0c;该架构提高了移动模型在多个任务和基准测试中的性能&#xff0c;以及在各种不同模型大小范围内的性能. 该架构基于倒残差结构&#xff0c;其中 shortcut 连接在 thin bottleneck 层之间. 中间的 expansion 层使用轻…...

React Flow 简介:构建交互式流程图的最佳工具

本文为《React Agent&#xff1a;从零开始构建 AI 智能体》专栏系列文章。 专栏地址&#xff1a;https://blog.csdn.net/suiyingy/category_12933485.html。项目地址&#xff1a;https://gitee.com/fgai/react-agent&#xff08;含完整代码示​例与实战源&#xff09;。完整介绍…...