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

日志的实现

一、日志有什么作用

        在线程池(Thread Pool)中,日志(Logging)起着至关重要的作用,主要体现在以下几个方面:

  1. 调试和错误跟踪

    • 日志记录可以帮助开发者了解线程池的运行状态,包括线程的创建、执行和销毁等。

    • 当线程池中出现错误或异常时,日志可以提供详细的错误信息,帮助开发者快速定位和解决问题。

  2. 性能监控

    • 通过记录线程池的运行数据,如线程执行时间、资源消耗等,可以监控线程池的性能。

    • 日志可以帮助识别性能瓶颈,如线程创建和销毁的频率、任务执行时间等。

  3. 资源管理

    • 日志可以记录线程池中线程对资源的请求和释放情况,如内存申请和释放。

    • 这有助于确保资源被正确管理,避免资源泄漏。

  4. 审计和合规性

    • 在需要审计或需要符合特定合规性要求的场景中,日志可以记录所有关键操作,以满足审计和合规性要求。

  5. 故障恢复

    • 在系统崩溃或出现严重错误时,日志可以提供必要的信息,帮助进行故障恢复。

  6. 用户行为分析

    • 如果线程池服务于用户请求,日志可以记录用户的行为和请求,用于分析用户模式和偏好。

  7. 系统行为分析

    • 日志可以记录系统级别的信息,如系统负载、响应时间等,有助于理解系统的整体行为和性能。

  8. 调试并发

    • 在开发过程中,日志可以帮助开发者理解线程池的行为,特别是在并发环境中。

  9. 运行时信息

    • 日志可以记录线程池运行时的关键信息,如线程数量、任务队列长度等。

        为了有效地利用日志,通常需要实现一个日志系统或使用现有的日志库。在 C++ 中,可以使用标准库(如 <cstdio>)或第三方库(如 Boost.Log、log4cpp)来实现日志功能。日志系统应该设计为易于配置、易于访问,并且能够在不影响线程池的性能

二、日志的实现

1.LogStrategy

    LogStrategy(日志策略)是设计模式之一,它定义了日志记录系统如何创建、存储、访问和删除日志信息。在软件工程中,日志策略对于监控应用程序的行为、调试、审计和安全分析等方面非常重要。

