| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- /**
- * log_manager.h - 内存日志缓冲管理系统
- * fix24 v36: 日志写入内存,定时刷盘,Web从内存读取
- */
- #ifndef LOG_MANAGER_H
- #define LOG_MANAGER_H
- #include <string>
- #include <deque>
- #include <mutex>
- #include <atomic>
- #include <thread>
- #include <condition_variable>
- // ==================== 日志条目结构 ====================
- struct LogEntry {
- std::string timestamp; // "2026-07-05 23:15:00"
- std::string level; // INFO / WARN / ERROR
- std::string message; // 日志内容(单行)
- size_t byte_size; // 该条目占用内存字节数
- LogEntry() : byte_size(0) {}
- LogEntry(const std::string& ts, const std::string& lv, const std::string& msg)
- : timestamp(ts), level(lv), message(msg) {
- byte_size = ts.size() + lv.size() + msg.size() + 32; // overhead
- }
- };
- // ==================== 日志状态(Web API返回) ====================
- struct LogStatus {
- std::string log_file_path; // 日志文件路径
- long file_size_mb; // 磁盘文件大小 (MB)
- long buffer_size_mb; // 缓冲区上限配置 (MB)
- double buffer_usage_percent; // 缓冲区使用率 (%)
- std::string flush_time; // 定时刷盘时间
- int retention_days; // 保留天数
- long line_count; // 内存中总条数
- std::string last_modified; // 最后修改时间(文件/刷盘)
- bool redirect_enabled; // stdout 重定向是否启用
- bool memory_enabled; // 内存模式是否启用
- long memory_usage_bytes; // 当前内存占用(字节)
- std::string last_flush_time; // 上次刷盘时间
- long total_flush_count; // 累计刷盘次数
- };
- // ==================== 内存日志缓冲区 ====================
- class MemoryLogBuffer {
- public:
- MemoryLogBuffer();
- ~MemoryLogBuffer();
- // 初始化(从config读取参数后调用)
- void init(size_t max_bytes, const std::string& flush_time,
- const std::string& log_file, int retention_days,
- bool redirect_stdout, bool auto_flush_on_exit);
- // 启动(创建刷盘线程 + stdout重定向)
- bool start();
- // 停止(刷盘 + 关闭线程)
- void stop();
- // 写入日志条目
- void push(const std::string& level, const std::string& message);
- // 获取最后N条
- std::deque<LogEntry> tail(int n);
- // 获取状态
- LogStatus get_status();
- // 手动刷盘到文件
- bool flush_to_file(std::string& error);
- // 清理过期日志
- bool cleanup_old_logs(std::string& error);
- // 信号处理调用(SIGTERM/SIGINT时调用)
- void signal_flush();
- // 全局单例
- static MemoryLogBuffer& instance();
- private:
- // 刷盘线程
- void flush_thread_func();
- // stdout读取线程(当redirect_stdout=true时)
- void stdout_reader_func();
- // 解析刷盘时间 "HH:MM" → 时、分
- bool parse_flush_time(const std::string& time_str, int& hour, int& minute);
- // 生成带日期的归档文件名
- std::string generate_archive_filename();
- // 获取当前时间字符串
- std::string current_timestamp();
- // 环形缓冲区
- std::deque<LogEntry> buffer_;
- size_t max_memory_bytes_;
- size_t current_bytes_;
- std::mutex mutex_;
- // 配置
- std::string log_file_; // PlateRecApp.log
- std::string flush_time_; // "23:20"
- int retention_days_;
- bool redirect_stdout_;
- bool auto_flush_on_exit_;
- bool enabled_; // enabled=1 内存模式, =0 直写模式
- // 刷盘线程
- std::thread flush_thread_;
- std::mutex flush_mutex_;
- std::condition_variable flush_cv_;
- std::atomic<bool> flush_running_;
- // stdout重定向
- std::thread stdout_thread_;
- int pipe_fd_[2]; // pipefd[0]=读端, pipefd[1]=写端
- int saved_stdout_; // 备份原始stdout fd
- int saved_stderr_; // 备份原始stderr fd
- std::atomic<bool> stdout_redirect_active_;
- // 统计
- std::atomic<long> total_flush_count_;
- std::string last_flush_time_;
- std::mutex stats_mutex_;
- };
- // ==================== 兼容旧接口(namespace log_mgr) ====================
- namespace log_mgr {
- // 获取日志状态
- LogStatus get_log_status();
- // 手动触发日志刷新(sync)
- bool flush_log(std::string &error);
- // 清理过期日志
- bool cleanup_old_logs(std::string &error);
- // 获取日志文件最后 N 行
- std::string tail_log(int lines);
- } // namespace log_mgr
- #endif // LOG_MANAGER_H
|