I have done a lot of boost log examples, now To sum up, the latest code in my open source project: https://gitlab.com/mystudy/boost_log
The architecture diagram of the boost log library is as follows:
The following summarizes the knowledge related to this architecture:
1. How to obtain the Logging core
#include <boost/log/core.hpp>...boost::shared_ptr<logging::core> core = logging::core::get();
2. How to install the Sink object
Multiple sinks can be installed on one core. The following Code assumes that two Sink objects exist and installs them into the core.
core->add_sink(sink1);... core->add_sink(sink2);
3. How to Create a Sink object
You must first create a backend object, and then pass the backend object to it when creating the sink object.
typedef sinks::synchronous_sink<sinks::text_file_backend> TextSink; // init sink1 boost::shared_ptr<sinks::text_file_backend> backend1 = boost::make_shared<sinks::text_file_backend>( keywords::file_name = "sign_%Y-%m-%d_%H-%M-%S.%N.log", keywords::rotation_size = 10 * 1024 * 1024, keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), keywords::min_free_space = 30 * 1024 * 1024); boost::shared_ptr<TextSink> sink1(new TextSink(backend1));
4. How to Create a backend object to specify the frontend type
As shown in the previous Code, note that a frontend type must be set as its template class for the backend type. Therefore, when you create a backend object, you have determined the frontend.
This frontend template can use the synchronous_sink class or asynchronous_sink class. The latter does not block the calling program and will create additional threads to process logs. However, it will be slower and the memory consumption will increase. It is generally recommended that the latter be used first.
Construct parameters with keywords
Here we can see a concept: keywords. There are 27 hpp files in the boost/log/keywords/directory:
auto_flush.hpp facility.hpp ident.hpp log_source.hpp open_mode.hpp rotation_size.hpp target.hppchannel.hpp file_name.hpp ip_version.hpp max_size.hpp order.hpp scan_method.hpp time_based_rotation.hppdelimiter.hpp filter.hpp iteration.hpp message_file.hpp ordering_window.hpp severity.hpp use_impl.hppdepth.hpp format.hpp log_name.hpp min_free_space.hpp registration.hpp start_thread.hpp
Keywords is the basic concept of the boost library. It is designed to a macro BOOST_PARAMETER_KEYWORD, which is defined in the boost/parameter/keywords. hpp file. The main function is to create a singleton object in the specified namespace. Therefore, the preceding lines of keywords: The Code assigns values to the singleton objects file_name, rotation, time_based_rotation, and min_free_space In the keywords namespace. The key is to see how the constructor of the following class uses these keywords.
sinks::text_file_backend
Reference:
Http://boost-log.sourceforge.net/libs/log/doc/html/log/detailed/sink_backends.html
Http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/boost/log/sinks/text_file_backend.html
Note: The text_file_backend constructor syntax supports variable parameters, but only supports limited keywords:
template< typename ArgsT > void construct(ArgsT const& args) { construct( filesystem::path(args[keywords::file_name | filesystem::path()]), args[keywords::open_mode | (std::ios_base::trunc | std::ios_base::out)], args[keywords::rotation_size | (std::numeric_limits< uintmax_t >::max)()], args[keywords::time_based_rotation | time_based_rotation_predicate()], args[keywords::auto_flush | false]); }
This is also true in the document. However, the Code for min_free_space is found in the text_file_backend.hpp file:
namespace aux { //! Creates and returns a file collector with the specified parameters BOOST_LOG_API shared_ptr< collector > make_collector( filesystem::path const& target_dir, uintmax_t max_size, uintmax_t min_free_space ); template< typename ArgsT > inline shared_ptr< collector > make_collector(ArgsT const& args) { return aux::make_collector( filesystem::path(args[keywords::target]), args[keywords::max_size | (std::numeric_limits< uintmax_t >::max)()], args[keywords::min_free_space | static_cast< uintmax_t >(0)]); }} // namespace aux
Therefore, it is estimated that the keywords such as target, max_size, and min_free_space can still be used. You will know it after trying it.
5. How to specify the format in sink
The following describes the specified log format, which must be specified in the sink, for example:
sink1->set_formatter (expr::format("[%1%]<%2%>(%3%): %4%")% expr::format_date_time< boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S")% expr::attr<sign_severity_level>("Severity")% expr::attr<attrs::current_thread_id::value_type>("ThreadID")% expr::smessage);
Boost: Format the key here is understanding expr: format. Documentation here: http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/detailed/expressions.html#log.detailed.expressions.formatters
I am using the Boost: Format style.
Attributes
Reference: http://boost-log.sourceforge.net/libs/log/doc/html/log/detailed/attributes.html
According to the design, log records are composed of attributes, so the printed content must be transmitted to the sink object in the form of attribute.
sink1->set_formatter (expr::format("[%1%]<%2%>(%3%)(%4%): %5%")% expr::attr<unsigned int>("LineID")% expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")% expr::attr<sign_severity_level>("Severity")% expr::attr<attrs::current_thread_id::value_type >("ThreadID")% expr::smessage);
Do not forget to add commont attributes
logging::add_common_attributes();
This function is defined in the boost/log/utility/setup/common_attributes.hpp file, which contains four attributes:
inline void add_common_attributes(){ shared_ptr< core > pCore = core::get(); pCore->add_global_attribute( aux::default_attribute_names::line_id(), attributes::counter< unsigned int >(1)); pCore->add_global_attribute( aux::default_attribute_names::timestamp(), attributes::local_clock()); pCore->add_global_attribute( aux::default_attribute_names::process_id(), attributes::current_process_id());#if !defined(BOOST_LOG_NO_THREADS) pCore->add_global_attribute( aux::default_attribute_names::thread_id(), attributes::current_thread_id());#endif}
6. Name scope
Name scope is also a solution in the preceding format, but it is described separately because it is complicated.
Stack element
First understand the structure named_scope_entry, the document in: http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/boost/log/attributes/named_scope_entry.html
Named_scope_entry contains scope_name, file_name, and line (source code line number). Each stack element is a name_scope_entry object.
Scope stack
Scope has a variety of, see the document: http://en.wikipedia.org/wiki/Scope_ (computer_science)
The most common function is the function stack. In this case, the scope stack is the function stack.
Boost log can print the scope stack information to the log.
Named_scope attributes
The named scope attribute can be added to the global attribute, Which is thread-related. Add the Property Code as follows:
logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
Reference: http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/boost/log/attributes/named_scope.html
Set format
Document: http://www.boost.org/doc/libs/1_54_0/libs/log/doc/html/log/detailed/expressions.html#log.detailed.expressions.formatters.named_scope
The following is a simple example:
First, add a format when setting the format:
% expr::format_named_scope("Scopes", boost::log::keywords::format = "%n (%f : %l)")
Then add the property:
core->add_global_attribute("Scopes", attrs::named_scope());
Then call the code to add a Bar and Foo function, here refer to the official documentation: http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/detailed/attributes.html#log.detailed.attributes.named_scope
void Bar() { int x = 0;}void Foo(int n) { src::severity_logger_mt<sign_severity_level>& lg = my_logger::get(); // Mark the scope of the function foo BOOST_LOG_FUNCTION(); switch (n) { case 0: {// Mark the current scopeBOOST_LOG_NAMED_SCOPE("case 0");BOOST_LOG(lg) << "Some log record";Bar(); // call some function } break; case 1: {// Mark the current scopeBOOST_LOG_NAMED_SCOPE("case 1");BOOST_LOG(lg) << "Some log record";Bar(); // call some function } break; default: {// Mark the current scopeBOOST_LOG_NAMED_SCOPE("default");BOOST_LOG(lg) << "Some log record";Bar(); // call some function } break; }}
Finally, call the following in the main. cc function:
Foo(1);
Execution result:
[8]<2014-03-01 23:49:19>(0)(0x00007f21bf00e740)(void Foo(int) (./main.cc : 11)->case 1 (./main.cc : 27)): Some log record
Note that two macros are used in the above Code: BOOST_LOG_NAMED_SCOPE and BOOST_LOG_FUNCTION. In fact, it is a macro. The macro is just a simplified version of the previous macro, and the current function can be used as the scope name automatically. Defined in the/boost/log/attributes/named_scope.hpp File
/*! * Macro for function scope markup. The scope name is constructed with help of compiler and contains current function name. * The scope name is pushed to the end of the current thread scope list. * * Not all compilers have support for this macro. The exact form of the scope name may vary from one compiler to another. */#define BOOST_LOG_FUNCTION() BOOST_LOG_NAMED_SCOPE(BOOST_CURRENT_FUNCTION)
The BOOST_LOG_NAMED_SCOPE macro is also defined in this file:
/*! * Macro for scope markup. The specified scope name is pushed to the end of the current thread scope list. */#define BOOST_LOG_NAMED_SCOPE(name)\ BOOST_LOG_NAMED_SCOPE_INTERNAL(BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_named_scope_sentry_), name, __FILE__, __LINE__)
#define BOOST_LOG_NAMED_SCOPE_INTERNAL(var, name, file, line)\ BOOST_LOG_UNUSED_VARIABLE(::boost::log::attributes::named_scope::sentry, var, (name, file, line));
The GCC compiler instruction _ attribute _ is used in the file/boost/log/utility/unused_variable.hpp __
#if defined(__GNUC__)//! The macro suppresses compiler warnings for \c var being unused#define BOOST_LOG_UNUSED_VARIABLE(type, var, initializer) __attribute__((unused)) type var initializer#else
So when BOOST_LOG_FUNCTION is used in the FOO function, this line of code is written:
__attribute__((unused)) ::boost::log::attributes::named_scope::sentry _boost_log_named_scope_sentry_18 (__PRETTY_FUNCTION__, "./main.cc", 18);;
So we can see that the number of lines of code here is fixed to 18. Therefore, if you want to display the number of lines of code when logging, you must write at least two rows of macros into the log:
BOOST_LOG_FUNCTION and BOOST_LOG_SEV macro.
7. filter
Filter can filter the log level and more. The following is an example:
sink1->set_filter(expr::attr<sign_severity_level>("Severity") >= trace);
The advanced filter documentation is here:
Http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/tutorial/advanced_filtering.html