#ifndef __LOG_HPP__
#define __LOG_HPP__#include <iostream>
#include "Mutex.hpp"
#include <string>
#include <filesystem>
#include <cstdio>
#include <sstream>
#include <fstream>
#include <memory>
#include <unistd.h>namespace LogModule
{using namespace MutexModule;const std::string gsep = "\r\n"; // gsep分隔符// 策略模式,C++多态// 刷新策略:a.显示器打印   b.向指定文件写入// 刷新策略:基类class LogStrategy{public:~LogStrategy() = default;virtual void SyncLog(const std::string &message) = 0;};// 显示器打印的策略:子类class ConsoleLogStrategy : public LogStrategy{public:ConsoleLogStrategy(){}void SyncLog(const std::string &message) override{LockGuard lockguard(_mutex);std::cout << message << gsep;}~ConsoleLogStrategy(){}private:Mutex _mutex;};// 文件打印日志的策略:子类const std::string defaultpath = "./log";const std::string defaultfile = "my.log";class FileLogStrategy : public LogStrategy{public:FileLogStrategy(const std::string &path = defaultpath, const std::string &file = defaultfile): _path(path), _file(file){LockGuard lockguard(_mutex);if (std::filesystem::exists(_path)){return;}try{std::filesystem::create_directories(_path);}catch (const std::exception &e){std::cerr << e.what() << '\n';}}void SyncLog(const std::string &message) override{LockGuard lockguard(_mutex);std::string filename = _path + (_path.back() == '/' ? "" : "/") + _file; // "./log/" + "my.log"std::ofstream out(filename, std::ios::app);                              // 追加写入的 方式打开// 打开文件:使用 std::ofstream 以追加模式(std::ios::app)打开日志文件。如果文件成功打开,继续执行;如果失败(out.is_open() 返回 false),则直接返回。if (!out.is_open()){return;}out << message << gsep;out.close();}private:std::string _path; // 日志文件路径std::string _file; // 日志文件本身Mutex _mutex;};// 形成一条完整的日志&&根据上面的策略,选择不同的刷新方式enum class LogLevel{DEBUG,INFO,WARNING,ERROR,FATAL};std::string Level2Str(LogLevel level){switch (level){case LogLevel::DEBUG:return "DEBUG";case LogLevel::INFO:return "INFO";case LogLevel::WARNING:return "WARNING";case LogLevel::ERROR:return "ERROR";case LogLevel::FATAL:return "FATAL";defaule:return "UNKNOWN";}}std::string GetTimeStamp(){time_t curr = time(nullptr);struct tm curr_tm;localtime_r(&curr, &curr_tm);char timebuffer[128];snprintf(timebuffer, sizeof(timebuffer), "%4d-%02d-%02d %02d:%02d:%02d",curr_tm.tm_year + 1900,curr_tm.tm_mon + 1,curr_tm.tm_mday,curr_tm.tm_hour,curr_tm.tm_min,curr_tm.tm_sec);return timebuffer;}// 1. 形成日志 && 2. 根据不同的策略,完成刷新class Logger{public:Logger(){EnableConsoleLogStrategy();}void EnableFileLogStrategy(){_fflush_strategy = std::make_unique<FileLogStrategy>();}void EnableConsoleLogStrategy(){_fflush_strategy = std::make_unique<ConsoleLogStrategy>();}// 表示的是未来的一条日志class LogMessage{public:LogMessage(LogLevel &level, std::string &src_name, int line_number, Logger &logger): _curr_time(GetTimeStamp()),_level(level),_pid(getpid()),_src_name(src_name),_line_number(line_number),_logger(logger){// 日志的左边部分,合并起来std::stringstream ss;ss << "[" << _curr_time << "] "<< "[" << Level2Str(_level) << "] "<< "[" << _pid << "] "<< "[" << _src_name << "] "<< "[" << _line_number << "] "<< "- ";_loginfo = ss.str();}// LogMessage() << "hell world" << "XXXX" << 3.14 << 1234template <typename T>LogMessage &operator<<(const T &info){// a = b = c =d;// 日志的右半部分,可变的std::stringstream ss;ss << info;_loginfo += ss.str();return *this;}~LogMessage(){if (_logger._fflush_strategy){_logger._fflush_strategy->SyncLog(_loginfo);}}private:std::string _curr_time;LogLevel _level;pid_t _pid;std::string _src_name;int _line_number;std::string _loginfo; // 合并之后,一条完整的信息Logger &_logger;};// 这里故意写成返回临时对象LogMessage operator()(LogLevel level, std::string name, int line){return LogMessage(level, name, line, *this);}~Logger(){}private:std::unique_ptr<LogStrategy> _fflush_strategy;};#define LOG(level) logger(level, __FILE__, __LINE__)
#define Enable_Console_Log_Strategy() logger.EnableConsoleLogStrategy()
#define Enable_File_Log_Strategy() logger.EnableFileLogStrategy()}#endif

相关文章:

  • 强化学习笔记(三)——表格型方法(蒙特卡洛、时序差分)
  • docker学习笔记2-最佳实践
  • # 05_Elastic Stack 从入门到实践(五)
  • 【图像变换】pytorch-CycleGAN-and-pix2pix的学习笔记
  • Linux系统编程 day7、8 信号(周日划水了)
  • LangChain + 文档处理:构建智能文档问答系统 RAG 的实战指南
  • Hyperlane:Rust Web框架的性能新标杆
  • 超详细mac上用nvm安装node环境,配置npm
  • 智慧能源安全新纪元:当能源监测遇上视频联网的无限可能
  • kafka监控kafka manager(CMAK)部署配置
  • Moritex大靶面远心镜头 助力晶圆外观检测
  • 榕壹云预约咨询系统:基于ThinkPHP+MySQL+UniApp打造的灵活预约小程序解决方案
  • 【日志体系】ELK Stack与云原生日志服务
  • 【计算机视觉】CV实战项目- CMU目标检测与跟踪系统 Object Detection Tracking for Surveillance Video
  • 24. git revert
  • Spring(第一章)
  • 11-DevOps-Jenkins Pipeline流水线作业
  • 剑指offer经典题目(五)
  • ORION:通过视觉-语言指令动作生成的一个整体端到端自动驾驶框架
  • WPF的发展历程
  • 三部门:对不裁员少裁员的参保企业实施稳岗返还政策至今年底
  • 人民日报评“我愿意跟他挨着”:城市要善待奋斗者,惩治作恶者
  • 诺奖得主等数十位经济学家发表宣言反对美关税政策
  • 寻找“香奈儿”代工厂
  • 世遗X时尚,七匹狼这场大秀秀出中国文化独特魅力
  • 人民文学奖颁出,董宇辉获传播贡献奖