user_ch-ml
2025-07-02 3ef3367fb535a41f08ff5ea87a62849d661a45e0
Merge branch 'master' of ssh://115.28.86.8:29418/~admin/智能网联_25-0305_617_v1
4个文件已添加
334 ■■■■■ 已修改文件
Server/王鹏哲/code/logger.h 334 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Server/王鹏哲/log/日志_王鹏哲_20250629.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/王鹏哲/log/日志_王鹏哲_20250630.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/王鹏哲/log/日志_王鹏哲_20250701.doc 补丁 | 查看 | 原始文档 | blame | 历史
Server/ÍõÅôÕÜ/code/logger.h
New file
@@ -0,0 +1,334 @@
#pragma once
#include "common.h"
#include <cstring> // ç”¨äºŽstrerror
#include <cstdio>  // ç”¨äºŽstd::rename, std::remove
#include <utility> // ç”¨äºŽstd::forward
// æ—¥å¿—级别枚举
enum class LogLevel {
    TRACE,   // æœ€è¯¦ç»†çš„跟踪信息
    DEBUG,   // è°ƒè¯•信息
    INFO,    // å¸¸è§„信息
    WARNING, // è­¦å‘Šä¿¡æ¯
    ERRORL,  // é”™è¯¯ä¿¡æ¯
    FATAL    // ä¸¥é‡é”™è¯¯
};
// å°†æ—¥å¿—级别转换为字符串
inline const char* levelToString(LogLevel level) {
    switch (level) {
    case LogLevel::TRACE:   return "TRACE";
    case LogLevel::DEBUG:   return "DEBUG";
    case LogLevel::INFO:    return "INFO";
    case LogLevel::WARNING: return "WARNING";
    case LogLevel::ERRORL:  return "ERROR";
    case LogLevel::FATAL:   return "FATAL";
    default:                return "UNKNOWN";
    }
}
// æ—¥å¿—配置结构
struct LogConfig {
    LogLevel minLevel = LogLevel::INFO; // æœ€å°æ—¥å¿—级别
    bool consoleOutput = true;          // æ˜¯å¦è¾“出到控制台
    bool fileOutput = false;            // æ˜¯å¦è¾“出到文件
    std::string logFilePath = "temp.log";// æ—¥å¿—文件路径
    bool includeTimestamp = true;       // æ˜¯å¦åŒ…含时间戳
    bool includeThreadId = false;       // æ˜¯å¦åŒ…含线程ID
    size_t maxFileSize = 10 * 1024 * 1024; // æœ€å¤§æ–‡ä»¶å¤§å° (10MB)
    int maxBackupFiles = 5;             // æœ€å¤§å¤‡ä»½æ–‡ä»¶æ•°
};
class Logger {
public:
    // èŽ·å–æ—¥å¿—å®žä¾‹
    static Logger& instance() {
        static Logger instance;
        return instance;
    }
    // é…ç½®æ—¥å¿—系统
    void configure(const LogConfig& config) {
        std::lock_guard<std::mutex> lock(configMutex_);
        config_ = config;
        // å¦‚果启用文件输出,确保文件已打开
        if (config.fileOutput) {
            openLogFile();
        }
    }
    // è®°å½•日志 (模板方法,支持任何可流式输出的类型)
    template<typename... Args>
    void log(LogLevel level, Args&&... args) {
        if (shutdown_) return;
        // å¤åˆ¶é…ç½®ä»¥æœ€å°åŒ–锁范围
        LogConfig currentConfig;
        {
            std::lock_guard<std::mutex> lock(configMutex_);
            if (level < config_.minLevel) return;
            currentConfig = config_;
        }
        // æž„造日志消息
        std::ostringstream oss;
        formatLogPrefix(oss, level, currentConfig);
        using expander = int[];
        (void)expander {
            0, (void(oss << std::forward<Args>(args)), 0)...
        };
        // æ·»åŠ æ¢è¡Œç¬¦
        oss << '\n';
        std::string message = oss.str();
        // ç›´æŽ¥å†™å…¥æ—¥å¿—
        /*writeLog(message);*/
        // å°†æ—¥å¿—消息加入队列
        {
            std::lock_guard<std::mutex> lock(queueMutex_);
            logQueue_.push(std::move(message));
        }
        // é€šçŸ¥æ—¥å¿—线程有新消息
        queueCond_.notify_one();
    }
    // ä¾¿æ·æ—¥å¿—方法
    template<typename... Args> void trace(Args&&... args) {
        log(LogLevel::TRACE, std::forward<Args>(args)...);
    }
    template<typename... Args> void debug(Args&&... args) {
        log(LogLevel::DEBUG, std::forward<Args>(args)...);
    }
    template<typename... Args> void info(Args&&... args) {
        log(LogLevel::INFO, std::forward<Args>(args)...);
    }
    template<typename... Args> void warning(Args&&... args) {
        log(LogLevel::WARNING, std::forward<Args>(args)...);
    }
    template<typename... Args> void error(Args&&... args) {
        log(LogLevel::ERRORL, std::forward<Args>(args)...);
    }
    template<typename... Args> void fatal(Args&&... args) {
        log(LogLevel::FATAL, std::forward<Args>(args)...);
        flush();
        std::exit(EXIT_FAILURE);
    }
    // åˆ·æ–°æ—¥å¿—缓冲区
    void flush() {
        std::lock_guard<std::mutex> lock(fileMutex_);
        if (logFile_.is_open()) {
            logFile_.flush();
        }
    }
    // æžæž„函数
    ~Logger() {
        shutdown();
        flush();
    }
    // å®‰å…¨å…³é—­æ—¥å¿—系统
    void shutdown() {
        if (shutdown_) return;
        shutdown_ = true;
        queueCond_.notify_all();  // å”¤é†’线程以处理退出
        if (workerThread_.joinable()) {
            workerThread_.join(); // ç­‰å¾…线程结束
        }
        flush();  // æœ€ç»ˆåˆ·æ–°
    }
    // åˆ é™¤æ‹·è´æž„造函数和赋值运算符
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
private:
    LogConfig config_;                      // æ—¥å¿—配置
    std::ofstream logFile_;                 // æ—¥å¿—文件流
    std::mutex configMutex_;                // é…ç½®äº’斥锁
    std::mutex fileMutex_;                  // æ–‡ä»¶æ“ä½œäº’斥锁
    std::atomic<bool> shutdown_{ false };   // å…³é—­æ ‡å¿—
    // æ–°å¢žçº¿ç¨‹å®‰å…¨é˜Ÿåˆ—相关成员
    std::queue<std::string> logQueue_;      // æ—¥å¿—消息队列
    std::mutex queueMutex_;                 // é˜Ÿåˆ—互斥锁
    std::condition_variable queueCond_;     // é˜Ÿåˆ—条件变量
    std::thread workerThread_;              // æ—¥å¿—写入线程
    // ç§æœ‰æž„造函数
    Logger() {
        // å¯åŠ¨æ—¥å¿—å†™å…¥çº¿ç¨‹
        workerThread_ = std::thread(&Logger::processLogs, this);
    };
    // æ—¥å¿—处理线程函数
    void processLogs() {
        while (true) {
            std::unique_lock<std::mutex> lock(queueMutex_);
            // ç­‰å¾…新日志或关闭信号
            queueCond_.wait(lock, [this] {
                return !logQueue_.empty() || shutdown_;
                });
            // å¤„理关闭信号
            if (shutdown_ && logQueue_.empty()) {
                break;
            }
            // å–出所有待处理日志
            std::queue<std::string> tempQueue;
            std::swap(logQueue_, tempQueue);
            lock.unlock();
            // å¤„理所有取出的日志
            while (!tempQueue.empty()) {
                writeLog(tempQueue.front());
                tempQueue.pop();
            }
        }
    }
    // æ ¼å¼åŒ–日志前缀
    void formatLogPrefix(std::ostringstream& oss, LogLevel level, const LogConfig& config) {
        // æ—¥å¿—级别标签
        oss << "[" << levelToString(level) << "] ";
        // æ—¶é—´æˆ³
        if (config.includeTimestamp) {
            auto now = std::chrono::system_clock::now();
            auto in_time_t = std::chrono::system_clock::to_time_t(now);
            auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                now.time_since_epoch()) % 1000;
            std::tm tm;
#ifdef _WIN32
            localtime_s(&tm, &in_time_t);
#else
            localtime_r(&in_time_t, &tm);
#endif
            oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
            oss << '.' << std::setfill('0') << std::setw(3) << ms.count() << " ";
        }
        // çº¿ç¨‹ID
        if (config.includeThreadId) {
            oss << "[Thread:" << std::this_thread::get_id() << "] ";
        }
    }
    // æ‰“开日志文件
    void openLogFile() {
        // å…³é—­å½“前文件(如果已打开)
        if (logFile_.is_open()) {
            logFile_.close();
        }
        // æ£€æŸ¥æ–‡ä»¶å¤§å°ï¼Œå¿…要时轮转
        std::ifstream in(config_.logFilePath, std::ios::binary | std::ios::ate);
        if (in) {
            auto size = in.tellg();
            if (static_cast<size_t>(size) >= config_.maxFileSize) {
                rotateLogFiles();
            }
        }
        in.close();
        // æ‰“开新日志文件
        logFile_.open(config_.logFilePath, std::ios::out | std::ios::app);
        if (!logFile_.is_open()) {
            std::cerr << "Failed to open log file: "
                << config_.logFilePath << " - "
                << errno << std::endl;
        }
    }
    // è½®è½¬æ—¥å¿—文件
    void rotateLogFiles() {
        // åˆ é™¤æœ€æ—§çš„备份文件
        if (config_.maxBackupFiles > 0) {
            std::string oldestFile = config_.logFilePath + "." + std::to_string(config_.maxBackupFiles);
            std::remove(oldestFile.c_str());
            // é‡å‘½åçŽ°æœ‰å¤‡ä»½æ–‡ä»¶
            for (int i = config_.maxBackupFiles - 1; i >= 1; i--) {
                std::string oldName = config_.logFilePath + "." + std::to_string(i);
                std::string newName = config_.logFilePath + "." + std::to_string(i + 1);
                if (fileExists(oldName)) {
                    std::rename(oldName.c_str(), newName.c_str());
                }
            }
            // é‡å‘½åå½“前日志文件为备份1
            if (fileExists(config_.logFilePath)) {
                std::string newName = config_.logFilePath + ".1";
                std::rename(config_.logFilePath.c_str(), newName.c_str());
            }
        }
    }
    // æ£€æŸ¥æ–‡ä»¶æ˜¯å¦å­˜åœ¨
    bool fileExists(const std::string& path) {
        std::ifstream f(path);
        return f.good();
    }
    // å®žé™…写入日志
    void writeLog(const std::string& message) {
        LogConfig currentConfig;
        {
            std::lock_guard<std::mutex> configLock(configMutex_);
            currentConfig = config_;
        }
        // è¾“出到控制台
        if (currentConfig.consoleOutput) {
            if (message.find("[ERROR]") != std::string::npos ||
                message.find("[FATAL]") != std::string::npos) {
                std::cerr << message;
            }
            else {
                std::cout << message;
            }
        }
        // è¾“出到文件
        if (currentConfig.fileOutput) {
            std::lock_guard<std::mutex> fileLock(fileMutex_);
            if (!logFile_.is_open() || !logFile_.good()) {
                openLogFile();
            }
            if (logFile_.good()) {
                logFile_ << message;
                logFile_.flush(); // å®žæ—¶åˆ·æ–°åˆ°ç£ç›˜
                // æ£€æŸ¥æ–‡ä»¶å¤§å°
                auto pos = logFile_.tellp();
                if (static_cast<size_t>(pos) >= currentConfig.maxFileSize) {
                    logFile_.close();
                    rotateLogFiles();
                    logFile_.open(currentConfig.logFilePath, std::ios::out | std::ios::app);
                }
            }
        }
    }
};
// æ—¥å¿—宏定义 - æä¾›æ–‡ä»¶åå’Œè¡Œå·ä¿¡æ¯
#define LOG_TRACE(...)   Logger::instance().trace("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
#define LOG_DEBUG(...)   Logger::instance().debug("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
#define LOG_INFO(...)    Logger::instance().info(__VA_ARGS__)
#define LOG_WARN(...)    Logger::instance().warning("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
#define LOG_ERROR(...)   Logger::instance().error("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
#define LOG_FATAL(...)   Logger::instance().fatal("(", __FILE__, ":", __LINE__, ") ", __VA_ARGS__)
Server/ÍõÅôÕÜ/log/ÈÕÖ¾_ÍõÅôÕÜ_20250629.doc
Binary files differ
Server/ÍõÅôÕÜ/log/ÈÕÖ¾_ÍõÅôÕÜ_20250630.doc
Binary files differ
Server/ÍõÅôÕÜ/log/ÈÕÖ¾_ÍõÅôÕÜ_20250701.doc
Binary files differ