Classes | |
struct | holder |
Holds up to 10 tags. More... | |
struct | file_line |
tag that holds file/line context information More... | |
struct | function |
tag that holds function name context information More... | |
struct | level |
tag that holds the log level context information More... | |
struct | time |
tag that holds the current time context information More... | |
struct | module |
tag that holds module context information (note: you need to specify the module yourself) More... | |
struct | thread_id |
tag that holds thread id context information More... | |
struct | high_precision_time |
tag that holds the current time (with high precision) context information More... |
#define LDBG_ BOOST_LOG_USE_LOG_IF_LEVEL(g_l(), g_log_level(), debug ) << __FILE__ << ":" << __LINE__ << " [dbg] "
In the above case, you appended file & line, and the level of the logged message. Usage is just the same:
std::string hello = "hello", world = "world"; LAPP_ << hello << ", " << world;
The output could look like:
my_cool_sample:234 [dbg] hello, world
I can see a few issues with the above
[idx] file_and_line [time] message [level]
?" << __FILE__ << ":" << __LINE__ << " [dbg] "
, in the above case, takes time. It is much faster to only gather the context on the current thread, and then dump it on the dedicated thread. You can use tags for that.If you're ok with the above issues, no need to delve into tags. You can dump context like shown above, and be fine with it.
Otherwise, welcome to the world of tags!
#include <boost/logging/format_fwd.hpp>
A tag class is deadly simple. Here are a few examples:
struct file_line { file_line(const char * val = "") : val(val) {} const char * val; }; struct time { time() : val( ::time(0) ) {} ::time_t val; };
They only allow holding the context, and making sure you can get to it - when doing formatting. You can of course add your own tag clases.
You will replace your old BOOST_LOG_FORMAT_MSG(string_class)
usage, with tags. In case you don't have a BOOST_LOG_FORMAT_MSG in your application, the string_class is std::(w)string.
// old BOOST_LOG_FORMAT_MSG( optimize::cache_string_one_str<> ) // new - use tags // // In our case, time, file/line, function name typedef tag::holder< optimize::cache_string_one_str<>, tag::time, tag::file_line, tag::function> string; BOOST_LOG_FORMAT_MSG( string )
In your LOG macros, you need to append the tags like this:
.set_tag( tag_class( tag_init_values) )
Examples:
// add file/line and function tags #define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() ) .set_tag(BOOST_LOG_TAG_FILELINE) .set_tag(BOOST_LOG_TAG_FUNCTION) // add function and level #define LDBG_ BOOST_LOG_USE_LOG_IF_LEVEL(g_log_dbg(), g_log_level(), debug ) .set_tag(BOOST_LOG_TAG_FUNCTION) .set_tag( BOOST_LOG_TAG_LEVEL(debug) ) // add module information - you specify the module name whe using the L_ macro. Example: // L_("chart") << "Initializing environment"; #define L_(module_name) BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() ) .set_tag( BOOST_LOG_TAG(module)(module_name) )
#include <boost/logging/format/formatter/tags.hpp> ... g_l()->writer().add_formatter( formatter::idx() ); g_l()->writer().add_formatter( formatter::append_newline() ); // formatters to add the file/line and level g_l()->writer().add_formatter( formatter::tag::file_line() ); g_l()->writer().add_formatter( formatter::tag::level() ); g_l()->writer().add_destination( destination::file("out.txt") ); g_l()->writer().add_destination( destination::cout() ); g_l()->writer().add_destination( destination::dbg_window() );
Note that the library comes with default formatters for each tag class. However, you can create your own formatter class, for a given tag class.
The formatters that come with the library, have the same name as the tag class itself, only that they're in the formatter::tag
namespace.
Examples:
When adding the formatters, don't forget to:
#include <boost/logging/format/formatter/tags.hpp>
[file/line] [thread_id] [idx] [time] message [enter]
Optimizations:
In this example, all output will be written to the console, debug window, and "out.txt" file. The output can look like:
logging\samples\scenarios\using_tags.cpp:94 [T7204] [1] 14:55 this is so cool 1 logging\samples\scenarios\using_tags.cpp:95 [T7204] [2] 14:55 this is so cool again 2
#include <boost/logging/format_fwd.hpp> namespace bl = boost::logging; typedef bl::tag::holder< bl::optimize::cache_string_one_str<>, bl::tag::file_line, bl::tag::thread_id, bl::tag::time> log_string; BOOST_LOG_FORMAT_MSG( log_string ) #include <boost/logging/format_ts.hpp> #include <boost/logging/format/formatter/tags.hpp> #include <boost/logging/format/formatter/named_spacer.hpp> using namespace boost::logging; using namespace boost::logging::scenario::usage; typedef use< // the filter is always accurate (but slow) filter_::change::always_accurate, // filter does not use levels filter_::level::no_levels, // the logger is initialized once, when only one thread is running logger_::change::set_once_when_one_thread, // the logger favors speed (on a dedicated thread) logger_::favor::speed> finder; BOOST_DECLARE_LOG_FILTER(g_log_filter, finder::filter ) BOOST_DECLARE_LOG(g_l, finder::logger) #define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() ) .set_tag( BOOST_LOG_TAG_FILELINE) BOOST_DEFINE_LOG_FILTER(g_log_filter, finder::filter ) BOOST_DEFINE_LOG(g_l, finder::logger) void using_tags_example() { // add formatters and destinations // That is, how the message is to be formatted and where should it be written to g_l()->writer().add_formatter( formatter::named_spacer( "%fileline% [T%thread_id%] [%idx%] %time%" ) .add( "time", formatter::tag::time("$mm:$ss ") ) // time tag .add( "idx", formatter::idx() ) .add( "thread_id", formatter::tag::thread_id() ) // thread_id tag .add( "fileline", formatter::tag::file_line() ) ); // file/line tag g_l()->writer().add_formatter( formatter::append_newline() ); g_l()->writer().add_destination( destination::cout() ); g_l()->writer().add_destination( destination::file("out.txt") ); g_l()->mark_as_initialized(); int i = 1; L_ << "this is so cool " << i++; L_ << "this is so cool again " << i++; } int main() { using_tags_example(); } // End of file
That's it, enjoy!