muduo 10 Logger日志

目录

 构造函数:

Logger::setLogLevel设置日志级别

 Logger::log写日志

Logger.h

使用宏定义优点:

注意:

如何使用:

Logger.cc


         noncopyable类防止派生类对象进行拷贝构造,或者是赋值操作,但是能够让派生类对象正常的构造跟析构。muduo网络库的日志系统,日志对于一个软件来说呢,还是非常非常重要的。

日志级别:

        infer: 正常的一个日志输出,打印一些重要的流程信息;

        error:打印错误信息,但不影响软件继续进行下去;

        fatal: 系统是无法正常向下继续运行,输出关键的日志信息,然后exit;

        debug: 调试信息呢,一般来说是非常非常多的,可能我们在系统正常运行的情况下,会默认把debug日志关掉,当我们需要去输出debug日志的时候,再打开一个开关。

         定义一个日志类,由 noncopyable类继承而来,私有化构造函数,静态成员函数获取唯一日志实列对象,包括设置日志级别、写入日志信息函数。

 构造函数:

         单例模式的一种,将构造函数放到静态函数中,使用了静态局部变量的概念,静态局部变量的生命周期延长至整个程序运行期间,确保只有在第一次调用instance函数时才会创建Logger实例,在后续调用时直接返回创建的实例,并在程序退出时销毁。该实现方式是线程安全的。

Logger::setLogLevel设置日志级别

定义日志枚举信息: 

 Logger::log写日志

Logger.h

#pragma once

#include <string>

#include "noncopyable.h"

//LOG_INFO("%s %d", arg1, arg2)
//__VA_ARGS__获取可变参的宏
//logmsgFormat:字符串,后面...是可变参
#define LOG_INFO(logmsgFormat, ...) \
    do \
    { \
        Logger &logger = Logger::instance(); \
        logger.setLogLevel(INFO); \
        char buf[1024] = {0}; \
        snprintf(buf, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buf); \
    } while(0) 

#define LOG_ERROR(logmsgFormat, ...) \
    do \
    { \
        Logger &logger = Logger::instance(); \
        logger.setLogLevel(ERROR); \
        char buf[1024] = {0}; \
        snprintf(buf, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buf); \
    } while(0) 

#define LOG_FATAL(logmsgFormat, ...) \
    do \
    { \
        Logger &logger = Logger::instance(); \
        logger.setLogLevel(FATAL); \
        char buf[1024] = {0}; \
        snprintf(buf, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buf); \
        exit(-1); \
    } while(0) 

#ifdef MUDEBUG
#define LOG_DEBUG(logmsgFormat, ...) \
    do \
    { \
        Logger &logger = Logger::instance(); \
        logger.setLogLevel(DEBUG); \
        char buf[1024] = {0}; \
        snprintf(buf, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buf); \
    } while(0) 
#else
    #define LOG_DEBUG(logmsgFormat, ...)
#endif

//定义日志的级别  INFO(正常的日志输出)  ERROR(错误,不影响软件继续向下执行)
//  FATAL(毁灭性的打击,系统无法正常向下运行)  DEBUG(调试信息,一般是关闭的) 
enum LogLevel
{
    INFO, //普通信息
    ERROR,//错误信息
    FATAL,//core信息
    DEBUG,//调试信息
};

//输出一个日志类
class Logger : noncopyable
{
public:
    //获取日志唯一的实例对象
    static Logger& instance();
    //设置日志级别
    void setLogLevel(int level);
    //写日志
    void log(std::string msg);
private:
    int logLevel_;
};

      这里日志只需要打印出我们所需的信息,不需要用户去获取日志实例然后再设置日历级别再写日志,直接定义成四种宏,使用更方便。

        使用格式化字符形式进行日志输出。

使用宏定义优点:

        1.代码简洁:使用宏定义可以将一系列操作封装在一个宏中,代码读起来更简洁;

        2. 灵活性,宏定义可以接收不同数量的参数,并使用可变参数列表来处理;

        3. 高可定制性,宏定义允许开发者根据自己的需求自定义日志格式、日志级别等;

        4. 低开销:宏定义在编译时进行替换,不会引入额外函数调用开销。

注意:

        使用do{}while(0)来确保宏定义展开有正确的语法结构。

        使用##_VA_ARGS_可变参数占位符,它可以接收任意数量和任意类型的参数,需要放在参数化列表的末尾。

        对于debug日志,一般不使用时将其关闭,因为debug日志一般信息比较多,一直开着占用资源,所以我们定义#ifdef #endif 条件编译指令。

如何使用:

        LOG_INFO("%s %d", arg1, arg2)

Logger.cc

#include "Logger.h"
#include "Timestamp.h"

#include <iostream>

//获取日志唯一的实例对象
Logger& Logger::instance()
{
    static Logger logger;
    return logger;
}

//设置日志级别
void Logger::setLogLevel(int level)
{
    logLevel_ = level;
}

//写日志  [级别信息] time : msg
void Logger::log(std::string msg)
{
    switch (logLevel_)
    {
    case INFO:
        std::cout << "[INFO]";
        break;
    case ERROR:
        std::cout << "[ERROR]";
        break;
    case FATAL:
        std::cout << "[FATAL]";
        break;
    case DEBUG:
        std::cout << "[DEBUG]";
        break;
    default:
        break;
    }

    //打印时间和msg
    std::cout << Timestamp::now().toString() << " : " << msg << std::endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值