2014-02-28 59 views
6

我可以使用LineID屬性嗎? 我希望我可以用水槽:: set_formatter做的,而不是在每個日誌語句中使用如何在boost log 2.0中記錄編碼器的行號?

__LINE__ 

__FILE__ 

這一點。

+1

這應該是如此明顯,但事實並非如此。現在我已經把這個頭撞過了很長一段時間。自從你發佈你的問題後有什麼運氣?如果你發現了,回答你自己的問題,並幫助一個傢伙! – ixe013

回答

7

我與此掙扎,直到我發現this snippet

#define LFC1_LOG_TRACE(logger) \ 
BOOST_LOG_SEV(logger, trivial::trace) << "(" << __FILE__ << ", " << __LINE__ << ") " 

就像一個魅力

+0

我試過名稱範圍,但它工作但更復雜。在我的帖子中看到我的代碼。 http://blog.csdn.net/csfreebird/article/details/20213349#t9 我有和你一樣的想法,只是定義我自己的宏,並使用__FILE__,__LINE__ –

+0

是的,張貼後我沿着那條路線太。結束了與你有點不同的事情,因爲我把named_scope作爲我的格式化程序的一部分。然後它可以產生嵌套的作用域調用。 – Chris

5

的LineID屬性是遞增每個日誌消息的序號。所以你不能使用它。

您可以使用屬性來記錄行號等。這允許您使用格式字符串靈活地格式化,而使用Chris的回答您的格式是固定的。

註冊在你的日誌初始化函數全局屬性:

using namespace boost::log; 
core::get()->add_global_attribute("Line", attributes::mutable_constant<int>(5)); 
core::get()->add_global_attribute("File", attributes::mutable_constant<std::string>("")); 
core::get()->add_global_attribute("Function", attributes::mutable_constant<std::string>("")); 

在你的日誌宏設置這些屬性:

#define logInfo(methodname, message) do {       \ 
    LOG_LOCATION;              \ 
    BOOST_LOG_SEV(_log, boost::log::trivial::severity_level::info) << message; \ 
    } while (false) 

#define LOG_LOCATION       \ 
    boost::log::attribute_cast<boost::log::attributes::mutable_constant<int>>(boost::log::core::get()->get_global_attributes()["Line"]).set(__LINE__); \ 
    boost::log::attribute_cast<boost::log::attributes::mutable_constant<std::string>>(boost::log::core::get()->get_global_attributes()["File"]).set(__FILE__); \ 
    boost::log::attribute_cast<boost::log::attributes::mutable_constant<std::string>>(boost::log::core::get()->get_global_attributes()["Function"]).set(__func__); 

不完全是美麗的,但它的工作原理,它對於我來說是一個很長的路要走。這是一個可惜的提升不提供此功能的框。

do {...} while(false)是使宏在語義上中立。

1

另一種可能性是在每個日誌記錄創建後爲其添加行和文件屬性。這是可能的,因爲在較新的版本中。稍後添加的屬性不參與過濾。具有可變記錄器識別

假設severity_logger:

boost::log::record rec = logger.open_record(boost::log::keywords::severity = <some severity value>); 
if (rec) 
{ 
    rec.attribute_values().insert(boost::log::attribute_name("Line"), 
     boost::log::attributes::constant<unsigned int>(__LINE__).get_value()); 
    ... other stuff appended to record ... 
} 

上面將當然,得到包裹成方便宏。

稍後,您可以使用自定義格式的片顯示此屬性:

sink->set_formatter(...other stuff... << expr::attr<unsigned int>("Line") << ...other stuff...); 

不同於以往的答案,這種方法需要更多的自定義代碼,並不能使用過的,現成的升壓記錄宏。

0

爲了後代的緣故 - 我爲非常簡單的日誌記錄需求製作了這套宏,這對我來說很好 - 對於簡單的日誌記錄需求。但是他們通常會說明如何做到這一點,並且這個概念很容易與Boost一起使用。它們旨在用於一個文件(它運行在多個進程中,有時在多個進程中的多個線程中)。它們是爲了相對簡單而不是速度。他們是安全的,如果陳述等不偷其他。在其中一個希望記錄功能的開始,一個叫

