log格式如下:
<Timestamp> [<Category> <Verbosity Level>] <Message> (<File Name>:<Line Number>) -> Function <Function Name>
# 如:
2020-05-27 11:45:47.447 [DOCUMENTATION_CATEGORY Error] This is an error message (example.cpp:50) -> Function main
用户通过三个宏记录Log:
EPROSIMA_LOG_INFO
: Log::Kind::Info verbosity.EPROSIMA_LOG_WARNING
: Log::Kind::Warning verbosity.EPROSIMA_LOG_ERROR
: Log::Kind::Error verbosity.EPROSIMA_LOG_INFO(DOCUMENTATION_CATEGORY, "This is an info message");
EPROSIMA_LOG_WARNING(DOCUMENTATION_CATEGORY, "This is an warning message");
EPROSIMA_LOG_ERROR(DOCUMENTATION_CATEGORY, "This is an error message");
YYYY-MM-DD hh:mm:ss.sss
,固定格式,且不能关闭// Set log verbosity level to Log::Kind::Info
Log::SetVerbosity(Log::Kind::Info);
// Get log verbosity level
Log::Kind verbosity_level = Log::GetVerbosity();
// Enable file name and line number reporting
Log::ReportFilenames(true);
// Disable file name and line number reporting
Log::ReportFilenames(false);
// Enable function name reporting
Log::ReportFunctions(true);
// Disable function name reporting
Log::ReportFunctions(false);
支持0或多个consumers,通过函数 Log::RegisterConsumer() 注册,Log::ClearConsumers()清空所有comsumers。
// Create a FileConsumer consumer that logs entries in "archive.log"
std::unique_ptr<FileConsumer> file_consumer(new FileConsumer("archive.log"));
// Register the consumer. Log entries will be logged to STDOUT and "archive.log"
Log::RegisterConsumer(std::move(file_consumer));
// Clear all the consumers. Log entries are discarded upon consumption.
Log::ClearConsumers();
三种级别:
Log::Kind::Error
: Used to log error messages.Log::Kind::Warning
: Used to log error and warning messages.Log::Kind::Info
: Used to log error, warning, and info messages.Log::Kind::Error
,可以通过函数 Log::SetVerbosity
重新设置。// Set log verbosity level to Log::Kind::Info
Log::SetVerbosity(Log::Kind::Info);
// Get log verbosity level
Log::Kind verbosity_level = Log::GetVerbosity();
通过函数 Log::Reset()
重置到默认的配置,具体为:
除了Verbosity Level,DDS提供了三种不同的过滤条件,都使用std::regex_search()
过滤:
Log::SetCategoryFilter
设置过滤规则:// Set filter using regular expression
Log::SetCategoryFilter(std::regex("(CATEGORY_1)|(CATEGORY_2)"));
// Would be consumed
EPROSIMA_LOG_ERROR(CATEGORY_1, "First log entry");
// Would be consumed
EPROSIMA_LOG_ERROR(CATEGORY_2, "Second log entry");
// Would NOT be consumed
EPROSIMA_LOG_ERROR(CATEGORY_3, "Third log entry");
输出以下内容:
2020-05-27 15:07:05.771 [CATEGORY_FILTER_1 Error] First log entry -> Function main
2020-05-27 15:07:05.771 [CATEGORY_FILTER_2 Error] Second log entry -> Function main
Log::ReportFilenames
设置文件名过滤// Enable file name and line number reporting
Log::ReportFilenames(true);
// Set filter using regular expression so filename must match "example"
Log::SetFilenameFilter(std::regex("example"));
// Would be consumed
EPROSIMA_LOG_ERROR(CATEGORY, "First log entry");
// Set filter using regular expression so filename must match "other"
Log::SetFilenameFilter(std::regex("other"));
// Would NOT be consumed
EPROSIMA_LOG_ERROR(CATEGORY, "Second log entry");
输出如下log:
2020-05-27 15:07:05.771 [CATEGORY Error] First log entry (example.cpp:50) -> Function main
Log::SetErrorStringFilter
函数用来设置过滤。举例如下:// Set filter using regular expression so message component must match "First"
Log::SetErrorStringFilter(std::regex("First"));
// Would be consumed
EPROSIMA_LOG_ERROR(CATEGORY, "First log entry");
// Would NOT be consumed
EPROSIMA_LOG_ERROR(CATEGORY, "Second log entry");
输出以下内容:
2020-05-27 15:07:05.771 [CATEGORY Error] First log entry -> Function main
使用函数 Log::Reset()
,重置内容包括以下:
提供了三种不同的comsumers对应到三种输出流:
标准输出,默认的输出方式。log模块的cmake中LOG_CONSUMER_DEFAULT 值为AUTO,STDOUT,或者没有被其他设置时。
// Create a StdoutConsumer consumer that logs entries to stdout stream.
std::unique_ptr<StdoutConsumer> stdout_consumer(new StdoutConsumer());
// Register the consumer.
Log::RegisterConsumer(std::move(stdout_consumer));
StdoutErrConsumer使用Log::Kind过滤log。大于等于Log::Kind级别的log会输出到STDERR中,其他的输出到STDOUT中。默认情况下阈值为Log::Kind::Warning。函数StdoutErrConsumer::stderr_threshold可以修改默认阈值。如果cmake中的LOG_CONSUMER_DEFAULT 指定为STDOUTERR,默认log consumer会使用StdoutErrConsumer。
// Create a StdoutErrConsumer consumer that logs entries to stderr only when the Log::Kind is equal to ERROR
std::unique_ptr<StdoutErrConsumer> stdouterr_consumer(new StdoutErrConsumer());
stdouterr_consumer->stderr_threshold(Log::Kind::Error);
// Register the consumer
Log::RegisterConsumer(std::move(stdouterr_consumer));
可以将log输入到文件中,并且可以使用write或append模式,清空写或追加log到log文件中。
// Create a FileConsumer consumer that logs entries in "archive_1.log", opening the file in "write" mode.
std::unique_ptr<FileConsumer> write_file_consumer(new FileConsumer("archive_1.log", false));
// Create a FileConsumer consumer that logs entries in "archive_2.log", opening the file in "append" mode.
std::unique_ptr<FileConsumer> append_file_consumer(new FileConsumer("archive_2.log", true));
// Register the consumers.
Log::RegisterConsumer(std::move(write_file_consumer));
Log::RegisterConsumer(std::move(append_file_consumer));
可以通过以下CMake 中的编译宏,在编译阶段禁用log:
类图
时序图
Fast DDS中的DBQueue(Double Buffer Queue)使用两个buffer是为了提高数据处理的效率。当一个buffer被用来填充新的数据时,另一个buffer可以被用来处理和发送已经填充好的数据。这样,填充数据和处理数据这两个操作就可以并行进行,互不干扰。这种设计通常被称为"双缓冲"(Double Buffering)