1 /*
2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7 /*!
8 * \file default_sink.cpp
9 * \author Andrey Semashev
10 * \date 19.04.2007
11 *
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14 */
15
16 #include <boost/log/detail/config.hpp>
17 #include <cstdio>
18 #include <boost/optional/optional.hpp>
19 #if !defined(BOOST_LOG_NO_THREADS)
20 #include <boost/thread/locks.hpp>
21 #include <boost/log/detail/thread_id.hpp>
22 #endif
23 #include <boost/log/detail/default_attribute_names.hpp>
24 #include <boost/date_time/microsec_time_clock.hpp>
25 #include <boost/date_time/time_resolution_traits.hpp>
26 #include <boost/date_time/gregorian/gregorian_types.hpp>
27 #include "default_sink.hpp"
28 #include <boost/log/detail/header.hpp>
29
30 namespace boost {
31
32 BOOST_LOG_OPEN_NAMESPACE
33
34 #if !defined(BOOST_LOG_NO_THREADS)
35
36 namespace aux {
37
38 // Defined in thread_id.cpp
39 void format_thread_id(char* buf, std::size_t size, thread::id tid);
40
41 } // namespace aux
42
43 #endif // !defined(BOOST_LOG_NO_THREADS)
44
45 namespace sinks {
46
47 namespace aux {
48
49 BOOST_LOG_ANONYMOUS_NAMESPACE {
50
51 //! A special time point type that contains decomposed date and time to avoid excessive calculations
52 struct decomposed_time_point
53 {
54 struct date_type :
55 public gregorian::greg_year_month_day
56 {
57 date_type(year_type y, month_type m, day_type d) :
58 gregorian::greg_year_month_day(y, m, d)
59 {
60 }
61 };
62
63 struct time_duration_type :
64 public date_time::micro_res
65 {
66 typedef date_time::micro_res rep_type;
67
68 hour_type hours;
69 min_type minutes;
70 sec_type seconds;
71 fractional_seconds_type useconds;
72
73 time_duration_type(hour_type h, min_type m, sec_type s, fractional_seconds_type u) :
74 hours(h),
75 minutes(m),
76 seconds(s),
77 useconds(u)
78 {
79 }
80 };
81
82 date_type date;
83 time_duration_type time;
84
85 decomposed_time_point(date_type const& d, time_duration_type const& t) :
86 date(d),
87 time(t)
88 {
89 }
90 };
91
92 inline const char* severity_level_to_string(boost::log::trivial::severity_level lvl)
93 {
94 switch (lvl)
95 {
96 case boost::log::trivial::trace:
97 return "[trace] ";
98 case boost::log::trivial::debug:
99 return "[debug] ";
100 case boost::log::trivial::info:
101 return "[info] ";
102 case boost::log::trivial::warning:
103 return "[warning]";
104 case boost::log::trivial::error:
105 return "[error] ";
106 case boost::log::trivial::fatal:
107 return "[fatal] ";
108 default:
109 return "[-] ";
110 }
111 }
112
113 struct message_printer
114 {
115 typedef void result_type;
116
117 explicit message_printer(boost::log::trivial::severity_level lvl) : m_level(lvl)
118 {
119 }
120
121 #ifdef BOOST_LOG_USE_CHAR
122
123 result_type operator() (std::string const& msg) const
124 {
125 #if !defined(BOOST_LOG_NO_THREADS)
126 char thread_id_buf[64];
127 boost::log::aux::format_thread_id(thread_id_buf, sizeof(thread_id_buf), boost::log::aux::this_thread::get_id());
128 #endif
129
130 const decomposed_time_point now = date_time::microsec_clock< decomposed_time_point >::local_time();
131
132 std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%06u] "
133 #if !defined(BOOST_LOG_NO_THREADS)
134 "[%s] "
135 #endif
136 "%s %s\n",
137 static_cast< unsigned int >(now.date.year),
138 static_cast< unsigned int >(now.date.month),
139 static_cast< unsigned int >(now.date.day),
140 static_cast< unsigned int >(now.time.hours),
141 static_cast< unsigned int >(now.time.minutes),
142 static_cast< unsigned int >(now.time.seconds),
143 static_cast< unsigned int >(now.time.useconds),
144 #if !defined(BOOST_LOG_NO_THREADS)
145 thread_id_buf,
146 #endif
147 severity_level_to_string(m_level),
148 msg.c_str());
149 }
150
151 #endif
152
153 #ifdef BOOST_LOG_USE_WCHAR_T
154
155 result_type operator() (std::wstring const& msg) const
156 {
157 #if !defined(BOOST_LOG_NO_THREADS)
158 char thread_id_buf[64];
159 boost::log::aux::format_thread_id(thread_id_buf, sizeof(thread_id_buf), boost::log::aux::this_thread::get_id());
160 #endif
161
162 const decomposed_time_point now = date_time::microsec_clock< decomposed_time_point >::local_time();
163
164 std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%06u] "
165 #if !defined(BOOST_LOG_NO_THREADS)
166 "[%s] "
167 #endif
168 "%s %ls\n",
169 static_cast< unsigned int >(now.date.year),
170 static_cast< unsigned int >(now.date.month),
171 static_cast< unsigned int >(now.date.day),
172 static_cast< unsigned int >(now.time.hours),
173 static_cast< unsigned int >(now.time.minutes),
174 static_cast< unsigned int >(now.time.seconds),
175 static_cast< unsigned int >(now.time.useconds),
176 #if !defined(BOOST_LOG_NO_THREADS)
177 thread_id_buf,
178 #endif
179 severity_level_to_string(m_level),
180 msg.c_str());
181 }
182
183 #endif
184
185 private:
186 const boost::log::trivial::severity_level m_level;
187 };
188
189 } // namespace
190
191 default_sink::default_sink() :
192 sink(false),
193 m_severity_name(boost::log::aux::default_attribute_names::severity()),
194 m_message_name(boost::log::aux::default_attribute_names::message()),
195 m_severity_extractor(boost::log::trivial::info)
196 {
197 }
198
~default_sink()199 default_sink::~default_sink()
200 {
201 }
202
will_consume(attribute_value_set const &)203 bool default_sink::will_consume(attribute_value_set const&)
204 {
205 return true;
206 }
207
consume(record_view const & rec)208 void default_sink::consume(record_view const& rec)
209 {
210 BOOST_LOG_EXPR_IF_MT(lock_guard< mutex_type > lock(m_mutex);)
211 m_message_visitor(m_message_name, rec.attribute_values(), message_printer(m_severity_extractor(m_severity_name, rec).get()));
212 std::fflush(stdout);
213 }
214
flush()215 void default_sink::flush()
216 {
217 BOOST_LOG_EXPR_IF_MT(lock_guard< mutex_type > lock(m_mutex);)
218 std::fflush(stdout);
219 }
220
221 } // namespace aux
222
223 } // namespace sinks
224
225 BOOST_LOG_CLOSE_NAMESPACE // namespace log
226
227 } // namespace boost
228
229 #include <boost/log/detail/footer.hpp>
230