namespace logging = boost::log; namespace src = boost::log::sources; namespace expr = boost::log::expressions; namespace sinks = boost::log::sinks; namespace attrs = boost::log::attributes; namespace keywords = boost::log::keywords;
trivial
頭文件可用於通常的控制檯輸出,日誌等級被定義在改頭文件;logging::core::get()->set_filter();
sink
,使用logging::add_file_log
可添加文件sink後端,格式以下: 1 2 3 4 5 6 7 |
logging::add_file_log
(
keywords::file_name="sample_%N.log", //文件名格式 keywords::rotation_size=10*1024*1024, //超過此大小自動創建新文件 keywords::time_based_rotation=sinks::file::rotation_at_time_point(0,0,0), //每隔指定時間重建新文件 keywords::format="[%TimeStamp%]:%Message%" //日誌消息格式 ); |
除了這種語法外,也能夠創建sinks::text_file_backend
後端,用之初始化一個sink。 file rotation的選項有不少,能夠指定日期、時間間隔、文件大小,甚至能夠指定本身的謂詞。 此外,能夠設置在創建新文件後首先執行(sink->locked_backend()->set_open_handler(xx)
),以及rotation以前最後執行的語句。 能夠綜合管理這些日誌文件,限制輸出文件夾,日誌總大小限制,以及最低磁盤空間限制。以下:ios
1 2 3 4 5 |
sink->locked_backend()->set_file_collector(sinks::file::make_collector(
keywords::target="logs", //目標文件夾 keywords::max_size=16*1024*1024, //全部日誌加起來的最大大小, keywords::min_free_space=100*1024*1024 //最低磁盤空間限制 )); |
若是多個後端制定了相同的存放文件夾,限制取其中最嚴格的,另外,注意避免不一樣後端日誌的命名衝突問題。 注意使用sink->locked_backend()->scan_for_files()
來掃描其餘實例創建的日誌文件。express
以上都是使用程序自己使用單日誌文件的狀況,若是須要根據請求的不一樣將消息分發到不一樣的文件,可使用sinks::text_mutlifile_backend
。該後端經常使用於多線程調試。windows
除了文件後端,更經常使用的是文本流後端sinks::text_ostream_backend
,與別的後端不一樣,文本流後端能夠添加多個輸出對象,這些對象因爲都在同一個sink
中,因此輸出格式是同樣的,這種作法的性能比添加文件後端更高,可是會失去對文件的控制能力。後端
對於大規模應用程序,爲了方便查看記錄,各模塊的日誌應該相互獨立,所以一個logger通常是不夠的,咱們須要本身創建logger。logger的創建方法很簡單,new一個src::logger就能夠了…安全
若是真的只須要一個logger,除了使用前面提到的trivial中的宏之外,也能夠用BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger,src::logger_mt)
,本身定義屬於本身的全局logger。而後在須要的時候使用src::logger_mt& lg=my_logger::get()
得到logger的單例引用(這裏最好是線程安全的logger,顯然)。多線程
logger的使用方法:frontend
1 2 3 4 5 6 7 8 |
logging::record rec=log.open_record();
if(rec) { logging::record_ostream strm(rec); strm<<"Hello,World!"; strm.flush(); lg.push_record(boost::move(rec)); } |
以上能夠簡化成一個宏:BOOST_LOG(lg)<<"Hello World"
函數
attribute
是log record的附加信息,不一樣於通常的消息記錄,屬性能夠被單獨拿出來處理,做爲某種過濾條件,或者其餘使用。屬性分爲全局屬性,特定線程屬性和特定源的屬性。經常使用的屬性,如時間戳、計數器,boost.log
都已經有實現好的版本,直接使用logging::add_common_attributes()
能夠一次性得到LineID
,TimeStamp
, ProcessID
, ThreadID
這些經常使用屬性(單線程程序沒有線程ID)。post
能夠本身註冊安全等級,定義相關枚舉,而後使用其做爲src::serverity_logger<>
的模板參數初始化,就獲得了自定義Severity
屬性的logger。這種logger可使用BOOST_LOG_SEV(logger,serverity)
來記錄。性能
特定範圍的屬性能夠用來作一些特殊日誌,好比須要評估性能的地方可使用BOOST_LOG_SCOPED_THREAD_ATTR("Timeline",attrs::timer());
註冊一個時間線標籤。
此外,能夠給屬性定義佔位符,至關於註冊爲關鍵字,方便在流中使用。關於屬性的函數大多定義在expr
命名空間裏面。
set_formatter
的用法。格式化消息可使用stl格式expr::stream<<xxx
,也可使用boost::format
格式,即expr::format("%1%)%xxx
這種。爲了取得最大靈活性,能夠自定義一個formatter
。
過濾子,如前文,可使用sink.set_filter
來設置,可使用的過濾條件包括布爾表達式和lambda表達式等,若是想要肯定有沒有某個屬性,可以使用expr::has_attr()
。
寬字符。使用windows的話,這塊算是最噁心的部分了
boost.log
定義了大量輔助函數實現經常使用功能。
logging::add_console_log()
能夠直接添加控制檯sink,返回boost::shared_ptr<sinks::synchronous_sink<sinks::text_ostream_backend>>
,可利用返回值設置過濾器或其餘屬性。
logging::add_file_log()
,前文已經提過,能夠直接獲得文件sink…
最後logging::add_common_attributes
能夠得到經常使用屬性,前文也有詳解。
徹底封裝boost.log
的工程量比較大,不過對於小規模工程,使用一個初始化函數就足夠了,可是這會致使整個項目與boost
深度耦合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
/* * FILE: boost.log.init.hpp * INSTRUCTION: 這個文件用於初始化boost.log * DETAIL: 這裏從新定義了日誌級別和對應的文本內容. * 文件大小限制等信息被硬編碼在cpp文件中,若有需求能夠修改。 */ #ifndef BOOST_LOG_INIT_TAIRAN_HPP #define BOOST_LOG_INIT_TAIRAN_HPP #include <iostream> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/log/support/date_time.hpp> #include <boost/log/common.hpp> #include <boost/log/expressions.hpp> #include <boost/log/expressions/keyword.hpp> #include <boost/log/attributes.hpp> #include <boost/log/attributes/timer.hpp> #include <boost/log/sources/logger.hpp> #include <boost/log/sources/severity_logger.hpp> #include <boost/log/sinks/sync_frontend.hpp> #include <boost/log/sinks/text_file_backend.hpp> #include <boost/log/utility/setup/file.hpp> #include <boost/log/utility/setup/console.hpp> #include <boost/log/utility/setup/common_attributes.hpp> #include <boost/log/attributes/named_scope.hpp> namespace logging = boost::log; namespace attrs = boost::log::attributes; namespace src = boost::log::sources; namespace sinks = boost::log::sinks; namespace expr = boost::log::expressions; namespace keywords = boost::log::keywords; enum SeverityLevel { Log_Info, Log_Notice, Log_Debug, Log_Warning, Log_Error, Log_Fatal }; // The formatting logic for the severity level template< typename CharT, typename TraitsT > inline std::basic_ostream< CharT, TraitsT >& operator<< ( std::basic_ostream< CharT, TraitsT >& strm, SeverityLevel lvl) { static const char* const str[] = { "Info", "Notice", "Debug", "Warning", "Error", "Fatal" }; if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str))) strm << str[lvl]; else strm << static_cast< int >(lvl); return strm; } BOOST_LOG_ATTRIBUTE_KEYWORD(log_severity, "Severity", SeverityLevel) BOOST_LOG_ATTRIBUTE_KEYWORD(log_timestamp, "TimeStamp", boost::posix_time::ptime) BOOST_LOG_ATTRIBUTE_KEYWORD(log_uptime, "Uptime", attrs::timer::value_type) BOOST_LOG_ATTRIBUTE_KEYWORD(log_scope, "Scope", attrs::named_scope::value_type) void g_InitLog(); #endif |
實現:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include "boost.log.init.hpp" void g_InitLog() { logging::formatter formatter= expr::stream <<"["<<expr::format_date_time(log_timestamp,"%H:%M:%S") <<"]"<<expr::if_(expr::has_attr(log_uptime)) [ expr::stream<<" ["<<format_date_time(log_uptime,"%O:%M:%S")<<"]" ] <<expr::if_(expr::has_attr(log_scope)) [ expr::stream<<"["<<expr::format_named_scope(log_scope,keywords::format = "%n")<<"]" ] <<"<"<<log_severity<<">"<<expr::message; logging::add_common_attributes(); auto console_sink=logging::add_console_log(); auto file_sink=logging::add_file_log ( keywords::file_name="%Y-%m-%d_%N.log", //文件名 keywords::rotation_size=10*1024*1024, //單個文件限制大小 keywords::time_based_rotation=sinks::file::rotation_at_time_point(0,0,0) //天天重建 ); file_sink->locked_backend()->set_file_collector(sinks::file::make_collector( keywords::target="logs", //文件夾名 keywords::max_size=50*1024*1024, //文件夾所佔最大空間 keywords::min_free_space=100*1024*1024 //磁盤最小預留空間 )); file_sink->set_filter(log_severity>=Log_Warning); //日誌級別過濾 file_sink->locked_backend()->scan_for_files(); console_sink->set_formatter(formatter); file_sink->set_formatter(formatter); file_sink->locked_backend()->auto_flush(true); logging::core::get()->add_global_attribute("Scope",attrs::named_scope()); logging::core::get()->add_sink(console_sink); logging::core::get()->add_sink(file_sink); } |
使用:
調用g_initlog()
初始化一次之後,在任意位置聲明logger,使用宏BOOST_LOG_SEV(logger,SeverityLevel)<<"..."
來寫入日誌便可。