• 仿写muduo网络库:日志的简单实现


    日志级别

    // 定义日志的级别 INFO  ERROR  FATAL DEBUG
    enum LogLevel
    {
        INFO,   // 普通信息
        ERROR,  // 错误信息
        FATAL,  // core信息
        DEBUG   // 调试信息
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    日志类

    noncopyable

    在查看muduo库的源代码时,首先发现的是利用了基本的OOP思想。它有一个copyable和noncopyable头文件,方便后续的代码使用。

    #pragma once
    
    /*
    noncopyable被继承以后派生类对象可以正常的构造析构
    但不可以拷贝构造和赋值操作
    */
    
    class noncopyable
    {
    public:
        noncopyable(const noncopyable&) = delete;
        noncopyable& operator=(const noncopyable&) = delete;
    
    protected:
        noncopyable() = default;
        ~noncopyable() = default;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    日志类:主要有三个方法:

    1. 获取实例对象
    2. 设置日志级别
    3. 写日志
    #pragma once
    
    #include 
    #include 
    
    #include "noncopyable.h"
    #include "Timestamp.h"
    
    // LOG_INFO
    #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); \
        } 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 : public noncopyable
    {
    public:
        // 获取日志唯一的实例对象
        static Logger& instance();
        // 设置日志级别
        void setLogLevel(int level);
        // 写日志
        void log(std::string msg);
    private:
        int logLevel_;
        Logger(){}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    获取实例对象

    // 获取日志唯一的实例对象
    Logger& Logger::instance()
    {
        static Logger logger;
        return logger;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    设置日志级别

    // 设置日志级别
    void Logger::setLogLevel(int level)
    {
        logLevel_ = level;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    写日志

    // 写日志 [级别信息] 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    这里的格式采用的是【级别】+ 时间戳 + msg,所以需要时间类

    Timestamp.h

    #pragma once
    
    #include 
    #include 
    
    class Timestamp
    {
    public:
        Timestamp();
        explicit Timestamp(int64_t microSecondsSinceEpoch);
        static Timestamp now();
        std::string toString() const;
    
    private:
        int64_t microSecondsSinceEpoch_;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Timestamp.cc

    #include "Timestamp.h"
    #include 
    
    Timestamp::Timestamp() : microSecondsSinceEpoch_(0) {}
    
    Timestamp::Timestamp(int64_t microSecondsSinceEpoch)
        : microSecondsSinceEpoch_(microSecondsSinceEpoch)
    {}
    
    Timestamp Timestamp::now()
    {
        return Timestamp(time(NULL));
    }
    
    std::string Timestamp::toString() const
    {
        char buf[128] = {0};
        tm* tm_time = localtime(&microSecondsSinceEpoch_);
        snprintf(buf, 128, "%4d/%02d/%02d %02d:%02d:%02d",
            tm_time->tm_year + 1900,
            tm_time->tm_mon + 1,
            tm_time->tm_mday,
            tm_time->tm_hour,
            tm_time->tm_min,
            tm_time->tm_sec);
            return buf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    如何用WebSocket打造Web端IM即时通讯聊天
    网页抓取软件-免费网页自动采集抓取任意内容软件
    MySQL中的锁机制、MyISAM表锁、MyISAM表级锁争用情况、MyISAM并发插入Concurrent Inserts、MyISAM的锁调度
    网络请求中如何封装对话框并调用
    新火种AI|苹果要将苹果智能做成AI时代的APP Store?
    大二Web课程设计——张家界旅游网站设计与实现(HTML+CSS+JavaScript)
    使用 HelpLook Chatbot,让AI聊天机器人变成销售经理
    AcWing 4604. 集合询问
    新一代开源语音库CoQui TTS冲到了GitHub 20.5k Star
    编译原理复习——文法和语言2
  • 原文地址:https://blog.csdn.net/m0_56257585/article/details/126472688