C++实现的单例模式日志类

在实际生产中,日志是非常重要的调试工具,日志内容至少需要包括时间戳、日志级别、日志内容

推荐的日志库有:

google/glog: C++ implementation of the Google logging module (github.com)

 Apache Log4cxx: Apache Log4cxx

自己实现的话, 日志内容应该包括,精确到微秒的时间戳,日志级别(DEBUG / INFO / WARN / ERROR / FATAL),日志写入时的代码文件名,代码行号和函数名,例如

2024-05-25 23:46:07.998429 [FATAL] This is a fatal message (File=C:/Users/Yezi/Desktop/Logger/main.cpp Function=main Line=9)

并且我希望日志是这样使用的

#include "logger.h"

int main() {
    Logger::InitLogger("logfile.txt");
    LOG(LogLevel::DEBUG, "This is a debug message");
    LOG(LogLevel::INFO, "This is an info message");
    LOG(LogLevel::WARN, "This is a warning message");
    LOG(LogLevel::ERROR, "This is an error message");
    LOG(LogLevel::FATAL, "This is a fatal message");
    return 0;
}

而不是这样使用的

int main() {
    Logger logger("logfile.txt");

    // 示例使用
    LOG(logger, LogLevel::DEBUG, "This is a debug message");
    LOG(logger, LogLevel::INFO, "This is an info message");
    LOG(logger, LogLevel::WARN, "This is a warning message");
    LOG(logger, LogLevel::ERROR, "This is an error message");
    LOG(logger, LogLevel::FATAL, "This is a fatal message");

    return 0;
}

这意味着我们需要一个单例模式的实现,需要将类实例静态化,由一个静态函数返回类实例的引用,由于静态变量只会初始化一次,所以每次返回的都是同一个实例
同时我们希望能够保留可以更改类实例初始化的参数,例如日志文件名,因此需要一个初始化的静态函数来进行类实例的初始化

//
// Created by YEZI on 2024/5/25.
//

#ifndef LOGGER_H
#define LOGGER_H

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>

// 定义日志级别
enum class LogLevel { DEBUG, INFO, WARN, ERROR, FATAL };

class Logger {
private:
    int fd_ = -1;
    // 获取当前时间戳
    static std::string getCurrentTime() {
        // 获取当前时间点
        auto now = std::chrono::system_clock::now();
        // 将时间点转换为time_t
        auto now_time_t = std::chrono::system_clock::to_time_t(now);
        // 获取tm结构体
        std::tm time_info = *std::localtime(&now_time_t);
        // 构造时间字符串
        std::ostringstream oss;
        oss << std::put_time(&time_info, "%Y-%m-%d %H:%M:%S"); // 格式化时间
        // 获取微秒部分
        auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(
                                now.time_since_epoch()) % 1000000;
        oss << "." << std::setfill('0') << std::setw(6) << microseconds.count(); // 微秒部分
        return oss.str();
    }

    // 私有化构造函数
    explicit Logger(const char *filename) {
        // 打开日志文件
        fd_ = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0666);
        if (fd_ == -1) {
            std::cerr << "Failed to open log file\n";
        }
    }

public:
    ~Logger() {
        // 关闭日志文件
        if (fd_ != -1) {
            close(fd_);
        }
    }

    //初始化日志文件
    static void InitLogger(const char *filename) {
        getInstance(filename);
    }

    // 禁用拷贝构造函数和赋值运算符
    Logger(const Logger &) = delete;

    Logger &operator=(const Logger &) = delete;

    // 获取 Logger 实例的静态方法
    static Logger &getInstance(const char *filename = nullptr) {
        // 静态变量只会初始化一次
        static Logger instance(filename);
        return instance;
    }

    // 写日志函数
    void log(LogLevel level, const char *message, const char *file, int line, const char *function) const {
        std::string logLevelStr;
        switch (level) {
            case LogLevel::DEBUG:
                logLevelStr = "DEBUG";
                break;
            case LogLevel::INFO:
                logLevelStr = "INFO";
                break;
            case LogLevel::WARN:
                logLevelStr = "WARN";
                break;
            case LogLevel::ERROR:
                logLevelStr = "ERROR";
                break;
            case LogLevel::FATAL:
                logLevelStr = "FATAL";
                break;
        }

        // 构建日志消息
        std::string logMessage = getCurrentTime() + " [" + logLevelStr + "] " + message +
                                 " (File=" + file + " Function=" + function + " Line=" + std::to_string(line) + ")\n";

        // 写入日志到文件
        write(fd_, logMessage.c_str(), logMessage.size());
    }
};

// 宏定义简化日志调用
#define LOG(level, message) Logger::getInstance().log(level, message, __FILE__, __LINE__, __FUNCTION__)

#endif //LOGGER_H

代码维护在GitHub 

MaolinYe/Logger: C++实现的日志类,记录日志写入时的时间,可选的日志级别(DEBUG / INFO / WARN / ERROR / FATAL),日志内容,日志写入时的代码文件,代码行号和函数名 (github.com)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

MaolinYe(叶茂林)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值