GLogFunc("function name"); 

那麼就可以做到這一點登錄的完整產品線:

GLogL("this is a log entry with a string: " << some_string); 

它們是如此 -

#define GLogFunc(x)  std::stringstream logstr; \ 
         std::string logfunc; \ 
         logfunc = x 

#define GLog(x)   do { logstr << x; } while(0) 

#define GLogComplete do { \ 
          _log << "[PID:" << _my_process << " L:" << __LINE__ << "] ((" << logfunc << ")) " << logstr.str() << endl; \ 
          logstr.str(""); \ 
          _log.flush(); \ 
         } while(0) 

#define GLogLine(x)  do { GLog(x); GLogComplete; } while(0) 
#define GLogL(x)  GLogLine(x) 
#define GLC    GLogComplete 

也可以建立一個幾行日誌...

GLog("I did this."); 
// later 
GLog("One result was " << some_number << " and then " << something_else); 
// finally 
GLog("And now I'm done!"); 
GLogComplete; 

無論流_log是(我打開它在類的構造函數,這是保證在這種情況下安全的文件)獲取輸出中是這樣的:

[PID:4848 L:348] ((SetTextBC)) ERROR: bad argument row:0 col:-64 

他們可以有條件地關閉,所有性能點球由符號在編譯的時候,像這樣否定:

#ifdef LOGGING_ENABLED 
... do the stuff above ... 
#else 

#define GLogFunc(x) 
#define GLog(x) 
#define GLogComplete 
#define GLogLine(x) 
#define GLogL(x) 

#endif 
3

通過Chris作品所示的解決方案,但如果你想自定義格式或選擇出現在每個水槽,你需要使用可變常量屬性哪些信息:

logging::core::get()->add_global_attribute("File", attrs::mutable_constant<std::string>("")); 
    logging::core::get()->add_global_attribute("Line", attrs::mutable_constant<int>(0)); 

然後,你讓包括這些新屬性自定義宏:

// New macro that includes severity, filename and line number 
#define CUSTOM_LOG(logger, sev) \ 
    BOOST_LOG_STREAM_WITH_PARAMS(\ 
     (logger), \ 
     (set_get_attrib("File", path_to_filename(__FILE__))) \ 
     (set_get_attrib("Line", __LINE__)) \ 
     (::boost::log::keywords::severity = (boost::log::trivial::sev)) \ 
    ) 

// Set attribute and return the new value 
template<typename ValueType> 
ValueType set_get_attrib(const char* name, ValueType value) { 
    auto attr = logging::attribute_cast<attrs::mutable_constant<ValueType>>(logging::core::get()->get_global_attributes()[name]); 
    attr.set(value); 
    return attr.get(); 
} 

// Convert file path to only the filename 
std::string path_to_filename(std::string path) { 
    return path.substr(path.find_last_of("/\\")+1); 
} 

下一個完整的源代碼創建兩個水槽。第一個使用File和Line屬性,第二個不使用。

#include <boost/log/trivial.hpp> 
#include <boost/log/sources/severity_logger.hpp> 
#include <boost/log/utility/setup/file.hpp> 
#include <boost/log/utility/setup/console.hpp> 
#include <boost/log/expressions.hpp> 
#include <boost/log/utility/setup/common_attributes.hpp> 
#include <boost/log/attributes/mutable_constant.hpp> 
#include <boost/date_time/posix_time/posix_time_types.hpp> 
#include <boost/log/support/date_time.hpp> 
#include <boost/log/attributes/mutable_constant.hpp> 

namespace logging = boost::log; 
namespace attrs = boost::log::attributes; 
namespace expr  = boost::log::expressions; 
namespace src  = boost::log::sources; 
namespace keywords = boost::log::keywords; 

// New macro that includes severity, filename and line number 
#define CUSTOM_LOG(logger, sev) \ 
    BOOST_LOG_STREAM_WITH_PARAMS(\ 
     (logger), \ 
     (set_get_attrib("File", path_to_filename(__FILE__))) \ 
     (set_get_attrib("Line", __LINE__)) \ 
     (::boost::log::keywords::severity = (boost::log::trivial::sev)) \ 
    ) 

