# WLog **Repository Path**: fengxian21/WLog ## Basic Information - **Project Name**: WLog - **Description**: 用c++写的日志系统 - **Primary Language**: C++ - **License**: 0BSD - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-06-29 - **Last Updated**: 2026-10-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # WLog 一个轻量级的 C++11 日志库,无三方依赖(仅标准库 + POSIX),支持多种输出目标、日志文件轮转和自动清理,Linux / macOS 可用。 ## 功能特性 - **多目标输出**:标准输出、文件输出或同时输出到两者,默认仅标准输出 - **日志轮转**:单个日志文件达到大小上限自动轮转,历史文件按时间戳命名归档 - **智能清理**:按文件数量 或 按保留时间 两种方式清理历史日志(二选一生效) - **线程安全**:文件输出通道由互斥锁全量保护,多线程并发写入安全 - **可靠落盘**:每行日志写入后立即 flush,进程崩溃时已打印日志不丢失 - **两套接口**:printf 风格宏 + 流式(`<<`)接口,按需选用 ## 快速开始 ### 编译项目 CMakeLists 使用 `GLOB_RECURSE` 收集源文件,**需要在项目目录外构建**: ```bash cd WLog cmake -S . -B ../build cmake --build ../build ../build/WLog # 运行演示程序 ``` ### 基础使用 ```cpp #include "WLog.h" int main() { // 初始化日志配置(不调用 init 则默认仅输出到标准输出) LogConfig config; config.outputTarget = WLOG_OUTPUT_BOTH; // 标准输出 + 文件 config.logDir = "./logs"; // 日志目录(自动创建) config.logBaseName = "app"; // 当前文件为 logs/app.log config.logFileMaxSize = 10 * 1024 * 1024; // 单个日志文件最大 10MB config.cleanMode = WLOG_CLEAN_BY_COUNT;// 按文件数量清理 config.logFileMaxCount = 5; // 最多保留 5 个文件(含当前文件) WLog::init(config); // printf 风格 Logi("这是信息日志"); Logw("这是警告日志, code=%d", 42); Loge("这是错误日志"); // 流式风格 WLogi() << "info stream " << 123; W_Logw(data); // W_Logi / W_Logw / W_Loge 宏 return 0; } ``` ### 配置选项(LogConfig) | 配置项 | 说明 | 默认值 | |-------|------|-------| | `outputTarget` | 输出目标:`WLOG_OUTPUT_STDOUT` / `WLOG_OUTPUT_FILE` / `WLOG_OUTPUT_BOTH` | `WLOG_OUTPUT_STDOUT` | | `logDir` | 日志目录,不存在时自动递归创建 | `"./logs"` | | `logBaseName` | 日志基础名,当前文件为 `logDir/logBaseName.log` | `"wlog"` | | `logFileMaxSize` | 单个日志文件大小上限(字节) | 50MB | | `cleanMode` | 清理策略:`WLOG_CLEAN_BY_COUNT` / `WLOG_CLEAN_BY_TIME`,二选一生效 | `WLOG_CLEAN_BY_COUNT` | | `logFileMaxCount` | 按数量清理时,最多保留的文件总数(含当前文件) | 10 | | `logFileMaxLiveDays` | 按时间清理时,历史文件保留天数(如 30 = 保留 1 个月) | 30 | ### 日志级别 ```cpp WLog::setLogLevel(WLog::DEBUG); // 默认 INFO,级别:ERROR / WARNING / INFO / DEBUG ``` 级别过滤对流式接口生效(`WLogd() << x` 在级别低于 DEBUG 时不输出)。 ## 工作原理 1. **初始化**:`WLog::init(config)` 在进程启动时调用一次(需在多线程写日志之前) 2. **日志写入**:两套接口最终都汇聚到 `LogInternal()`,整行格式化后按 `outputTarget` 分发到 stdout 和/或文件通道 3. **文件轮转**:当前文件超过 `logFileMaxSize` 时,rename 归档为时间戳文件名,再新开当前文件: ``` logs/app.log <- 当前正在写的文件(名字固定,方便 tail -f) logs/app_20260908_153000_123.log <- 轮转归档的历史文件 ``` 4. **自动清理**: - `WLOG_CLEAN_BY_COUNT`:每次轮转后,删除超出 `logFileMaxCount` 的最旧历史文件 - `WLOG_CLEAN_BY_TIME`:写日志路径中每 60 秒检查一次 + 启动时检查一次,删除 mtime 超过 `logFileMaxLiveDays` 天的历史文件(无后台线程) 5. **进程重启**:续写已有的当前文件并继承其大小(不会启动时归档,避免频繁重启产生碎片小文件) ## 线程安全 文件输出通道为单例,写入、轮转、清理全部在同一把 `std::mutex` 保护下执行,多线程并发写安全。`WLog::init()` 本身非线程安全,需在启动阶段单线程调用。 ## 性能 实测(macOS,clang -O2,SSD,每条约 100 字节): | 场景 | 吞吐 | |------|------| | 文件输出,单线程 | ≈ 48 万条/秒 | | 文件输出,4 线程并发 | ≈ 17.7 万条/秒 | | stdout + 文件,4 线程 | ≈ 14 万条/秒 | 设计上可靠性优先于吞吐:每行日志立即落盘,进程崩溃时不丢已打印的日志。 ## 目录结构 ``` WLog/ ├── CMakeLists.txt # CMake 构建配置 ├── main.cpp # 使用示例(多线程 + 轮转演示) └── WLogSrc/ ├── WLog.h/.cpp # 日志接口:printf 风格宏 + 流式类,init/级别控制 ├── WLogConfig.h # LogConfig 配置结构体与枚举 └── WLogFileSink.h/.cpp # 文件输出通道:线程安全写入、轮转、清理 ``` ## 许可证 本项目采用 MIT 许可证开源。