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(buf: thread_id_buf, size: sizeof(thread_id_buf), tid: 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(format: "[%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(lvl: 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(buf: thread_id_buf, size: sizeof(thread_id_buf), tid: 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(format: "[%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(lvl: 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 | |
199 | default_sink::~default_sink() |
200 | { |
201 | } |
202 | |
203 | bool default_sink::will_consume(attribute_value_set const&) |
204 | { |
205 | return true; |
206 | } |
207 | |
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 | |
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 | |