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;
}

效果展示

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

相关推荐
zhanghaha131413 小时前
Python进阶教程:35_PyQt (保姆级零基础教程)
开发语言·python·pyqt
释厄62313 小时前
多黑洞具现论·物理/生物/金融三域显化·虚拟宇宙黑洞·奇点=0 圆圈
开发语言·数据结构·人工智能·程序人生·安全威胁分析
UIU11414 小时前
递归算法与汉诺塔
c++·学习·算法·c#·递归
Fruit_Caller15 小时前
static
开发语言·c++
codigger20 小时前
ObjectSense:一门千行内核、把可靠性写进骨子里的面向对象脚本语言
开发语言·编程·编程语言
小小龙学IT20 小时前
Boost.Interprocess 开源 C++ 进程间通信库深度解析
c++·开源
倒头就睡的小比特6 天前
算法竞赛C++常用的STL
c++·算法
weilx12346 天前
C++笔记-文件IO-<fcntl.h>
c++
小羊没烦恼!6 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读6 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python