2016-07-28 85 views
0

我正在嘗試使用Boost.Log自定義格式化程序。我知道如何做到這一點的方法是調用匯給它一個本地函數的地址set_formatter方法,其中本地函數的簽名必須是:如何在自定義格式化函數中使用Boost.Log格式表達式

void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm) 

my_formatter我可以使用Boost .Log抽取API以獲取我需要的屬性值。一旦我得到的值,我可以輸出他們到strm。我想這樣做,這樣我可以輕鬆地格式化存儲在記錄中的一些自定義屬性。但對於其他更傳統的Boost.Log屬性,我想繼續使用簡單的格式化表達式,這些表達式被記錄爲set_formatter方法的關鍵字參數。有沒有辦法在my_formatter自定義函數中使用關鍵字表達式?

例如:

void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm) 
{ 
    // here I can get the timestamp attribute and format its ticks value to the stream 
    boost::log::value_ref<boost::posix_time::ptime> tstamp_ref = 
     boost::log::extract<boost::posix_time::ptime>("TimeStamp", rec); 
    const boost::posix_time::ptime& timestamp = tstamp_ref.get(); 

    strm << timestamp.time_of_day().ticks(); 
} 

然後給一個接收器,我可以打電話給

sink->set_formatter(&my_formatter) 

但Boost.Log給我一個優雅的(幾乎是不可思議的)的表達,我可以用它來設置格式:

boost::log::formatter formatter = 
    expr::stream 
    << expr::format_date_time<boost::posix_time::ptime>(
     "TimeStamp", "%Y/%m/%d, %H:%M:%S.%f, "); 

sink->set_formatter(formatter) 

我的問題是:有沒有辦法在我的自定義中使用formatter表達式my_formatter功能?

謝謝!

回答

1

您可能想要做的是將格式化程序的自定義部分注入到使用Boost.Log創建的格式化表達式中,而不是用其他方式。 This答案描述了一種通過使用phoenix::bind來實現這一點的方法。

+0

謝謝!這是一個很長的答案,所以我將不得不稍稍研究一下,但這似乎也是一個很好的方法。在使用格式化表達式時,您可以多討論一下性能下降嗎?您在文檔中提到,代碼中的格式化表達式的執行速度要比從配置文件創建的快。我的觀察是我的非表達式格式化程序比基於表達式的表達式執行得更快。 (在我的臨時基準測試中,唯一正在做的工作就是日誌記錄,所以我對速度變慢了,但有時性能確實很重要。) – Phil

+0

必須檢查代碼和生成的程序集才能發現績效迴歸的原因。格式化表達式(無論如何涉及'expr :: stream')比解析格式化器更有效率,因爲編譯器有更多優化方法。特別是它可以更積極地內聯函數。手寫格式化程序可能會勝過格式化表達式,因爲它可以更加專業化。它通常是一個扁平函數,所以它不依賴內聯,而編譯器可能由於某種原因無法優化模板表達式。 –

+0

另外,如果你的格式化程序涉及日期/時間,那麼確保你使用'expr :: format_date_time'而不是Boost.DateTime中的'operator <<',因爲後者被認爲比較慢。 –

0

經過一番工作,我找到了一些Boost.Log測試代碼,form_date_time.cpp,它顯示瞭如何做到這一點。以下是如何在自定義格式函數中以編程方式使用表達式格式程序。

void my_formatter(boost::log::record_view const& rec, 
        boost::log::formatting_ostream& strm) 
{ 
    typedef boost::log::formatter formatter; 
    formatter f = expr::stream << expr::format_date_time<boost::posix_time::ptime>(
         "TimeStamp", "%Y/%m/%d, %H:%M:%S.%f, "); 
    f(rec, strm); 
} 

雖然我已經給出了答案,但應該小心使用它。在我的基準測試中,正確實現的自定義格式化函數將優於表達式格式化程序。但對於不想爲其編寫代碼的複雜表達式(例如專用Named scope formatter),此方法允許在自定義格式化函數中利用表達式格式化程序。

相關問題