Line data Source code
1 : /*
2 : * Copyright (c) 2013-2021 Made to Order Software Corp. All Rights Reserved
3 : *
4 : * https://snapwebsites.org/project/snaplogger
5 : * contact@m2osw.com
6 : *
7 : * This program is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 2 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * This program is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License along
18 : * with this program; if not, write to the Free Software Foundation, Inc.,
19 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 : */
21 :
22 : /** \file
23 : * \brief Appenders are used to append data to somewhere.
24 : *
25 : * This file declares the base appender class.
26 : */
27 :
28 : // self
29 : //
30 : #include "snaplogger/message.h"
31 :
32 : #include "snaplogger/exception.h"
33 : #include "snaplogger/logger.h"
34 :
35 :
36 : // C++ lib
37 : //
38 : #include <iostream>
39 :
40 :
41 : // C lib
42 : //
43 : #include <sys/time.h>
44 :
45 :
46 : // last include
47 : //
48 : #include <snapdev/poison.h>
49 :
50 :
51 :
52 : namespace snaplogger
53 : {
54 :
55 :
56 1064273 : int null_buffer::overflow(int c)
57 : {
58 1064273 : return c;
59 : }
60 :
61 :
62 :
63 :
64 :
65 91736 : message::message(
66 : severity_t sev
67 : , char const * file
68 : , char const * func
69 91736 : , int line)
70 : : f_logger(logger::get_instance())
71 : , f_severity(sev)
72 : , f_filename(file == nullptr ? std::string() : std::string(file))
73 : , f_funcname(func == nullptr ? std::string() : std::string(func))
74 : , f_line(line)
75 91736 : , f_environment(create_environment())
76 : {
77 91736 : clock_gettime(CLOCK_REALTIME_COARSE, &f_timestamp);
78 :
79 183472 : if(f_severity < f_logger->get_lowest_severity()
80 91736 : || f_severity == severity_t::SEVERITY_OFF)
81 : {
82 46782 : f_null.reset(new null_buffer);
83 46782 : std::ostream & ref = *this;
84 46782 : f_saved_buffer = ref.rdbuf(f_null.get());
85 : }
86 91736 : }
87 :
88 :
89 2 : message::message(std::basic_stringstream<char> const & m, message const & msg)
90 : : f_logger(msg.f_logger)
91 : , f_timestamp(msg.f_timestamp)
92 2 : , f_severity(msg.f_severity)
93 : , f_filename(msg.f_filename)
94 : , f_funcname(msg.f_funcname)
95 2 : , f_line(msg.f_line)
96 2 : , f_recursive_message(msg.f_recursive_message)
97 : , f_environment(msg.f_environment)
98 : , f_components(msg.f_components)
99 : , f_fields(msg.f_fields)
100 : , f_null(null_buffer::pointer_t())
101 : , f_saved_buffer(nullptr)
102 8 : , f_copy(true)
103 : {
104 2 : *this << m.rdbuf();
105 2 : }
106 :
107 :
108 183476 : message::~message()
109 : {
110 91738 : if(f_saved_buffer != nullptr)
111 : {
112 46782 : std::ostream & ref = *this;
113 46782 : ref.rdbuf(f_saved_buffer);
114 : }
115 91738 : }
116 :
117 :
118 0 : severity_t message::default_severity()
119 : {
120 0 : return logger::get_instance()->get_default_severity();
121 : }
122 :
123 :
124 26147 : void message::set_severity(severity_t severity)
125 : {
126 26147 : f_severity = severity;
127 26147 : }
128 :
129 :
130 1 : void message::set_filename(std::string const & filename)
131 : {
132 1 : f_filename = filename;
133 1 : }
134 :
135 :
136 1 : void message::set_function(std::string const & funcname)
137 : {
138 1 : f_funcname = funcname;
139 1 : }
140 :
141 :
142 1 : void message::set_line(int line)
143 : {
144 1 : f_line = line;
145 1 : }
146 :
147 :
148 34 : void message::set_recursive_message(bool state) const
149 : {
150 34 : f_recursive_message = state;
151 34 : }
152 :
153 :
154 8 : bool message::can_add_component(component::pointer_t c) const
155 : {
156 8 : if(c != nullptr)
157 : {
158 8 : return !c->is_mutually_exclusive(f_components);
159 : }
160 :
161 0 : return false;
162 : }
163 :
164 :
165 8 : void message::add_component(component::pointer_t c)
166 : {
167 8 : if(c != nullptr)
168 : {
169 8 : if(!can_add_component(c))
170 : {
171 : throw duplicate_error(
172 : "component \""
173 0 : + c->get_name()
174 0 : + "\" cannot be added to this message as it is mutually exclusive with one or more of the other components that were added to this message.");
175 : }
176 :
177 8 : f_components.insert(c);
178 : }
179 8 : }
180 :
181 :
182 3 : void message::add_field(std::string const & name, std::string const & value)
183 : {
184 3 : if(!name.empty())
185 : {
186 3 : f_fields[name] = value;
187 : }
188 3 : }
189 :
190 :
191 45882 : std::shared_ptr<logger> message::get_logger() const
192 : {
193 45882 : return f_logger;
194 : }
195 :
196 :
197 183491 : severity_t message::get_severity() const
198 : {
199 183491 : return f_severity;
200 : }
201 :
202 :
203 0 : void message::set_precise_time()
204 : {
205 0 : clock_gettime(CLOCK_REALTIME, &f_timestamp);
206 0 : }
207 :
208 :
209 4 : timespec const & message::get_timestamp() const
210 : {
211 4 : return f_timestamp;
212 : }
213 :
214 :
215 2 : std::string const & message::get_filename() const
216 : {
217 2 : return f_filename;
218 : }
219 :
220 :
221 2 : std::string const & message::get_function() const
222 : {
223 2 : return f_funcname;
224 : }
225 :
226 :
227 2 : int message::get_line() const
228 : {
229 2 : return f_line;
230 : }
231 :
232 :
233 45719 : bool message::get_recursive_message() const
234 : {
235 45719 : return f_recursive_message;
236 : }
237 :
238 :
239 0 : bool message::has_component(component::pointer_t c) const
240 : {
241 0 : return f_components.find(c) != f_components.end();
242 : }
243 :
244 :
245 137459 : component::set_t const & message::get_components() const
246 : {
247 137459 : return f_components;
248 : }
249 :
250 :
251 29 : environment::pointer_t message::get_environment() const
252 : {
253 29 : return f_environment;
254 : }
255 :
256 :
257 45717 : std::string message::get_message() const
258 : {
259 45717 : std::string s(str());
260 :
261 91434 : if(!s.empty()
262 45717 : && s.back() == '\n')
263 : {
264 4 : s.pop_back();
265 : }
266 :
267 91434 : if(!s.empty()
268 45717 : && s.back() == '\r')
269 : {
270 2 : s.pop_back();
271 : }
272 :
273 45717 : return s;
274 : }
275 :
276 :
277 1 : std::string message::get_field(std::string const & name) const
278 : {
279 1 : auto it(f_fields.find(name));
280 1 : if(it == f_fields.end())
281 : {
282 0 : return std::string();
283 : }
284 1 : return it->second;
285 : }
286 :
287 :
288 1 : message::field_map_t message::get_fields() const
289 : {
290 1 : return f_fields;
291 : }
292 :
293 :
294 91729 : void send_message(std::basic_ostream<char> & out)
295 : {
296 91729 : message * msg(dynamic_cast<message *>(&out));
297 91729 : if(msg == nullptr)
298 : {
299 1 : throw not_a_message("the 'out' parameter to the send_message() function is expected to be a snaplogger::message object.");
300 : }
301 :
302 91728 : logger::get_instance()->log_message(*msg);
303 91728 : }
304 :
305 :
306 :
307 :
308 6 : } // snaplogger namespace
309 : // vim: ts=4 sw=4 et
|