2013-07-11 14 views
4

我需要一個記錄器用於調試目的,我使用的是Boost.Log(1.54.0在boost.org主頁中有一個補丁)。只在調試時啓用Boost.Log

這是所有罰款我已經創造了一些宏是這樣的:

#define LOG_MESSAGE(lvl) BOOST_LOG_TRIVIAL(lvl) 

現在是一種方式,LOG_MESSAGE(LVL)在BOOST_LOG_TRIVIAL(LVL)是expaneded僅在調試模式和發佈忽略?

例如:

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

編輯 我第一次嘗試是創建一個nullstream ...我認爲,在釋放模式編譯器優化它...

#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 

回答

5

的日誌條目的嚴重級別可以作爲接收器的過濾器。接收器將根據嚴重級別決定如何處理消息(打印或不打印)。但該消息仍將被髮送。

如果您試圖不發送消息的所有,那麼您需要重新定義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 EAN比較是超級便宜,你可能在未來的某一天發現,打開和關閉日誌記錄的功能可能非常方便。另外,這樣做意味着您不需要再添加#define,這總是一件好事。

3

我喜歡John的NullLogger班。我會做的唯一的變化是如下

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

不幸的是這可能會產生警告,但我希望再一個像樣的編譯器將能夠消除所有的相關的日誌代碼。

+0

這種方法幾乎沒有好處。它可能會阻止NullLogger方法被調用,但看看它們:它們是在類中定義的,所以是'inline'。他們也是空的。調用它們只是理論上的,實際上優化器會刪除每個'NullLogger'的蹤跡。 – MSalters