C++实现简单的日志logger输出

原文链接:https://blog.csdn.net/qq_21334991/article/details/79282622
本文是根据原文,结合自己的的思考,增加了一下说明。
1、先看一下日志的使用
日志可以将程序的一些调试、错误等信息保存到文件(或者打印出来),便于程序的调试以及故障查询等。

#include <iostream>
#include "Logger.h"
using namespace std;
int main(int argc, char *argv) {
    LOG(INFO)<<"helloworld";
    return 0;
}

运行结果如下:
从上面的可以看出,使用日志时,只需要加上如下类似语句:

LOG(INFO)<<"helloworld";
//使用日志时,只需要指明日志的级别和要输出的信息即可
//格式:LOG(级别)<<"输出的信息";

2、日志输出的实现原理
上面以及提到,使用日志时,只需要在代码中加上如下类似语句:
LOG(INFO)<<“helloworld”;
既然是输出流,所以实现肯定是通过输出流对象来实现的。LOG(INFO)流对象的实现代码如下:

//LOG()宏定义如下:
#define LOG(log_rank)   \
Logger(log_rank).start(log_rank, __LINE__,__FUNCTION__)

//Logger类的start函数实现如下:
std::ostream& Logger::start(log_rank_t log_rank,
                            const int line,
                            const std::string&function)
{
    time_t tm;
    time(&tm);
    char time_string[128];
    ctime_r(&tm, time_string);
    return getStream(log_rank) << time_string
                               << "function (" << function << ")"
                               << "line " << line<<" "
                               <<std::flush;
}

从上面的代码可以看出,日志输出的原理为:
LOG(INFO)为一个宏函数,宏展开构造了一个Logger类对象,然后调用该对象的start函数,而start函数返回类型为流对象类型,因此,LOG(INFO)获得了一个输出流对象,然后就可以根据该对象进行输出了。
3、日志涉及的几个关键问题
(1)怎么输出 (上面已经提到,是通过获取流对象)
(2)输出对象(输出到文件保存,还是标准输出对象显示器)
(3)日志的级别 (根据不同需求,输出的日志级别不同,并且可以将不同级别的日志分类保存)
(4)日志文件的保存 (如果日志保存到文件,需要指明文件把保存的路径)

下面结合Logger类和上面几个关键问题逐一分析:

class Logger {
    friend void initLogger(const std::string& info_log_filename,
                           const std::string& warn_log_filename,
                           const std::string& erro_log_filename);
 
public:
    //构造函数
    Logger(log_rank_t log_rank) : m_log_rank(log_rank) {};
 
    ~Logger();
    ///
    /// \brief 写入日志信息之前先写入的源代码文件名, 行号, 函数名
    /// \param log_rank 日志的等级
    /// \param line 日志发生的行号
    /// \param function 日志发生的函数
    static std::ostream& start(log_rank_t log_rank,
                               const int line,
                               const std::string& function);
 
private:
    ///
    /// \brief 根据等级获取相应的日志输出流
    ///
    static std::ostream& getStream(log_rank_t log_rank);
 
    static std::ofstream m_info_log_file;                   ///< 信息日子的输出流
    static std::ofstream m_warn_log_file;                  ///< 警告信息的输出流
    static std::ofstream m_error_log_file;                  ///< 错误信息的输出流
    log_rank_t m_log_rank;                             ///< 日志的信息的等级
};

Logger包含的成员函数和变量如下:
(1)公共接口
Logger(log_rank_t log_rank) :构造函数,构建个Logger类对象,需要指明该对象的打印级别
static std::ostream& start():获取输出流对象
(2)私有成员函数
static std::ostream& getStream(log_rank_t log_rank)
根据日志输出位置(显示器or文件),决定获取的成员函数是标准输出对象cout还是文件流对象 m_info_log_file/ m_warn_log_file/ m_error_log_file
(3)成员变量
static std::ofstream m_info_log_file; ///< 信息日子的输出流
static std::ofstream m_warn_log_file; ///< 警告信息的输出流
static std::ofstream m_error_log_file; ///< 错误信息的输出流
log_rank_t m_log_rank; ///< 日志的信息的等级
(4)友元函数
friend void initLogger(const std::string& info_log_filename,
const std::string& warn_log_filename,
const std::string& erro_log_filename);
主要用于指定不同级别日志的输出路径。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值