大家好!我是大聪明-PLUS

日志库

这个项目是一个用 C++ 编写的简单而灵活的日志库。该库支持多种日志级别、消息格式化以及将日志写入不同流的功能。

主要特点

  • 支持不同的日志级别:DEBUG,,,。INFOWARNERROR

  • 可自定义日志格式。

  • 支持在多个数据流中进行日志记录,并防止数据竞争。

  • 将日志记录到不同的输出流(std::cout文件等)。

  • 可以使用全局日志记录器。

安装

  1. 克隆仓库:

    git clone <https://github.com/Fallet666/logger.git>
  2. 进入项目目录并使用 CMake 进行构建:

    cd logger
    mkdir build
    cd build
    cmake ..
    make

基本概念

  • 日志记录器:主要的日志记录类。创建此类的实例以将日志记录到指定的流中。

  • 全局日志记录器:一个单例实例Logger,可在整个项目中默认使用。

日志记录功能

该项目提供了多种用于写入不同严重级别的日志的功能。这些功能允许根据日志的严重级别灵活控制消息输出。日志分为四个级别:

  • DEBUG— 用于调试信息。

  • INFO— 用于一般信息消息。

  • WARN— 用于警告。

  • ERROR— 用于需要注意的错误。

基本功能

LOG_MESSAGE(Logger& logger, LogLevel level, const std::string& message)

记录指定级别的消息。此函数通用,可用于记录任何级别的消息。

使用示例:

Logger::Logger log("Logger");
LOG_MESSAGE(log, Logger::DEBUG, "I'm MESSAGE");
各级别的简化功能

这些函数旨在简化特定级别的日志记录调用:

  1. logDebug(Logger& logger, const std::string& message)

记录一条级别为DEBUG.

使用示例:

logDebug(log, "This is a debug message");
  1. logInfo(Logger& logger, const std::string& message)

记录一条级别为INFO.

使用示例:

logInfo(log, "This is an info message");
  1. logWarn(Logger& logger, const std::string& message)

记录一条级别为WARN.

使用示例:

logWarn(log, "This is a warning message");
  1. logError(Logger& logger, const std::string& message)

记录一条级别为ERROR.

使用示例:

logError(log, "This is an error message");
全局日志记录功能

该项目还提供了使用 globalLogger 的全局日志记录功能。这些功能允许您记录消息,而无需创建和管理自己的日志记录器实例。

与基本功能类似,还有以下全局日志记录功能:

  • logMessageGlobal(LogLevel level, const std::string& message)

  • logDebugGlobal(const std::string& message)

  • logInfoGlobal(const std::string& message)

  • logWarnGlobal(const std::string& message)

  • logErrorGlobal(const std::string& message)

日志级别

您可以使用设置日志级别Cmake,这样就会显示不低于指定级别的日志。例如,如果您将级别设置为,则会显示级别为 100和Warn100 的日志。WarnError

使用示例:

set(DEFAULT_LOG_LEVEL DEBUG)
add_compile_definitions(GLOBAL_LOG_LEVEL=${DEFAULT_LOG_LEVEL})
笔记

每个日志记录函数都会使用FILELINE宏自动添加有关调用该日志的文件和行的信息。这使得在代码中追踪日志来源变得更加容易。

格式化日志

默认格式:

格式字符串:“%L: %T [%N]: %M\n”

示例输出:

DEBUG: 12:34:56 [MyLogger]: This is a debug message
高级格式设置

可以使用格式字符串自定义日志。默认情况下,格式字符串可以包含以下组件:

  • %L — 日志级别(DEBUG、INFO、WARN、ERROR)。

  • %T — 以 HH:MM:SS 格式记录日志条目时间。

  • %N — 日志记录器名称。

  • %M — 日志消息。

  • %t — 写入日志的线程 ID。

  • %S — 调用该日志的文件名。

  • %# — 调用该日志的文件行号。

这些规范可以按任意顺序组合和排列,以自定义日志格式,从而满足项目的需要。

格式字符串指定如下:

Logger::Logger log("custom formating");
log.setFormatString("%L: %T [%N]: %M (%S: %#)\n");
在对数中使用颜色

该项目包含对控制台日志输出进行颜色编码的功能,以便轻松区分不同级别的消息。如果日志记录器的输出流配置为启用颜色编码,则会自动应用颜色std::cout

配色方案

  • DEBUG— 白色 (\033[37m)。

  • INFO— 绿色(\033[32m)。

  • WARN— 黄色(\033[33m)。

  • ERROR— 红色 (\033[31m)。

日志记录时,终端会显示颜色,这使得识别消息的重要性变得更加容易。

禁用颜色

如果使用不同的输出流(例如,将日志写入文件),则颜色会自动禁用。

多线程应用程序中的日志记录

该项目支持多线程日志记录。这意味着多个线程可以同时写入日志,而不会出现数据损坏或竞态条件。

流同步

为了确保线程安全,Logger 类使用互斥锁(mutex std::mutex)。每次调用日志记录函数或修改日志记录字段时,线程都会被阻塞,直到操作完成。这可以防止并发访问共享资源(例如输出流或日志记录设置),从而确保日志数据的正确性和完整性。

多线程日志记录示例:

Logger::Logger log("MultiThreadLogger");

std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
    threads.emplace_back([&log, i] {
        logInfo(log, "Message from thread " + std::to_string(i));
    });
}

for (auto &t : threads) {
    t.join();
}

此示例创建了 10 个线程,每个线程都会写入一条包含其线程 ID 的日志消息。使用互斥锁可确保所有消息都能正确写入,避免混淆。

多线程日志记录的特性
  • 线程安全:在日志记录器中使用互斥锁可确保一次只执行一个操作——要么写入消息,要么更改日志记录器字段(例如,更改输出流或日志格式)。

  • 性能:尽管日志记录器会阻塞进程,但其设计旨在最大限度地减少对性能的影响。然而,当日志数量庞大或系统负载较高时,可能会出现延迟。

  • 输出到不同的流:日志记录器允许您为不同的实例使用不同的输出流,这对于按类别或来源分离日志非常有用。

将日志记录到不同的输出流

该项目为日志记录器提供了灵活的输出流配置。这意味着您可以将日志定向到任何支持该接口的流std::ostream,包括标准输出(std::cout)、文件、字符串流(std::ostringstream),甚至是自定义流。

设置输出流

创建日志记录器实例时,您可以指定日志的写入位置。默认情况下,日志会写入到 `/ std::coutetc/logger ...

std::ofstream file("log.txt");
Logger::Logger log("FileLogger", file);

在这个例子中,日志将被写入 log.txt 文件。

更改输出流

您还可以使用以下方法在程序运行时更改日志记录器输出流setOutStream

Logger::Logger log("Logger");
log.setOutStream(std::cerr);

使用不同输出流的示例:

std::ofstream file("output.log");
std::ostringstream oss;

Logger::Logger logToFile("FileLogger", file);
Logger::Logger logToStringStream("StringStreamLogger", oss);
Logger::Logger logToConsole("ConsoleLogger");

logInfo(logToFile, "This log goes to a file");
logWarn(logToStringStream, "This log goes to a string stream");
logError(logToConsole, "This log goes to the console");

file.close();

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