/* * Copyright Andrey Semashev 2007 - 2015. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ /*! * \file main.cpp * \author Andrey Semashev * \date 30.08.2009 * * \brief An example of asynchronous logging with bounded log record queue in multiple threads. */ // #define BOOST_LOG_DYN_LINK 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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; using boost::shared_ptr; enum { LOG_RECORDS_TO_WRITE = 10000, THREAD_COUNT = 2 }; BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(test_lg, src::logger_mt) //! This function is executed in multiple threads void thread_fun(boost::barrier& bar) { // Wait until all threads are created bar.wait(); // Here we go. First, identify the thread. BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::this_thread::get_id()); // Now, do some logging for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i) { BOOST_LOG(test_lg::get()) << "Log record " << i; } } int main(int argc, char* argv[]) { try { // Open a rotating text file shared_ptr< std::ostream > strm(new std::ofstream("test.log")); if (!strm->good()) throw std::runtime_error("Failed to open a text log file"); // Create a text file sink typedef sinks::text_ostream_backend backend_t; typedef sinks::asynchronous_sink< backend_t, sinks::bounded_ordering_queue< logging::attribute_value_ordering< unsigned int, std::less< unsigned int > >, 128, // queue no more than 128 log records sinks::block_on_overflow // wait until records are processed > > sink_t; shared_ptr< sink_t > sink(new sink_t( boost::make_shared< backend_t >(), // We'll apply record ordering to ensure that records from different threads go sequentially in the file keywords::order = logging::make_attr_ordering("RecordID", std::less< unsigned int >()))); sink->locked_backend()->add_stream(strm); sink->set_formatter ( expr::format("%1%: [%2%] [%3%] - %4%") % expr::attr< unsigned int >("RecordID") % expr::attr< boost::posix_time::ptime >("TimeStamp") % expr::attr< boost::thread::id >("ThreadID") % expr::smessage ); // Add it to the core logging::core::get()->add_sink(sink); // Add some attributes too logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock()); logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >()); // Create logging threads boost::barrier bar(THREAD_COUNT); boost::thread_group threads; for (unsigned int i = 0; i < THREAD_COUNT; ++i) threads.create_thread(boost::bind(&thread_fun, boost::ref(bar))); // Wait until all action ends threads.join_all(); // Flush all buffered records sink->stop(); sink->flush(); return 0; } catch (std::exception& e) { std::cout << "FAILURE: " << e.what() << std::endl; return 1; } }