log4cplus 封装

log4cplus 是一个C++ 的日志库,虽然说对于 log4cplus 的使用已经很简单了,但是我们还想更简单,也就是只需要使用一个宏就可以完成不同级别日志的输出。

因为 log4cplus 的日志输出不同级别的日志可以使用不同级别的宏来输出,我觉得将 log4cplus 直接封装为一个类,然后我们可以调用一个宏,然后传入这个日志的级别,后面就是可变参数列表,可以传入任意类型任意个数的参数,最后以空格分隔输出到文件中。

但是并不是说 log4cplus 直接会帮你输出到文件中,而是需要你自己配置的,但是这里我们并不讲配置,也不讲使用,只是简单的封装。

设计:
我们决定将这个类设计为一个单例类,我们也采用最简单的懒汉模式,然后我们只需要获取到日志类的对象,然后我们调用里面的 log 方法及完成日志的输出。

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define FILE_AND_LINE __FILE__ ":" TOSTRING(__LINE__) // 定义一个文件名和行号

// 定义日志级别宏
#define LOG4C(level, ...) \
    Log::getInstance().log(level, FILE_AND_LINE,##__VA_ARGS__)

// 错误级别(log4cplus 中还有一个错误级别,但是因为这里智能用到这几种,另外的一个用不到,所以就不写了,如果有需要的话,可以直接写到枚举中,然后在 log 方法中添加一个关于该错误级别的日志输出即可)
enum Level{
    DEBUG,
    INFO,
    WARNING,
    ERROR,
    FATAL
};


// 封装的 log4cplus 类(该类为单例模式,所以构造函数不能为 public 的,这里决定以 getInstance 函数来完成日志对象的输出)
class Log
{
public:
    ~Log(){}
    
    // 获取日志对象
    static Log &getInstance() {
        static Log instance;

        return instance;
    }

    // 日志对象的主要的函数,完成对日志的输出,因为这里需要的是可变参数列表,所以这里就使用可变模板参数列表
    template<typename... Args>
    void log(int level, Args... args) {
        // 解析可变模板参数列表,将里面的参数都解析为 string 类型
        std::string message = format_impl(args...);
        switch(level){
        case DEBUG:
            LOG4CPLUS_DEBUG(logger, message);
            break;
        case WARNING:
            LOG4CPLUS_WARN(logger, message);
            break;
        case INFO:
            LOG4CPLUS_INFO(logger, message);
            break;
        case ERROR:
            LOG4CPLUS_ERROR(logger, message);
            break;
        case FATAL:
            LOG4CPLUS_FATAL(logger, message);
            break;
        default:
            LOG4CPLUS_ERROR(logger, "No such error");
            break;
        }
    }

private:
    // 解析函数也是一个可变模板参数列表,这里我就不说明这个为什么可以解析了,如果有想知道的可以问一下ai
    template<typename T>
    std::string format_impl(const T& value){
        std::ostringstream oss;
        oss << value;
        return oss.str();
    }

    template<typename T, typename... Args>
    std::string format_impl(const T& first, const Args&... args){
        std::ostringstream oss;
        oss << first << " " << format_impl(args...);
        return oss.str();
    }

    log4cplus::Logger logger;

private:
    Log() {
        // 这个就是读取 log4cplus 的配置
       log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("/home/nano/log4cplus-2.0.8/build/log4cplusConfig"));
        // 获取日志记录器,
        logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("myLog"));
    }

    Log(const Log&);

    Log operator=(const Log&);
};

log 函数是用于日志输出的,但是我们不想每次都 getInstance 后调用 log 方法,所以我们定义一个宏,这个宏就会替换为这个函数的调用。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naxx Crazy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值