c++ - 仅在调试时启用 Boost.Log

标签 c++ logging boost-log

我需要一个用于调试目的的记录器,我正在使用 Boost.Log(1.54.0,在 boost.org 主页上有一个补丁)。

没关系,我已经创建了一些像这样的宏:

#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )

现在这是一种仅在 Debug模式下在 BOOST_LOG_TRIVIAL( lvl ) 中扩展 LOG_MESSAGE( lvl ) 而在发布时忽略的方法吗?

例如:

LOG_MESSAGE( critical ) << "If I read this message we're in debug mode"

编辑 我的第一次尝试是创建一个空流...我认为在 Release模式下编译器会优化它...

#if !defined( NDEBUG )
#include <boost/log/trivial.hpp>
#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )
#else
#if defined( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-value"
#endif


#include <iosfwd>
struct nullstream : public std::ostream {
    nullstream() : std::ios(0), std::ostream(0) {}
};

static nullstream g_nullstream;

#define LOG_MESSAGE( lvl ) g_nullstream

#if defined( __GNUC__ )
#pragma GCC diagnostic pop
#endif

#endif

最佳答案

日志条目的严重级别仅充当接收器的过滤器。接收器将根据严重级别决定如何处理消息(打印或不打印)。但消息仍会发送。

如果您试图根本不发送消息,那么您需要将LOG_MESSAGE 重新定义为实际上什么都不做的东西。为此,Boost 库中可能有一些东西,否则,您将不得不编写自己的东西。也许这将是一个开始:

class NullLogger
{
public:
  template <typename SeverityT> NullLogger (SeverityT) {};
  template <typename Val> NullLog& operator<< (const Val&) { return * this};
};

...然后:

#define LOG_MESSAGE (lvl) NullLogger (lvl)

但是请注意,即使没有对日志消息或构成日志消息的表达式执行任何操作,表达式仍会被计算。如果其中一些表达式开销很大,您仍然会受到性能影响。例如:

LOG_MESSAGE (debug) << SomeSuperExpensiveFunction();

即使您使用上面的 NullLoggerSomeSuperExpensiveFunction() 仍将被调用。

作为替代方案,我建议添加一个在运行时评估的标志,并决定在运行时是否进行日志记录:

if (mLogStuff)
{ 
  LOG_MESSAGE (debug) << SomeSuperExpensiveFunction();
}

bool比较非常便宜,您可能会发现在未来的某一天,打开和关闭日志记录的功能会非常方便。此外,这样做意味着您不需要添加另一个 #define,这总是一件好事。

关于c++ - 仅在调试时启用 Boost.Log,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17598149/

相关文章:

c++ - 投入 constexpr 函数 : do we need wrapping condition?

c++ - 标准容器的复杂性保证是什么?

c++ - 在子类中调用父函数

c++ - 使用柯南包管理器 boost 链接错误

c++ - Boost.Log 在每个日志语句后刷新

c++ - 为什么 scanf 似乎跳过了输入?

c# - 如何与多个类共享一个类的实例?

java - 使用 Log4J 2 进行 JNDI 变量查找时如何设置默认值?

logging - 如何让 SAS 同时登录外部位置和 SAS Enterprise Guide

c++ - 在 Boost.Log 中正确使用 asynchronous_sink::flush()