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

使用C++实现日志(3)

 1.5 日志系统的设计

1. 公共头文件 public.hpp

enum class LOG_LEVEL
{FATAL = 0, // 致命错误ERROR = 1, // 错误WARN = 2, // 警告INFO = 3, // 信息 DEBUG = 4, // 调试TRACE = 5, // 跟踪,追踪   NUM_LOG_LEVELS, // 日志级别数
};
static const char * LLtoStr[]=
{{"FATAL"},{"ERROR"},{"WARN"},{"INFO"},{"DEBUG"},{"TRACE"},{"NUM_LOG_LEVELS"},
};

2. 时间戳类型的设计

enum class LOG_LEVEL
{FATAL = 0, // 致命错误ERROR = 1, // 错误WARN = 2,  // 警告INFO = 3,  // 信息 DEBUG = 4, // 调试TRACE = 5, // 跟踪,追踪  NUM_LOG_LEVELS, // 日志级别数
};static const char* LLtoStr[] =
{"FATAL","ERROR","WARN","INFO","DEBUG","TRACE","NUM_LOG_LEVELS"
};namespace tulun
{class Timestamp{private:int64_t microSecondsSinceEpoch_; // 从1970年1月1日到现在的微秒数public:explicit Timestamp(int64_t ms = 0);void swap(Timestamp& that);// 按不同格式输出时间string toString() const;string toFormattedString(bool showMs = true) const;// 时间戳是否有效bool valid() const;// for internal usage.int64_t getMicroSecond() const;time_t getSecond() const;public:// 获得当前时间的时间戳static Timestamp now();// 获得失效的时间戳// static Timestamp invalid();static const int kMicroSecondsPerSecond = 1000 * 1000;};// 内联函数减少函数调用的时间消耗inline bool operator<(const Timestamp& lhs, const Timestamp& rhs){return lhs.getMicroSecond() < rhs.getMicroSecond();}inline bool operator==(const Timestamp& lhs, const Timestamp& rhs){return lhs.getMicroSecond() == rhs.getMicroSecond();}inline int64_t timeDifference(const Timestamp& high, const Timestamp& low){return high.getMicroSecond() - low.getMicroSecond();}inline Timestamp addTime(const Timestamp& timestamp, const double seconds){int64_t delta = static_cast<int64_t>(seconds * Timestamp::kMicroSecondsPerSecond);return Timestamp(delta);}
}

3. 日志流类型的设计

// C++
#include <string>
#include <sstream>
using namespace std;// own
#include "public.hpp"namespace tulun
{
class LogMessage
{
private:string header_;       // 字段/标题[时间戳];[日志级别];[文件名称];[函数名称];[行号]string text_;         // 正文信息LOG_LEVEL level_;     // 日志信息的级别 public:// [日志级别];[文件名称];[函数名称];[行号]  LogMessage(LOG_LEVEL level, const string& filename, const string& funcname, int linenumber);const string toString() const;LOG_LEVEL getLogLevel() const;// 添加正文信息template<typename T>LogMessage& operator<<(const T& txt){stringstream ss;ss << " : " << txt;text_ += ss.str();return *this;}
};
}

4. 日志类型设计

// C++
#include <functional> // function
#include <string>
using namespace std;// own
#include "public.hpp"
#include "LogMessage.hpp"namespace tulun
{
class Logger
{
public:// using OutputFunc = void (*)(const char *msg,int len);// using FlushFunc = void(*)();using OutputFunc = std::function<void(const std::string& msg)>;using FlushFunc = std::function<void()>;static OutputFunc output_;static FlushFunc flush_;public:static void setOutput(OutputFunc);static void setFlush(FlushFunc);private:LogMessage impl_;             static LOG_LEVEL s_level_;    // 日志级别public:// [日志级别];[文件名称];[函数名称];[行号]  Logger(tulun::LOG_LEVEL level, const string& name, const string& func, const int line);~Logger();LogMessage& stream();static void setLogLevel(LOG_LEVEL level);static LOG_LEVEL getLogLevel();
};     
}

5. 文件写类型的设计

// C++
#include <string>
#include <iostream>
#include <memory>
using namespace std;// C 
#include <stdio.h>// not thread safe
namespace tulun
{class AppendFile{private:static const int FILEBUFFSIZE = 64 * 1024;FILE* fp_;// char buffer_[FILEBUFFSIZE]; // 64K;//8192std::unique_ptr<char[]> buffer_;size_t writtenBytes_;  // 累计写入字节数size_t write(const char* info, const size_t len);public:AppendFile(const string& filename);~AppendFile();void append(const string& info);void append(const char* info, const size_t len);void flush();size_t writtenBytes() const;};
}

6. 日志文件类型的设计

// C++
#include <string>
#include <mutex>
#include <memory>
using namespace std;// C
#include <time.h> // own
#include "Timestamp.hpp"
#include "AppendFile.hpp"namespace tulun
{
class LogFile
{
private:const string basename_;       // 日志文件名basename const size_t rollSize_;       // 日志文件达到rollSize时生成新文件const int flushInterval_;     // 日志写入间隔时间(秒级)const int checkEveryN_;       // 每调用checkEveryN_次日志写就滚动一次日志int count_;                   // 写文件的次数 private:time_t startOfPeriod_;        // 开始写日志的周期,同周期日志写入同一文件time_t lastRoll_;             // 最后一次滚动日志的时间 time_t lastFlush_;            // 上一次刷新日志文件时间private:std::unique_ptr<std::mutex> mutex_;std::unique_ptr<tulun::AppendFile> file_;static const int kRollPerSeconds_ = 60 * 60 * 24; // 滚动周期:1天private:// 不加锁的append方式void append_unlocked(const char* logline, const int len);// 获取日志文件的名称static string getLogFileName(const string& basename, const Timestamp& now);public:LogFile(const string& basename,   // 日志文件basename size_t rollSize,          // 日志文件达到rollsize生成新文件bool threadSafe = true,   // 线程安全控制项,默认为true// 当只有一个后端AsnycLogging和后端线程时可置为falseint flushInterval = 3,    // 日志写入间隔时间(秒级)int checkEveryN = 1024);  // 每调用checkEveryN_次日志写就滚动一次日志~LogFile();void append(const std::string& info);void append(const char* info, const int len);void flush();bool rollFile();
};
}

1.6 类图

http://www.dtcms.com/a/313491.html

相关文章:

  • sqli-labs:Less-23关卡详细解析
  • C的数据类型与变量
  • 2025 Java开发真实试题-阿里面试题分析
  • C语言与数据结构:从基础到实战
  • 机器学习——过采样(OverSampling),解决类别不平衡问题,案例:逻辑回归 信用卡欺诈检测
  • 前端工程化:Vue3(一)
  • 2025年EAAI SCI1区TOP,森林救援调度与路径规划:一种新型蚁群优化算法应用,深度解析+性能实测
  • 智能化门禁常见问题处理思路
  • Linux mount挂载选项详解(重点关注nosuid)
  • 使用Perl和库WWW::Curl的爬虫程序!
  • [spring-cloud: 服务注册]-源码解析
  • Spring Boot AOP 优雅实现异常重试机制
  • 多线程异步日志系统与实现及 TCP/IP C/S 模型
  • IO流-字节流-FileOutputStream
  • day50预训练模型 CBAM注意力
  • Effective C++ 条款20:宁以pass-by-reference-to-const替换pass-by-value
  • LeetCode 2122.还原原数组
  • centos7安装桌面客户软件并远程连接
  • 学习笔记《区块链技术与应用》第五天 分叉
  • Matlab 高斯牛顿法拟合曲线
  • 力扣-200.岛屿数量
  • 01数据结构-二叉搜索树
  • PAT 甲级题目讲解:1012《The Best Rank》
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-55,(知识点:STM32,外设及其特点)
  • 力扣-124.二叉树中的最大路径和
  • LLM调研
  • 计算用户日活:从数据设计到可视化的全流程(高频场景题)
  • 秋招笔记-8.3
  • AUTOSAR进阶图解==>AUTOSAR_RS_SystemTemplate
  • 元宇宙三维化会给游戏行业带来哪些改变?