// Set attribute and return the new value 
template<typename ValueType> 
ValueType set_get_attrib(const char* name, ValueType value) { 
    auto attr = logging::attribute_cast<attrs::mutable_constant<ValueType>>(logging::core::get()->get_global_attributes()[name]); 
    attr.set(value); 
    return attr.get(); 
} 

// Convert file path to only the filename 
std::string path_to_filename(std::string path) { 
    return path.substr(path.find_last_of("/\\")+1); 
} 

void init() { 
    // New attributes that hold filename and line number 
    logging::core::get()->add_global_attribute("File", attrs::mutable_constant<std::string>("")); 
    logging::core::get()->add_global_attribute("Line", attrs::mutable_constant<int>(0)); 

    // A file log with time, severity, filename, line and message 
    logging::add_file_log (
    keywords::file_name = "sample.log", 
    keywords::format = (
    expr::stream 
     << expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d_%H:%M:%S.%f") 
     << ": <" << boost::log::trivial::severity << "> " 
     << '[' << expr::attr<std::string>("File") 
       << ':' << expr::attr<int>("Line") << "] " 
     << expr::smessage 
    ) 
    ); 
    // A console log with only time and message 
    logging::add_console_log (
    std::clog, 
    keywords::format = (
    expr::stream 
     << expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S") 
     << " | " << expr::smessage 
    ) 
    ); 
    logging::add_common_attributes(); 
} 

int main(int argc, char* argv[]) { 
    init(); 
    src::severity_logger<logging::trivial::severity_level> lg; 

    CUSTOM_LOG(lg, debug) << "A regular message"; 
    return 0; 
} 

CUSTOM_LOG(lg, debug) << "A regular message";產生兩個輸出,寫這種格式的日誌文件中的聲明...

2015-10-15_15:25:12.743153: <debug> [main.cpp:61] A regular message 

...並輸出到控制檯這樣的:

2015-10-15 16:58:35 | A regular message 
+0

在利用多線程的程序中,上述代碼存在程序終止問題。程序結束了,斷點處於Visual Studio中boost日誌函數的中間。停止使用上述方法後,問題消失了。多線程環境中需要謹慎。 – Hill

0

這裏我的解決方案

設置代碼

auto formatter = 
    expr::format("[ %3% %1%:%2% :: %4%]") 
    % expr::attr<std::string>("File") 
    % expr::attr<uint32_t>("Line") 
    % expr::attr<boost::posix_time::ptime>("TimeStamp") 
    % expr::smessage 
    ; 

/* stdout sink*/ 
boost::shared_ptr<sinks::text_ostream_backend> backend = 
    boost::make_shared<sinks::text_ostream_backend>(); 
backend->add_stream(
    boost::shared_ptr<std::ostream>(&std::clog, NullDeleter())); 

// Enable auto-flushing after each log record written 
backend->auto_flush(true); 

// Wrap it into the frontend and register in the core. 
// The backend requires synchronization in the frontend. 
typedef sinks::synchronous_sink<sinks::text_ostream_backend> sink2_t; 
boost::shared_ptr<sink2_t> sink_text(new sink2_t(backend)); 

logging::add_common_attributes(); 

sink_text->set_formatter(formatter); 

日誌使用碼(短版):

rec.attribute_values().insert("File", attrs::make_attribute_value(std::string(__FILE__))); \ 

完整版本:

#define LOG(s, message) { \ 
    src::severity_logger<severity_level> slg; \ 
    logging::record rec = slg.open_record(keywords::severity = s); \ 
    if (rec) \ 
    { \ 
    rec.attribute_values().insert("File", attrs::make_attribute_value(boost::filesystem::path(__FILE__).filename().string())); \ 
    rec.attribute_values().insert("Line", attrs::make_attribute_value(uint32_t(__LINE__))); \ 
    logging::record_ostream strm(rec); \ 
    strm << message; \ 
    strm.flush(); \ 
    slg.push_record(boost::move(rec)); \ 
    } \ 

} \

如果我定義全局屬性(就像人們所建議的那樣前),即

logging::core::get()->add_global_attribute("File", attrs::mutable_constant<std::string>("")); 

然後我得到文件/撥動式。

相關問題