【C++】plog
GitHub地址:Plog - portable, simple and extensible C++ logging library
介绍
Plog is一个C++日志库,旨在保持尽可能的简单、小巧和灵活。它被创建作为现有大型库的替代品,并提供了一些独特的功能,如CSV日志格式和宽字符串支持。
主打一个小,灵活吗?
先来一段Demo
#include <plog/Log.h> // Step1: include the headers
#include "plog/Initializers/RollingFileInitializer.h"
int main()
{
plog::init(plog::debug, "Hello.txt"); // Step2: initialize the logger
// Step3: write log messages using a special macro
// There are several log macros, use the macro you liked the most
PLOGD << "Hello log!"; // short macro
PLOG_DEBUG << "Hello log!"; // long macro
PLOG(plog::debug) << "Hello log!"; // function-style macro
// Also you can use LOG_XXX macro but it may clash with other logging libraries
LOGD << "Hello log!"; // short macro
LOG_DEBUG << "Hello log!"; // long macro
LOG(plog::debug) << "Hello log!"; // function-style macro
return 0;
}
输出:
2015-05-18 23:12:43.921 DEBUG [21428] [main@13] Hello log!
2015-05-18 23:12:43.968 DEBUG [21428] [main@14] Hello log!
2015-05-18 23:12:43.968 DEBUG [21428] [main@15] Hello log!
日志有的都有了,怎么设置日志的格式,模式, 怎么输出到文件呢?
Here is the translation of the provided information:
- 非常小(略多于1000行代码)
- 易于使用
- 仅包含头文件
- 没有第三方依赖
- 跨平台支持:Windows、Linux、FreeBSD、macOS、Android、RTEMS(gcc、clang、msvc、mingw、mingw-w64、icc、c++builder)
- 线程安全和类型安全
- 格式化器:TXT、CSV、FuncMessage、MessageOnly
- 输出器:RollingFile、Console、ColorConsole、Android、EventLog、DebugOutput、DynamicAppender
- 自动捕获 ‘this’ 指针(仅在 msvc 上支持)
- 惰性流评估
- 兼容 Unicode,文件以 UTF-8 存储,支持 Utf8Everywhere
- 不要求 C++11
- 可扩展
- 没有对 windows.h 的依赖
- 可使用 UTC 或本地时间
- 可以以 HEX 或 ASCII 打印缓冲区
- 可以打印 std 容器
- 使用现代 CMake
1000多行就实现了,还是有点厉害啊,有机会学习一波
使用说明
Step1 导入头文件
你需要执行以下步骤:
- 将 plog/include 添加到项目的包含路径中。
- 在你的 cpp/h 文件中添加
#include <plog/Log.h>
(如果你使用了预编译头文件,将这个 include 添加到那里是一个不错的选择)。
Step2 初始化
Logger& init(
Severity maxSeverity,
const char/wchar_t* fileName,
size_t maxFileSize = 0,
int maxFiles = 0
);
-maxSeverity
是日志记录器的严重性上限。所有日志消息都有其自己的严重性,如果它高于设定的上限,那么这些消息将被丢弃。Plog 定义了以下严重性级别:
enum Severity
{
none = 0, // will always be printed
fatal = 1,
error = 2,
warning = 3,
info = 4,
debug = 5,
verbose = 6
};
日志格式会根据 fileName
文件扩展名自动确定:
.csv
=> CSV 格式- 其他任何扩展名 => TXT 格式
滚动行为由 maxFileSize
和 maxFiles
参数控制:
maxFileSize
- 日志文件的最大大小(以字节为单位)maxFiles
- 保留的日志文件数量
如果其中一个参数的值为零,则禁用日志滚动。
示例:
plog::init(plog::warning, "c:\\logs\\log.csv", 1000000, 5);
在这里,日志记录器被初始化为将所有最高严重性为警告的消息写入以 CSV 格式存储的文件。最大日志文件大小设置为 1,000,000 字节,同时保留 5 个日志文件。
Step3 打log
Long macros:
PLOG_VERBOSE << "verbose";
PLOG_DEBUG << "debug";
PLOG_INFO << "info";
PLOG_WARNING << "warning";
PLOG_ERROR << "error";
PLOG_FATAL << "fatal";
PLOG_NONE << "none";
Short macros:
PLOGV << "verbose";
PLOGD << "debug";
PLOGI << "info";
PLOGW << "warning";
PLOGE << "error";
PLOGF << "fatal";
PLOGN << "none";
Function-style macros:
PLOG(severity) << "msg";
Conditional logging macros
PLOG_VERBOSE_IF(cond) << "verbose";
PLOG_DEBUG_IF(cond) << "debug";
PLOG_INFO_IF(cond) << "info";
PLOG_WARNING_IF(cond) << "warning";
PLOG_ERROR_IF(cond) << "error";
PLOG_FATAL_IF(cond) << "fatal";
PLOG_NONE_IF(cond) << "none";
PLOGV_IF(cond) << "verbose";
PLOGD_IF(cond) << "debug";
PLOGI_IF(cond) << "info";
PLOGW_IF(cond) << "warning";
PLOGE_IF(cond) << "error";
PLOGF_IF(cond) << "fatal";
PLOGN_IF(cond) << "none";
Appender
有时候我们想在终端和文件同时输出,就需要用到Appender的概念了。你需要构造一个带有格式化器的 Appender,并将其传递给 plog::init 函数。
Logger& init(Severity maxSeverity = none, IAppender* appender = NULL);
static plog::ConsoleAppender<plog::TxtFormatter> consoleAppender;
plog::init(plog::debug, &consoleAppender);
如何使用多个Appender? 可以在一个单独的日志记录器中拥有多个 Appender。在这种情况下,日志消息将被写入所有这些 Appender。使用以下方法来实现这一点:
Logger& Logger::addAppender(IAppender* appender);
示例:
// Create the 1st appender.
static plog::RollingFileAppender<plog::CsvFormatter> fileAppender("MultiAppender.csv", 8000, 3);
// Create the 2nd appender.
static plog::ConsoleAppender<plog::TxtFormatter> consoleAppender;
// Initialize the logger with the both appenders.
plog::init(plog::debug, &fileAppender).addAppender(&consoleAppender);
跨模块共享log
对于由多个二进制模块组成的应用程序,plog 实例可以是本地的(每个模块都有自己的实例)或共享的(所有模块使用相同的实例)。在共享的情况下,你只需在一个模块中初始化 plog,其他模块将重用该实例。
在 Windows 上进行共享,一个模块应该使用 PLOG_EXPORT,而其他模块应该使用 PLOG_IMPORT。此外,在 Linux/Unix 上要小心,如果不指定共享行为,它将由编译器设置(-fvisibility)来确定。
其实我觉得共享 Appender 可能操作起来比较方便,
比如在 exe 里面有一个日志:
plog::Severity maxSeverity = plog::debug;
std::string logPath = "mylog.log";
//max 5MB, loop 3 files
static plog::RollingFileAppender<plog::TxtFormatter> fileAppender(logPath.c_str(), 1024 * 1024 * 5, 3);
// Create the 2nd appender.
static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;
// Initialize the logger with the both appenders.
plog::init(maxSeverity, &fileAppender).addAppender(&consoleAppender);
mylib.init(maxSeverity , plog::get())
在lib 中定义:
void init(int logSeverity, plog::IAppender* appender)
{
if (plog::get() == nullptr) {
if (appender != nullptr) {
if (logSeverity >= 0 && logSeverity <= 6) {
plog::init((plog::Severity)logSeverity, appender);
}
else {
plog::init(plog::Severity::verbose, appender);
}
}
}
}
这样可能在实际开发中,可能比较好操作一点。