65.9K
CodeProject 正在变化。 阅读更多。
Home

SLogLib:一个易于使用、完全可定制且可扩展的跨平台日志库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.47/5 (8投票s)

2015 年 5 月 20 日

MIT

5分钟阅读

viewsIcon

14606

downloadIcon

538

SLogLib 是一个易于使用、完全可定制且可扩展的跨平台日志库。

引言

SLogLib 是一个易于使用、完全可定制且可扩展的跨平台日志库。SLogLib 的重要特性包括:

  • 支持用户自定义消息格式。
  • 支持多种日志输出设备,包括控制台、文件和控件。
  • 支持调用栈。

入门

以下是开始使用 SLogLib 所需的最少代码:

#include "SLogLib/SLogLib"
void main()
{
    // Add these lines at the beginning of your program.
    // The devices and formatters are automatically deleted by SLogLib.
    using namespace SLogLib;
    addLoggingDevice(new ConsoleLogger(new NullFormatter)); // LINE 1
    addLoggingDevice(new FileLogger("foo.log", new DetailedFormatter)); // LINE 2

    // The following line writes the message to both console and file.
    int a = 10;
    double b = 15.3;
    const char* c = "Success";
    SLOGLIB_LOG_MSG_INFO("a = " << a << " b = " << b);
    SLOGLIB_LOG_MSG_INFO(c);
}

第一行代码向 SLogLib 添加了一个控制台日志设备。日志设备使用格式化器在将消息写入底层设备之前对其进行格式化。此处使用了 NullFormatter,它不做任何操作。控制台输出如下:

> a = 10 B = 15.3Success

请注意,两条消息都写在同一行上。这是因为 NullFormatter 在每条消息后不添加换行符。您可以自己为每条消息添加换行符,或者在 NullFormatter 的构造函数中传递 AppendNewLine 参数,以在每条消息后自动添加换行符。

SLogLib 可以将一条消息写入多个日志设备。第二行代码添加了一个文件日志设备,并使用详细格式化器来写入消息。以下是写入文件的第一条消息:

Msg Level  : 1
Time       : 2015-2-12 17:57:11:151
Process ID : 4188
Thread ID  : 7760
FileName   : LoggingDemo.cpp
FuncName   : wmain
Line No.   : 15
CallStack  : LoggingDemo.cpp : wmain [15]
Message    : a = 10 b = 15.3

几个要点

  • SLogLib 会自动管理设备和格式化器,因此在将它们传递给 SLogLib 后请勿删除它们。
  • 格式化器只能在构造时分配给设备,之后不能更改。
  • 格式化器不能在设备之间共享。每个设备都必须有一个唯一的格式化器。
  • 可以使用 Disable() 临时禁用一个日志设备。要重新启用,请使用 Enable()

SLogLib API

#define SLOGLIB_DISABLE_LOGGING

在编译时禁用所有日志代码。这可用于在生产版本中完全禁用日志。最好通过编译器参数定义此选项。如果您希望在运行时禁用日志,请使用 disableLogging() 和 enableLogging()。

#define SLOGLIB_LOG_MESSAGE(level, msg)

将指定级别的消息写入所有启用的日志设备。

#define SLOGLIB_LOG_MSG_INFO(m)   SLOGLIB_LOG_MESSAGE(MESSAGE_LEVEL_INFO   , m)
#define SLOGLIB_LOG_MSG_WARN(m)   SLOGLIB_LOG_MESSAGE(MESSAGE_LEVEL_WARNING, m)
#define SLOGLIB_LOG_MSG_ERROR(m)  SLOGLIB_LOG_MESSAGE(MESSAGE_LEVEL_ERROR  , m)
#define SLOGLIB_LOG_MSG_DEBUG(m)  SLOGLIB_LOG_MESSAGE(MESSAGE_LEVEL_DEBUG  , m)
#define SLOGLIB_LOG_MSG_DETAIL(m) SLOGLIB_LOG_MESSAGE(MESSAGE_LEVEL_DEBUG  , m)

上述方便宏会在预定义级别写入消息。

#define SLOGLIB_ADD_TO_CALLSTACK

将调用此宏的函数添加到当前调用栈。它可用于在调试时为重要函数构建调用栈。调用栈包含在 Message 中,并且可以写入日志设备。

函数

以下所有函数都包含在 SLogLib 命名空间中。

void SLogLib::addLoggingDevice(AbstractLoggingDevice* device);

将指定的日志设备添加到日志设备列表中。

void SLogLib::removeLoggingDevice(AbstractLoggingDevice* device);
void SLogLib::removeLoggingDevice(const std::string& name);

