带有 gtest 框架的 Spdlog 记录器无法正常工作

Posted

技术标签:

【中文标题】带有 gtest 框架的 Spdlog 记录器无法正常工作【英文标题】:Spdlog logger with gtest framework is not working 【发布时间】:2018-03-13 14:36:47 【问题描述】:

我在我的库中使用 spdlog 和 gtest。我需要将一些日志(不是 gtest 日志)从测试执行保存到文件中。以下是创建记录器的代码:

void createLogger() 
    auto debug_logger = spdlog::rotating_logger_mt("debug_logger", "logs/test_debug", 1024 * 1024 * 25, 3);
    debug_logger->set_level(spdlog::level::debug);
    auto logger = spdlog::rotating_logger_mt("logger", "logs/test_info", 1024 * 1024 * 5, 2);

它在我的库的示例程序中运行良好。当我运行测试时,debug_logger 将所有内容保存在文件中,但logger 什么也不保存。当我删除

debug_logger->set_level(spdlog::level::debug);

debug_logger 也不工作。所以我认为这是记录器的问题,但是当我添加时

logger->set_level(spdlog::level::info);

还是不行。

这里主要用于测试:

int main(int argc, char **argv) 
    try 
        utility::createLogger();
        ::testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
      catch (const spdlog::spdlog_ex& ex) 
         std::cout << "Log initialization failed: " << ex.what() << std::endl;
     

设置和测试用例之一:

class CPUTest: public ::testing::Test 

protected:

std::shared_ptr<spdlog::logger> logger;

void SetUp() 
    spdlog::get("logger")->info("test get");
    logger = spdlog::get("logger");

;

TEST_F(CPUTest, Resolve15) 
    logger->info("Something from info logger");
    // ...

debug_loggerdebug 级别也保存 info 日志,但 loggerdebug 不保存。

您知道我的代码中的测试和记录器初始化有什么问题吗?我应该在我的库中使用两个记录器还是一个包含两个文件?

【问题讨论】:

在您的第一个示例中,您是否尝试过 logger-&gt;set_level(spdlog::level::debug); 而不是 logger-&gt;set_level(spdlog::level::info);logger 工作?调试比信息更细。 是的,我已经尝试过了——它也不起作用。这很奇怪 - 可能 gtest 以某种特定的顺序初始化测试类...... 【参考方案1】:

由于我的测试执行时间很长,我正在杀死进程。 debug 日志始终保存在两个文件中,info 日志不保存。这是由spdlog 中的刷新策略引起的(debug 级别更重要,并且它被刷新得非常频繁——我想几乎是在每次调用之后)。

info 日志在所有测试之后被刷新(不是在每个测试用例或每个测试类之后)。这就是为什么我的文件总是空的(我杀死了进程)。

可以通过

更改记录器的刷新策略
logger->flush_on(spdlog::level::info);

【讨论】:

【参考方案2】:

没有必要有两个单独的记录器。这只会使您的逻辑复杂化。您应该有一个记录器,您将根据构建类型为其设置粒度级别。像这样的:

#ifdef RELEASE
logger->set_level(spdlog::level::info);
#else
logger->set_level(spdlog::level::debug);
#endif

这样,当你在发布模式下构建时,记录器只会记录 info 消息,而在发布模式下它将记录 both info调试

您的调试记录器也保存 info 日志这一事实并不奇怪。几乎所有的日志库都采用这种方法。它们具有不同的日志记录粒度级别。例如:信息警告调试详细。然后,当您将级别设置为 warning 时,只会记录 warninginfo,而如果您选择例如 verbose em>,那么所有类型都会被记录。

编辑:

如果您确实需要按类型将日志拆分为不同的文件,您可以使用您喜欢的脚本语言编写一个简单的脚本来执行此操作。我假设来自这个库的日志都标有它们的类型。您可以使用它来解析输出文件并将某种类型的日志提取到单独的文件中。这很容易做到。拥有两个记录器只会使事情复杂化,并且会导致性能损失,如果您的测试套件变得很大,这一点很重要。

【讨论】:

是的,你是对的,但是如何(如果有一个记录器)为一个记录器的信息级别和调试级别设置接收器?我认为不实现自定义记录器是不可能的。 @Nequeq 你能解释一下“设置接收器”是什么意思吗?顺便说一句,您的问题中没有提到这一点... Sinks 在 spdlog 中用于将日志写入文件。我创建了两个带有两个不同文件的记录器,因为我需要将调试保存到一个文件并将信息保存到不同的文件中 - 它在有问题的代码中。我没有找到显示如何按级别将日志分隔到两个接收器的示例,这就是我创建两个记录器的原因。

以上是关于带有 gtest 框架的 Spdlog 记录器无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

spdlog 仅标头,带有外部 fmt。 spdlog 错误:“内部”:不是“fmt”的成员

如何使用 Visual Studio 2005 设置 Google C++ 测试框架 (gtest)

如何将 Windows 调试记录器附加到 spdlog

如何使用 spdlog 记录 pid(进程 ID)

使用 spdlog (C++) 记录,记录器未将日志写入文件

如何在代码中启用/禁用 spdlog 日志记录?