timestamp时间戳
作用:高精度的时间封装 统一系统时间获取
设计详解 继承copyable 和 type类
copyable:空基类 标记类为值类型
Types.h:定义int64_t/string等基础类型别名
输出统一格式
TRACE:最详细的信息,通常用于调试。
DEBUG:调试信息,开发和调试时使用。
INFO:普通运行信息,系统正常运行时的重要事件。
WARN:警告信息,表示潜在问题但不影响程序运行。
ERROR:错误信息,程序出现错误但还能继续运行。
FATAL:严重错误,通常会导致程序终止。
日志消息通常由以下部分组成:
1. 时间戳:记录日志产生的精确时间。
2. 日志等级:如 TRACE、DEBUG、INFO、WARN、ERROR、FATAL。
3. 线程ID:产生日志的线程编号,便于多线程环境下排查问题。
4. 源文件名与行号:日志产生的代码位置,便于定位。
5. 日志内容:具体的日志信息。
示例格式:
2026-05-24 12:34:56.789 [INFO] [Thread 1] main.cpp:42 - 服务器启动成功
日志流操作是指通过类似C++标准流(如std::cout)的方式,使用<<操作符将各种类型的数据流式写入日志。
优点:
1. 语法简洁,易于使用。
2. 支持多种数据类型的拼接输出。
3. 可链式调用,便于组合复杂日志内容。
示例用法:
LOG_INFO << "服务器启动,端口: " << port << ", 状态: " << status;
实现方式:
重载operator<<,将不同类型的数据追加到日志缓冲区,最终在日志对象析构时统一输出。
日志支持的写入类型:
1. 普通文本日志文件(.log)
2. 按日期或大小自动切分的滚动日志文件
3. 支持标准输出/标准错误输出
4. 可扩展为二进制日志或系统日志
实现方式:
通过文件流或自定义文件写入类,将日志内容高效写入目标文件,并支持自动切分和归档。
日志刷盘操作是指将内存中的日志缓冲区内容写入磁盘文件,确保日志数据持久化。
常见刷盘策略:
1. 定时刷盘:每隔固定时间(如1秒)将缓冲区内容写入文件。
2. 条件刷盘:当缓冲区数据量达到阈值时自动刷盘。
3. 主动刷盘:关键日志(如FATAL)或程序退出时强制刷盘。
实现方式:
通常采用专用后台线程定时或按需将日志缓冲写入文件,提升性能并降低磁盘IO压力。
可通过fflush、fsync等系统调用实现数据落盘。
异步刷盘是指日志写入操作不在主线程直接进行磁盘IO,而是将日志内容先写入内存缓冲区,由专用后台线程异步写入文件。
优点:
1. 避免主线程阻塞,提高系统吞吐量。
2. 日志写入高效,适合高并发场景。
实现原理:
1. 主线程只负责将日志内容追加到缓冲区,速度极快。
2. 后台线程定期或按需将缓冲区内容写入磁盘。
3. 采用双缓冲或环形缓冲区,减少锁竞争。
典型实现:
主线程与后台线程通过线程安全队列或条件变量协作,保证日志数据及时落盘且主线程无感知。
线程池 = 预先创建好的一组线程 + 任务队列
不反复创建 / 销毁线程,提升性能、降低资源消耗
控制并发数,防止系统被大量线程压垮
统一管理线程生命周期
线程本身是操作系统重量级资源,创建 / 销毁都要走内核、分配 / 回收内存、触发上下文切换,每一步都有固定开销
固定大小的线程池:预先分配一组固定大小的线程池数量,每当有任务到达时,提交到线程池,启动一个线程来执行任务。
cmake .. 编译产物
cmake --build . --config Release