从日志设备列表中删除一个日志设备。

AbstractLoggingDevice* SLogLib::queryLoggingDevice(const std::string& name);

获取日志设备的指针。请注意,返回的指针不得被删除或更改。如果您想删除现有的日志设备,请使用 removeLoggingDevice()。

void SLogLib::writeMessage(const std::string& fileName,
                           const std::string& funcName,
                           unsigned int       lineNo,
                           unsigned int       level,
                           const std::string& msg);

将消息写入所有活动的日志设备。前三个参数必须是消息记录的源文件名、函数名和行号。最后两个参数是级别和要写入的消息。您无需直接调用此函数;SLOGLIB_LOG_MESSAGE 在自动添加文件名、函数名和行号后会在内部调用此函数。

void SLogLib::disableLogging();
void SLogLib::enableLogging();
bool SLogLib::isLoggingEnabled();

在运行时禁用和启用日志。在禁用日志期间,所有消息都会被忽略,并且在重新启用日志后也不会写入日志设备。

注释

您还应该阅读 AbstractLoggingDevice.h 和 AbstractFormatter.h 中的注释,以了解它们的 API。它们注释良好,应该易于理解。

构建 SLogLib

SLogLib 使用 cmake (http://www.cmake.org) 来生成构建工具(如 GNU Make、Visual Studio、XCode 等)所需的文件。如果您是 cmake 新手,应该阅读 Running CMake tutorial (http://www.cmake.org/runningcmake/)。 

您可以在 cmake 中配置以下变量:

  • SLOGLIB_DEBUG_POSTFIX (string):添加到调试构建库名称的后缀(默认为 d)。
  • SLOGLIB_BUILD_EXAMPLES (bool):构建示例(默认为 true)。
  • SLOGLIB_BUILD_QT_EXAMPLES (bool):构建 Qt 示例(默认为 false)。
  • SLOGLIB_USE_QT_VERSION (list):选择 Qt 版本:Qt4 或 Qt5(默认为 Qt5)。

SLogLib 已在 Windows 上使用 Visual Studio 2010 和 2013,在 Linux 上使用 g++,在 OSX 上使用 XCode 6 和 g++ 进行了测试。

SLogLib 内部结构

如果您希望通过创建自己的日志设备或格式化器来扩展 SLogLib,应该阅读本节以了解 SLogLib 的工作原理。SLogLib 包含三个主要组件:Message 结构体、将 Message 转换为 std::string 的格式化器,以及将 std::string 写入底层设备的日志设备。SLogLib 的整体架构如下:

SLogLib Architecture

Message 是核心数据

Message 结构体是核心数据,它会被格式化为字符串并写入设备。它包含以下字段:

  • mUserMessage:用户记录的消息。
  • mDateTime:记录消息时的本地日期和时间。
  • mLevel:用于将消息分类到不同级别。格式化器可以使用消息级别进行过滤,只格式化某些类型的消息并忽略其他消息。例如,您可能只想将错误消息写入控制台,而将所有类型的消息写入文件。以下消息级别定义如下:
    • MESSAGE_LEVEL_INFO
    • MESSAGE_LEVEL_WARNING
    • MESSAGE_LEVEL_ERROR
    • MESSAGE_LEVEL_DEBUG
    • MESSAGE_LEVEL_DETAIL
  • mCallstack:当前调用栈。默认情况下,它只包含一个条目:消息记录的行。但是,通过将 SLOGLIB_ADD_TO_CALLSTACK 添加到您希望包含在调用栈中的所有函数,可以生成更完整的调用栈。
  • mProcessID:记录消息的进程 ID。
  • mThreadID:记录消息的线程 ID。

格式化器将消息格式化为字符串

所有格式化器都派生自 AbstractFormatter 类。如果您想编写新的格式化器,应该继承自 AbstractFormatter 并重写 FormatMessage() 函数。有四种预定义的格式化器:

  • NullFormatter
  • InfoFormatter
  • ErrorFormatter
  • DetailedFormatter

NullFormatter 仅输出用户消息。InfoFormatterErrorFormatterDetailedFormatter 只格式化与其消息级别相等或更低的消息。

日志设备将字符串写入设备

所有日志设备都继承自 AbstractLoggingDevice。SLogLib 包含一个 ConsoleLogger (std::cout) 和 FileLogger (std::ofstream)。要创建新的日志设备,只需继承自 AbstractLoggingDevice 并重写 _WriteMessage()。更多详情请参阅 AbstractLoggingDevice.h。

Github

SLogLib 托管在 Github 上:https://github.com/saurabhg17/SLogLib

© . All rights reserved.