/* * 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 default_sink.cpp * \author Andrey Semashev * \date 19.04.2007 * * \brief This header is the Boost.Log library implementation, see the library documentation * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. */ #include #include #include #if !defined(BOOST_LOG_NO_THREADS) #include #include #endif #include #include #include #include #include "default_sink.hpp" #include namespace boost { BOOST_LOG_OPEN_NAMESPACE #if !defined(BOOST_LOG_NO_THREADS) namespace aux { // Defined in thread_id.cpp void format_thread_id(char* buf, std::size_t size, thread::id tid); } // namespace aux #endif // !defined(BOOST_LOG_NO_THREADS) namespace sinks { namespace aux { BOOST_LOG_ANONYMOUS_NAMESPACE { //! A special time point type that contains decomposed date and time to avoid excessive calculations struct decomposed_time_point { struct date_type : public gregorian::greg_year_month_day { date_type(year_type y, month_type m, day_type d) : gregorian::greg_year_month_day(y, m, d) { } }; struct time_duration_type : public date_time::micro_res { typedef date_time::micro_res rep_type; hour_type hours; min_type minutes; sec_type seconds; fractional_seconds_type useconds; time_duration_type(hour_type h, min_type m, sec_type s, fractional_seconds_type u) : hours(h), minutes(m), seconds(s), useconds(u) { } }; date_type date; time_duration_type time; decomposed_time_point(date_type const& d, time_duration_type const& t) : date(d), time(t) { } }; inline const char* severity_level_to_string(boost::log::trivial::severity_level lvl) { switch (lvl) { case boost::log::trivial::trace: return "[trace] "; case boost::log::trivial::debug: return "[debug] "; case boost::log::trivial::info: return "[info] "; case boost::log::trivial::warning: return "[warning]"; case boost::log::trivial::error: return "[error] "; case boost::log::trivial::fatal: return "[fatal] "; default: return "[-] "; } } struct message_printer { typedef void result_type; explicit message_printer(boost::log::trivial::severity_level lvl) : m_level(lvl) { } #ifdef BOOST_LOG_USE_CHAR result_type operator() (std::string const& msg) const { #if !defined(BOOST_LOG_NO_THREADS) char thread_id_buf[64]; boost::log::aux::format_thread_id(thread_id_buf, sizeof(thread_id_buf), boost::log::aux::this_thread::get_id()); #endif const decomposed_time_point now = date_time::microsec_clock< decomposed_time_point >::local_time(); std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%06u] " #if !defined(BOOST_LOG_NO_THREADS) "[%s] " #endif "%s %s\n", static_cast< unsigned int >(now.date.year), static_cast< unsigned int >(now.date.month), static_cast< unsigned int >(now.date.day), static_cast< unsigned int >(now.time.hours), static_cast< unsigned int >(now.time.minutes), static_cast< unsigned int >(now.time.seconds), static_cast< unsigned int >(now.time.useconds), #if !defined(BOOST_LOG_NO_THREADS) thread_id_buf, #endif severity_level_to_string(m_level), msg.c_str()); } #endif #ifdef BOOST_LOG_USE_WCHAR_T result_type operator() (std::wstring const& msg) const { #if !defined(BOOST_LOG_NO_THREADS) char thread_id_buf[64]; boost::log::aux::format_thread_id(thread_id_buf, sizeof(thread_id_buf), boost::log::aux::this_thread::get_id()); #endif const decomposed_time_point now = date_time::microsec_clock< decomposed_time_point >::local_time(); std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%06u] " #if !defined(BOOST_LOG_NO_THREADS) "[%s] " #endif "%s %ls\n", static_cast< unsigned int >(now.date.year), static_cast< unsigned int >(now.date.month), static_cast< unsigned int >(now.date.day), static_cast< unsigned int >(now.time.hours), static_cast< unsigned int >(now.time.minutes), static_cast< unsigned int >(now.time.seconds), static_cast< unsigned int >(now.time.useconds), #if !defined(BOOST_LOG_NO_THREADS) thread_id_buf, #endif severity_level_to_string(m_level), msg.c_str()); } #endif private: const boost::log::trivial::severity_level m_level; }; } // namespace default_sink::default_sink() : sink(false), m_severity_name(boost::log::aux::default_attribute_names::severity()), m_message_name(boost::log::aux::default_attribute_names::message()), m_severity_extractor(boost::log::trivial::info) { } default_sink::~default_sink() { } bool default_sink::will_consume(attribute_value_set const&) { return true; } void default_sink::consume(record_view const& rec) { BOOST_LOG_EXPR_IF_MT(lock_guard< mutex_type > lock(m_mutex);) m_message_visitor(m_message_name, rec.attribute_values(), message_printer(m_severity_extractor(m_severity_name, rec).get())); std::fflush(stdout); } void default_sink::flush() { BOOST_LOG_EXPR_IF_MT(lock_guard< mutex_type > lock(m_mutex);) std::fflush(stdout); } } // namespace aux } // namespace sinks BOOST_LOG_CLOSE_NAMESPACE // namespace log } // namespace boost #include