boost log使用
1.目標(biāo)
程序日志輸出改進(jìn)目標(biāo):
1. 用顏色區(qū)分錯誤和警告
2. 日志文件中用"warning"文本代替數(shù)字表示severity,便于日志中搜索
3. 合并log_setting.ini配置文件(到程序json配置文件,不使用init_from_stream)
4. 可同時輸出到console和文件
?
資料未整理完,以后再補(bǔ)充對程序的說明。
?
2.實現(xiàn)
log.h
enum SeverityLevel {SL_TRACE = 0,SL_DEBUG,SL_INFO,SL_WARNING,SL_ERROR,SL_CRITICAL };class Log { public:static void init_log(); private:static void init_logfile();static void init_console(); };boost::log::sources::severity_logger<SeverityLevel>* get_glog();?
log.cpp
#include "log.h"#include<ios> #include <boost/ref.hpp> #include <boost/bind.hpp> #include <boost/log/core.hpp> #include <boost/log/common.hpp> #include <boost/log/attributes.hpp> #include <boost/log/core/record.hpp> #include <boost/log/utility/setup/common_attributes.hpp> #include <boost/log/expressions.hpp> #include <boost/log/sinks/text_ostream_backend.hpp> #include <boost/log/support/date_time.hpp> #include <boost/log/utility/setup/file.hpp> #include <boost/core/null_deleter.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;/* Define place holder attributes */ BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int) BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime) //BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", logging::trivial::severity_level) //BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", logging::trivial::severity ) #include <boost/phoenix.hpp> BOOST_LOG_ATTRIBUTE_KEYWORD(process_id, "ProcessID", attrs::current_process_id::value_type ) BOOST_LOG_ATTRIBUTE_KEYWORD(thread_id, "ThreadID", attrs::current_thread_id::value_type )// Get Process native ID attrs::current_process_id::value_type::native_type get_native_process_id(logging::value_ref<attrs::current_process_id::value_type,tag::process_id> const& pid) {if (pid)return pid->native_id();return 0; }// Get Thread native ID attrs::current_thread_id::value_type::native_type get_native_thread_id(logging::value_ref<attrs::current_thread_id::value_type,tag::thread_id> const& tid) {if (tid)return tid->native_id();return 0; }typedef SeverityLevel severity_level; const char *get_severity_tag(severity_level level) {static const char* strings[] = {"trace","debug","info","waring","error","critical"};return static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings) ? strings[level] : std::to_string(level).c_str(); }void coloring_formatter(logging::record_view const& rec, logging::formatting_ostream& strm) {logging::value_ref< severity_level > level = logging::extract< severity_level >("Severity", rec);switch(level.get()) {case crush::common::SL_TRACE:case crush::common::SL_DEBUG:case crush::common::SL_INFO:strm << "\033[32m";break;case crush::common::SL_WARNING:strm << "\033[33m";break;case crush::common::SL_ERROR:case crush::common::SL_CRITICAL:strm << "\033[31m";break;default:break;}strm << logging::extract< unsigned int >("LineID", rec) << "|";auto date_time_formatter = expr::stream << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f");date_time_formatter(rec, strm);strm <<"|";strm<< std::dec<< logging::extract< attrs::current_process_id::value_type >("ProcessID", rec);strm << "|";strm<< std::dec<< logging::extract< attrs::current_thread_id::value_type >("ThreadID", rec);strm << "|";strm<< get_severity_tag(level.get());strm<< "|";strm<<"--";strm << rec[logging::expressions::smessage];// Restore the default colorstrm << "\033[0m"; }struct severity_tag; logging::formatting_ostream& operator<< (logging::formatting_ostream& strm,logging::to_log_manip< severity_level, severity_tag > const& manip ) {severity_level level = manip.get();strm << get_severity_tag(level);return strm; }BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(glog, boost::log::sources::severity_logger<SeverityLevel>);void Log::init_console() {typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();boost::shared_ptr< std::ostream > stream(&std::clog, boost::null_deleter());sink->locked_backend()->add_stream(stream);sink->set_formatter(&coloring_formatter);logging::core::get()->add_sink(sink); }void Log::init_logfile() {logging::add_file_log(keywords::file_name = "%Y-%m-%d_%5N.log",keywords::rotation_size = 10 * 1024 * 1024,keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),keywords::auto_flush = true,keywords::open_mode = std::ios::out | std::ios::app,keywords::format =(expr::stream<< expr::attr< unsigned int >("LineID")<<"|"<< expr::format_date_time(expr::attr< boost::posix_time::ptime >("TimeStamp"), "%Y-%m-%d, %H:%M:%S.%f") << "|"<< boost::phoenix::bind(&get_native_process_id, process_id.or_none()) << ":"<< boost::phoenix::bind(&get_native_thread_id, thread_id.or_none()) << "|"<< "[" << expr::attr< severity_level, severity_tag >("Severity")<< "] " << expr::smessage)); } void Log::init_log() {logging::core::get()->set_filter([](const logging::attribute_value_set& attr_set) {return attr_set["Severity"].extract<severity_level>() >= SL_WARNING;});init_logfile();init_console();logging::add_common_attributes(); }boost::log::sources::severity_logger<SeverityLevel>* get_glog() {return &(glog::get()); }3.使用
#include "log.h"void test_log() {Log::init();BOOST_LOG_SEV(*(crush::common::get_glog()), SL_TRACE) << "A trace severity message";BOOST_LOG_SEV(*(crush::common::get_glog()), SL_DEBUG) << "A debug severity message";BOOST_LOG_SEV(*(crush::common::get_glog()), SL_INFO) << "An informational severity message";BOOST_LOG_SEV(*(crush::common::get_glog()), SL_WARNING) << "A warning severity message";BOOST_LOG_SEV(*(crush::common::get_glog()), SL_ERROR) << "An error severity message";BOOST_LOG_SEV(*(crush::common::get_glog()), SL_CRITICAL) << "A fatal severity message";LOG_TRACE<<"this a trace";LOG_ERROR<<"this a error";return; }4.資料
4.1Howto
How to add color coding to boost::log console output?
https://stackoverflow.com/questions/38309479/how-to-add-color-coding-to-boostlog-console-output
A simple, customized logger, based on Boost.Log v2
http://gernotklingler.com/blog/simple-customized-logger-based-boost-log-v2/
how to print ProcessID and ThreadID in dec-format with boost.log
https://stackoverflow.com/questions/27597196/how-to-print-processid-and-threadid-in-dec-format-with-boost-log
how to customize “TimeStamp” format of Boost.Log
https://stackoverflow.com/questions/5947018/how-to-customize-timestamp-format-of-boost-log
How to use boost::log::expressions::format_date_time in a custom formatting function?
https://stackoverflow.com/questions/24287547/how-to-use-boostlogexpressionsformat-date-time-in-a-custom-formatting-func
boost log, why not print threadid and processid
https://stackoverflow.com/questions/46337337/boost-log-why-not-print-threadid-and-processid
Boost set_filter is not working
https://stackoverflow.com/questions/29707017/boost-set-filter-is-not-working
boost.log : using c++11 lambda expression to filter severity level
https://stackoverflow.com/questions/32399608/boost-log-using-c11-lambda-expression-to-filter-severity-level
Boost log and severity / local attributes
https://stackoverflow.com/questions/35895199/boost-log-and-severity-local-attributes
支持__FILE__,__LINE__
boost.log要點(diǎn)筆記
https://www.cnblogs.com/liaocheng/p/4222885.html
?
4.2官方文檔
Setting up sinks
https://www.boost.org/doc/libs/1_67_0/libs/log/doc/html/log/tutorial/sinks.html
Adding more information to log: Attributes
https://www.boost.org/doc/libs/1_67_0/libs/log/doc/html/log/tutorial/attributes.html
https://www.boost.org/doc/libs/1_67_0/libs/log/doc/html/log/detailed/expressions.html#log.detailed.expressions.attr
Sink backends
https://www.boost.org/doc/libs/master/libs/log/doc/html/log/detailed/sink_backends.html
Filters
http://boost-log.sourceforge.net/libs/log1/doc/html/log/detailed/filters.html
Log record formatting
https://www.boost.org/doc/libs/1_67_0/libs/log/doc/html/log/tutorial/formatters.html
logging::init_from_settings,
https://www.boost.org/doc/libs/1_67_0/libs/log/doc/html/log/detailed/utilities.html#log.detailed.utilities.setup.filter_formatter
?
5.經(jīng)驗
5.1使用logging::formatter_factory
#日志輸出格式
Format=[%TimeStamp% PID:%ProcessID% ThreadID:%ThreadID%] [%Severity%] %MyScopes% %Message%"
注意%MyScopes%
struct ScopeListFormatter {typedef attrs::named_scope::value_type scope_stack;explicit ScopeListFormatter(logging::attribute_name const &name) :name_(name) {}/// @notes/// rec.attribute_values()是attrs::named_scope::value_type嗎?/// 代碼的運(yùn)行效果是:%MyScopes%處輸出有顏色的當(dāng)前時間. /// ? 無法控制日志輸出的其它項,如%Message%void operator()(logging::record_view const &rec, logging::formatting_ostream &strm) const {// We need to acquire the attribute value from the log recordlogging::value_ref< severity_level > level = logging::extract< severity_level >("Severity", rec);if (level==SL_ERROR)strm<< "\033[31m";logging::visit<scope_stack>(name_,rec.attribute_values(),boost::bind(&ScopeListFormatter::format, _1, boost::ref(strm)));strm<<"\033[0m";}private://! This is where our custom formatting takes placestatic void format(scope_stack const &scopes, logging::formatting_ostream &strm) {using namespace std::chrono;system_clock::time_point time_now = system_clock::now();microseconds duration_in_mics = duration_cast<microseconds>(time_now.time_since_epoch());strm << "[" << duration_in_mics.count() << "]";scope_stack::const_iterator it = scopes.begin(), end = scopes.end();/// @notes /// .scopes是空的,怎么才能加入元素?/// . it->scope_name,it->file_name的含義和使用? for (; it != end; ++it) {strm << "\t" << it->scope_name << " [" << it->file_name << ":" << it->line << "]\n";}}private:logging::attribute_name name_; };class MyScopesFormatterFactory :public logging::formatter_factory<char> { public: // // * This function creates a formatter for the MyScopes attribute. // * It effectively associates the attribute with the scope_list_formatter class //formatter_type create_formatter(logging::attribute_name const &attr_name, args_map const &args) {return formatter_type(ScopeListFormatter(attr_name));} };調(diào)用代碼:
logging::register_formatter_factory("MyScopes", boost::make_shared<MyScopesFormatterFactory>()); logging::core::get()->add_global_attribute("MyScopes", attrs::named_scope());?
5.2使用logging::init_from_stream
[Core] #是否開啟Log DisableLogging=false[Sinks.TextFileSettings] #輸出到哪,支持TextFile Console Destination=Console#過濾日志等級 #trace = 0, debug = 1, info = 2, warning = 3, error = 4, critical = 5 Filter="%Severity% >= 0"#輸出的文件名 FileName="%Y-%m-%d_%5N.log"#單個log文件大小 RotationSize=204800000#產(chǎn)生新的log文件時間點(diǎn) RotationTimePoint="00:00:00"#是否開啟追加 Append=true#是否自動刷新 AutoFlush=true#日志輸出格式 Format="[%TimeStamp% PID:%ProcessID% ThreadID:%ThreadID%] [%Severity%] %MyScopes% %Message%"#是否開啟異步 Asynchronous=false使用代碼:
std::ifstream settings(filepath); logging::init_from_stream(settings);5.3自定義severity
severity_level類型
不同的severity_level定義,coloring_formatter中l(wèi)evel的內(nèi)容不同.?? ??? ?
? 異常的原因是未指定?SeverityLevel參數(shù)
修改
boost::log::sources::severity_logger<>* get_glog(); BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(glog, boost::log::sources::severity_logger<>);???為:
boost::log::sources::severity_logger<SeverityLevel>* get_glog(); BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(glog, boost::log::sources::severity_logger<SeverityLevel>);?? ????
5.4 logging::formatter
console的格式化輸出的另外一種方式.?? ??? ??
void Log::init_console() {typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();boost::shared_ptr< std::ostream > stream(&std::clog, boost::null_deleter());sink->locked_backend()->add_stream(stream);// ? sink->set_formatter(&coloring_formatter);/// @note 是phoneix函數(shù)對象?logging::formatter formatter = expr::stream<< std::setw(7) << std::setfill('0') << line_id << std::setfill(' ') << " | "<< expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f") << " "<< "[" << logging::trivial::severity << "]"<< " - " << expr::smessage;sink->set_formatter(formatter)logging::core::get()->add_sink(sink); }boost 的函數(shù)式編程庫 Phoenix入門學(xué)習(xí)
https://blog.csdn.net/doon/article/details/9119601
?? ??? ?
5.5 BOOST_LOG_ATTRIBUTE_KEYWORD
查看宏展開代碼
創(chuàng)建test2.cpp,內(nèi)容如下:
編譯:
? g++ -std=c++11 -g -E -P ?-c ./test2.cpp > b.txt查看b.txt內(nèi)容:
line_id,timestamp展開后的定義:
相關(guān)宏:
文件:/usr/local/include/boost/log/expressions/keyword.hpp
默認(rèn)屬性:?? ?
namespace boost { namespace log { inline namespace v2s_mt_posix { namespace aux { namespace default_attribute_names {attribute_name severity();attribute_name channel();attribute_name message();attribute_name line_id();attribute_name timestamp();attribute_name process_id();attribute_name thread_id(); } } }} }5.6 keywords::format指定?? ?
void Log::init_logfile() {logging::add_file_log(keywords::file_name = "%Y-%m-%d_%5N.log",keywords::rotation_size = 10 * 1024 * 1024,keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),keywords::auto_flush = true,keywords::open_mode = ?std::ios::out | std::ios::app,/// @notes 屬性名稱方式// ? ? ? keywords::format = "[%TimeStamp% PID:%ProcessID% ThreadID:%ThreadID%] [%Severity%] ?%Message%"// @question 以下是lambda還是phoneix?keywords::format =(expr::stream<< expr::attr< unsigned int >("LineID")<<"|"<< expr::format_date_time(expr::attr< boost::posix_time::ptime >("TimeStamp"), "%Y-%m-%d, %H:%M:%S.%f") << "|"<< boost::phoenix::bind(&get_native_process_id, process_id.or_none()) << ":"<< boost::phoenix::bind(&get_native_thread_id, thread_id.or_none()) << "|"/// @question 以下2行代碼輸出的內(nèi)容怎么是空的? // ? ? ?? ?<< logging::expressions::attr<logging::attributes::current_thread_id::value_type>("ThreadID") << ":" // ??? ?<< logging::expressions::attr<logging::attributes::current_process_id::value_type>("ProcessID") << ?"|"<< "[" << expr::attr< severity_level, severity_tag >("Severity")<< "] " << expr::smessage)); }?? ?5.7add_global_attribute
? ? boost::shared_ptr< logging::core > core = logging::core::get();core->add_global_attribute("LineID", attrs::counter< unsigned int >(1));core->add_global_attribute("TimeStamp", attrs::local_clock());5.8set_filter
方法1:
? logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::info);方法2:對于自定義severity級別 ?
? logging::core::get()->set_filter([](const logging::attribute_value_set& attr_set) {return attr_set["Severity"].extract<severity_level>() >= SL_WARNING;}) ?5.9logging::init_from_settings
以下代碼未驗證
void init_logging() {logging::settings setts;setts["Core"]["Filter"] = "%Severity% >= warning";setts["Core"]["DisableLogging"] = false;// Subsections can be referred to with a single pathsetts["Sinks.Console"]["Destination"] = "Console";setts["Sinks.Console"]["Filter"] = "%Severity% >= fatal";setts["Sinks.Console"]["AutoFlush"] = true;// ...as well as the individual parameterssetts["Sinks.File.Destination"] = "TextFile";setts["Sinks.File.FileName"] = "MyApp_%3N.log";setts["Sinks.File.AutoFlush"] = true;setts["Sinks.File.RotationSize"] = 10 * 1024 * 1024; // 10 MiBlogging::init_from_settings(setts); }?
總結(jié)
以上是生活随笔為你收集整理的boost log使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 11 月亚马逊云科技培训与认证课程,精彩
- 下一篇: 总结使用libwebsockets开发接