【C++】plog

GitHub地址:Plog - portable, simple and extensible C++ logging library

introduce

Plog is a C++ logging library designed to stay as simple, small and flexible as possible. It was created as a replacement for existing large libraries and provides some unique features such as CSV log format and wide string support.

Mainly a small one, is it flexible?

Let’s start with a 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;
}

Output:

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!

Now that we have all the logs, how do we set the format and mode of the logs, and how do we output them to files?

Here is the translation of the provided information:

  • Very small (a little over 1000 lines of code)
  • Easy to use
  • Include only header files
  • No third-party dependencies
  • Cross-platform support: Windows, Linux, FreeBSD, macOS, Android, RTEMS (gcc, clang, msvc, mingw, mingw-w64, icc, c++builder)
  • Thread safety and type safety
  • Formatters: TXT, CSV, FuncMessage, MessageOnly
  • Outputters: RollingFile, Console, ColorConsole, Android, EventLog, DebugOutput, DynamicAppender
  • Automatically capture the 'this' pointer (only supported on msvc)
  • Lazy flow evaluation
  • Compatible with Unicode, files are stored in UTF-8, and supports Utf8Everywhere
  • Not required C++11
  • Scalable
  • No dependency on windows.h
  • Can use UTC or local time
  • Can print buffer in HEX or ASCII
  • Can print std containers
  • Using modern CMake

It was implemented in more than 1,000 lines. It’s still a bit awesome. I’ll give it a try if I have a chance.

Instructions for use

Step1 Import header file

You need to perform the following steps:

  1. Add plog/include to your project's include path.
  2. Add #include <plog/Log.h> in your cpp/h file (if you are using precompiled headers, adding this include there is a good choice).

Step2 Initialization

Logger& init(
	Severity maxSeverity, 
	const char/wchar_t* fileName, 
	size_t maxFileSize = 0, 
	int maxFiles = 0
);

-maxSeverity is the maximum severity limit for the logger. All log messages have their own severity and if it is higher than the set upper limit then these messages will be discarded. Plog defines the following severity levels:

enum Severity
{
    
    
    none = 0, // will always be printed
    fatal = 1,
    error = 2,
    warning = 3,
    info = 4,
    debug = 5,
    verbose = 6
};

The log format is automatically determined based on fileName the file extension:

  • .csv=> CSV format
  • Any other extension => TXT format

Scrolling behavior is controlled by the maxFileSize and maxFiles parameters:

  • maxFileSize- The maximum size of the log file in bytes
  • maxFiles- Number of log files to keep

If the value of one of the parameters is zero, log rolling is disabled.

Example:

plog::init(plog::warning, "c:\\logs\\log.csv", 1000000, 5);

Here, the logger is initialized to write all messages with the highest severity warning to a file stored in CSV format. The maximum log file size is set to 1,000,000 bytes, with 5 log files retained.

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

Sometimes we want to output both the terminal and the file at the same time, so we need to use the concept of Appender. You need to construct an Appender with a formatter and pass it to the plog::init function.

Logger& init(Severity maxSeverity = none, IAppender* appender = NULL);
static plog::ConsoleAppender<plog::TxtFormatter> consoleAppender;
plog::init(plog::debug, &consoleAppender);

How to use multiple Appenders? It is possible to have multiple Appenders in a single logger. In this case, log messages will be written to all these Appenders. Use the following methods to achieve this:

Logger& Logger::addAppender(IAppender* appender);

Example:

 // 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); 

Share logs across modules

For applications composed of multiple binary modules, the plog instance can be local (each module has its own instance) or shared (all modules use the same instance). In the case of sharing, you only need to initialize the plog in one module and other modules will reuse the instance.
For sharing on Windows, one module should use PLOG_EXPORT and the other modules should use PLOG_IMPORT. Also, be careful on Linux/Unix, if you don't specify the sharing behavior it will be determined by the compiler setting (-fvisibility).

In fact, I think sharing the Appender may be more convenient.

For example, there is a log in the 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())

Defined in 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);
			}
		}
	}
}

This may be easier to operate in actual development.

Guess you like

Origin blog.csdn.net/qq_30340349/article/details/134460040
C++