Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable Boost.Log only on debug

I need a logger for debug purpose and I'm using Boost.Log (1.54.0 with a patch in the boost.org homepage).

It's all fine I've created some macro like this:

#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )

Now is that a way that LOG_MESSAGE( lvl ) is expaneded in BOOST_LOG_TRIVIAL( lvl ) only in debug mode and ignore in release?

for example:

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

edit My first attempt is to create a nullstream... I think that in release mode compiler will optimize it...

#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
like image 644
Elvis Dukaj Avatar asked Jul 11 '13 15:07

Elvis Dukaj


2 Answers

The severity level of the log entry meerly acts as a filter for sinks. The sink will decide what to do with the message (print it or not) based on the severity level. But the message will still be sent.

If you are trying to not send the message at all, then you'll need to redefine LOG_MESSAGE to something which actually does nothing. there might be something in the Boost library for this, otherwise, you'll have to write your own. Perhaps this will be a start:

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

...and then:

#define LOG_MESSAGE (lvl) NullLogger (lvl)

Note however that even though nothing is being done with the log message or the expressions that make it up, the expressions are still evaluated. If some of these expressions are expensive, you will still take the performance hit. For example:

LOG_MESSAGE (debug) << SomeSuperExpensiveFunction();

Even if you are using the NullLogger above, SomeSuperExpensiveFunction() is still going to be called.

I would suggest as an alternative adding a flag that is evaluated at runtime, and decide at runtime whether or not to do the logging:

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

boolean comparisons are super cheap, and you may find one day in the future that the ability to turn logging on and off could be super handy. Also, doing this means you don't need to add yet another #define, which is always a good thing.

like image 93
John Dibling Avatar answered Sep 21 '22 10:09

John Dibling


I like John's NullLogger class. The only change I would make is as follows

#define LOG_MESSAGE(lvl) while (0) NullLogger (lvl)

Unfortunately this may generate warnings, but I would hope a decent compiler would then be able to eliminate all the associated logging code.

like image 39
Stephen Nutt Avatar answered Sep 20 '22 10:09

Stephen Nutt