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

效果展示

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

相关推荐
低代码布道师2 分钟前
外包项目管理平台全栈实战课02搭建数据底座:Next.js + PostgreSQL + Prisma 7
开发语言·javascript·postgresql·全栈开发
格林威5 分钟前
C# 图像使用AVX2指令集:使用OpenCvSharp实现字节图像解压缩速度和map_image算子速度提升
开发语言·图像处理·人工智能·计算机视觉·c#·视觉检测·工业相机
(Charon)10 分钟前
【C++】网络缓冲区设计(四):epoll + Reactor中Buffer的完整读写流程
开发语言·c++
西西弗Sisyphus23 分钟前
Qt 实现一个 Windows 启动项查看器
开发语言·windows·qt
FfHUCisI26 分钟前
Golang 函数调用的瞬间:栈帧、拷贝栈与逃逸分析
开发语言·后端·golang
万邦科技Lafite28 分钟前
淘宝海外采购指南,taoworld资格申请对接流程讲解
开发语言·电商开放平台·淘宝开放平台·京东开放平台·比价
ThornArmor38 分钟前
奔腾的呼吸:被驱逐者的灵感
开发语言·程序人生·架构
软件黑马王子1 小时前
12.缓存池优化:对象上限
开发语言·前端框架·c#
阿里嘎多学长1 小时前
2026-09-07 GitHub 热点项目精选
开发语言·程序员·github·代码托管