c++ 基于 spdlog 日志类实现

at 6个月前  ca Cpp & C  pv 362  by touch  

为了使日志记录器支持自定义日志文件路径,你可以在 Logger 类中添加一个参数化的初始化函数,使得用户可以在实例化日志记录器时指定日志文件路径。

#include <iostream>
#include <memory>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/daily_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>

class Logger {
public:
    // 获取单例实例的静态方法
    static Logger& getInstance(const std::string& log_path = "logs/daily_logfile.log") {
        static Logger instance(log_path); // 局部静态变量保证线程安全
        return instance;
    }

    // 删除拷贝构造函数和赋值操作符
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;

    // 公共接口方法
    void logDebug(const std::string& message) {
        logger->debug(message);
    }

    void logTrace(const std::string& message) {
        logger->trace(message);
    }

    void logInfo(const std::string& message) {
        logger->info(message);
    }

    void logWarn(const std::string& message) {
        logger->warn(message);
    }

    void logError(const std::string& message) {
        logger->error(message);
    }

    void logCritical(const std::string& message) {
        logger->critical(message);
    }

private:
    std::shared_ptr<spdlog::logger> logger;

    // 私有构造函数
    Logger(const std::string& log_path) {
        try {
            // 创建按天旋转的文件 sink,每天创建一个新的日志文件,扩展名为 .log
            auto daily_file_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>(log_path, 0, 0);
            // 创建控制台 sink
            auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();

            // 创建多 sink logger
            spdlog::sinks_init_list sink_list = {daily_file_sink, console_sink};
            logger = std::make_shared<spdlog::logger>("multi_sink", sink_list.begin(), sink_list.end());

            // 设置日志级别
            logger->set_level(spdlog::level::trace);
            // 设置日志格式
            logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");

            // 注册 logger
            spdlog::register_logger(logger);
        } catch (const spdlog::spdlog_ex& ex) {
            std::cerr << "Log initialization failed: " << ex.what() << std::endl;
        }
    }

    // 私有析构函数
    ~Logger() {
        spdlog::drop_all();
    }
};

int main() {
    // 使用自定义路径创建单例模式的日志记录器
    Logger& logger = Logger::getInstance("custom_logs/daily_logfile.log");
    logger.logDebug("This is a debug message");
    logger.logTrace("This is a trace message");
    logger.logInfo("This is an info message");
    logger.logWarn("This is a warning message");
    logger.logError("This is an error message");
    logger.logCritical("This is a critical message");

    return 0;
}

解释

  1. Logger 类:

    • 创建按天旋转的文件 sink:spdlog::sinks::daily_file_sink_mt

    • 创建控制台 sink:spdlog::sinks::stdout_color_sink_mt

    • 创建一个多 sink logger,将文件 sink 和控制台 sink 组合在一起。

    • 设置日志级别为 trace,记录所有级别的日志。

    • 设置日志格式。

    • 注册 logger 以便全局访问。

    • daily_file_sink 参数 log_path 指定日志文件的路径,日志文件将被命名为 log_path.YYYY-MM-DD.log 格式。

    • 参数 0, 0 指定每天午夜(0点0分)旋转日志文件。

    • 静态方法 getInstance: 返回单例实例。使用局部静态变量确保线程安全(C++11 及以上)。增加了一个默认参数 log_path,使得可以指定日志文件的路径。

    • 删除拷贝构造函数和赋值操作符: 防止实例被复制。

    • 公共接口方法: 提供不同级别的日志记录方法。

    • 私有构造函数: 初始化 spdlog 日志记录器。

    • 私有析构函数: 清理 spdlog 资源。

    • 使用示例:

      • main 函数中,通过 Logger::getInstance("custom_logs/daily_logfile.log") 获取单例实例,并调用日志记录方法。

    输出结果

    日志记录器会将日志同时输出到指定路径的 custom_logs/daily_logfile.YYYY-MM-DD.log 文件和标准输出(控制台)。日志文件会根据日期自动旋转,每天生成一个新的日志文件,输出内容根据设定的格式进行显示。

    通过这种方式,可以确保只有一个日志记录器实例在整个程序生命周期中存在,并且提供一个全局访问点来记录不同级别的日志消息,日志消息会被同时写入每天生成的新文件和标准输出。


    版权声明

    本文仅代表作者观点,不代表码农殇立场。
    本文系作者授权码农殇发表,未经许可,不得转载。

     

    扫一扫在手机阅读、分享本文

    已有0条评论
    您是本站第12279名访客 今日有0篇新文章 当前在线 10 人