C++ 轻量级日志系统

C++ 轻量级日志系统(完整版)

Logger.h

cpp 复制代码
#ifndef LOGGER_H
#define LOGGER_H

#include <string>
#include <fstream>
#include <mutex>
#include <ctime>

// 日志等级
enum LogLevel {
    DEBUG,
    INFO,
    WARNING,
    ERROR,
    FATAL
};

class Logger {
public:
    static Logger& instance();

    // 设置输出文件(不设置则只输出控制台)
    void setLogFile(const std::string& filename);

    // 核心日志输出
    void log(LogLevel level, const char* file, int line, const char* format, ...);

private:
    Logger();
    ~Logger();

    std::string getLevelStr(LogLevel level);
    std::string getTime();
    void printColor(LogLevel level);

    std::ofstream m_file;
    std::mutex m_mutex;
    bool m_useFile;
};

// 宏定义,简化调用
#define LOGD(...) Logger::instance().log(DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define LOGI(...) Logger::instance().log(INFO, __FILE__, __LINE__, __VA_ARGS__)
#define LOGW(...) Logger::instance().log(WARNING, __FILE__, __LINE__, __VA_ARGS__)
#define LOGE(...) Logger::instance().log(ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define LOGF(...) Logger::instance().log(FATAL, __FILE__, __LINE__, __VA_ARGS__)

#endif // LOGGER_H

Logger.cpp

cpp 复制代码
#include "Logger.h"
#include <cstdarg>
#include <iostream>
#include <iomanip>

#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

Logger::Logger() : m_useFile(false) {}
Logger::~Logger() {
    if (m_file.is_open()) m_file.close();
}

Logger& Logger::instance() {
    static Logger logger;
    return logger;
}

void Logger::setLogFile(const std::string& filename) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_file.is_open()) m_file.close();
    m_file.open(filename, std::ios::out | std::ios::app);
    m_useFile = m_file.is_open();
}

std::string Logger::getLevelStr(LogLevel level) {
    switch (level) {
        case DEBUG: return "DEBUG";
        case INFO:  return "INFO ";
        case WARNING: return "WARN ";
        case ERROR: return "ERROR";
        case FATAL: return "FATAL";
        default: return "UNKNOWN";
    }
}

std::string Logger::getTime() {
    char buf[64];
    time_t now = time(nullptr);
    tm t{};
#ifdef _WIN32
    localtime_s(&t, &now);
#else
    localtime_r(&now, &t);
#endif
    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &t);
    return buf;
}

void Logger::printColor(LogLevel level) {
#ifdef _WIN32
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    switch (level) {
        case DEBUG: SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); break;
        case INFO:  SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); break;
        case WARNING: SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN); break;
        case ERROR: SetConsoleTextAttribute(hConsole, FOREGROUND_RED); break;
        case FATAL: SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY); break;
        default: SetConsoleTextAttribute(hConsole, 7);
    }
#else
    switch (level) {
        case DEBUG: std::cout << "\033[32m"; break;
        case INFO:  std::cout << "\033[0m"; break;
        case WARNING: std::cout << "\033[33m"; break;
        case ERROR: std::cout << "\033[31m"; break;
        case FATAL: std::cout << "\033[35m"; break;
        default: std::cout << "\033[0m";
    }
#endif
}

void Logger::log(LogLevel level, const char* file, int line, const char* format, ...) {
    std::lock_guard<std::mutex> lock(m_mutex);

    // 颜色
    printColor(level);

    // 头部:时间 等级 [文件:行号]
    std::string head = "[" + getTime() + "] [" + getLevelStr(level) + "] ["
                     + std::string(file) + ":" + std::to_string(line) + "] ";

    // 输出到控制台
    std::cout << head;

    // 格式化内容
    char buf[1024];
    va_list args;
    va_start(args, format);
    vsnprintf(buf, sizeof(buf), format, args);
    va_end(args);

    std::cout << buf << "\033[0m" << std::endl;

    // 输出到文件
    if (m_useFile) {
        m_file << head << buf << std::endl;
        m_file.flush();
    }
}

使用示例(main.cpp)

cpp 复制代码
#include "Logger.h"

int main() {
    // 可选:输出到日志文件
    Logger::instance().setLogFile("app.log");

    LOGD("这是调试信息,数字=%d,字符串=%s", 123, "测试");
    LOGI("程序启动成功");
    LOGW("内存占用偏高");
    LOGE("打开文件失败");
    LOGF("程序崩溃,即将退出");

    return 0;
}

效果展示

  • 控制台彩色显示
  • 每条日志带:时间 + 等级 + 文件名 + 行号 + 内容
  • 同时可输出到文件
  • 线程安全,多线程随便用

相关推荐
虚心的百褶裙4 分钟前
JavaScript性能优化
开发语言·javascript·性能优化
凯瑟琳.奥古斯特10 分钟前
二分查找解力扣1011最优运载能力
开发语言·c++·算法·leetcode·职场和发展
WZF-Sang19 分钟前
TCP和UDP协议
linux·服务器·网络·c++·学习·tcp/ip·udp
Tim_1028 分钟前
【C++】014、左值与右值的区别
开发语言·c++
想人陪的玫瑰29 分钟前
winform 能用 Native AOT 吗?——TDS 项目的实战尝试
c++·mfc
天空'之城34 分钟前
Linux 系统编程 14:Reactor 反应堆模式
linux·开发语言·网络编程·reactor 反应堆模式
Zhou14113644 分钟前
Java常见面试题7
java·开发语言
^yi1 小时前
【C++】类和对象(全)
开发语言·c++
我不是懒洋洋1 小时前
从零实现一个API网关:Kong的核心设计
c++
2301_777998341 小时前
C++异常处理
c++