Line data Source code
1 : /*
2 : * Copyright (c) 2013-2019 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 Implementation of the various logger variable support.
24 : *
25 : * This file implements the few logger variables which retrieves their
26 : * value from the message variable.
27 : */
28 :
29 :
30 : // self
31 : //
32 : #include "snaplogger/exception.h"
33 : #include "snaplogger/format.h"
34 : #include "snaplogger/map_diagnostic.h"
35 : #include "snaplogger/nested_diagnostic.h"
36 : #include "snaplogger/variable.h"
37 :
38 :
39 : // C++ lib
40 : //
41 : #include <iostream>
42 :
43 :
44 : // last include
45 : //
46 : #include <snapdev/poison.h>
47 :
48 :
49 :
50 : namespace snaplogger
51 : {
52 :
53 :
54 : namespace
55 : {
56 :
57 :
58 :
59 11 : DEFINE_LOGGER_VARIABLE(severity)
60 : {
61 0 : severity_t sev(msg.get_severity());
62 0 : severity::pointer_t severity(get_severity(msg, sev));
63 0 : if(severity == nullptr)
64 : {
65 : // not found, write value directly
66 : //
67 0 : value += std::to_string(static_cast<int>(sev));
68 0 : variable::process_value(msg, value);
69 0 : return;
70 : }
71 :
72 0 : auto params(get_params());
73 0 : if(!params.empty())
74 : {
75 0 : if(params[0]->get_name() == "format")
76 : {
77 0 : auto v(params[0]->get_value());
78 0 : if(v != "alpha")
79 : {
80 0 : if(v == "number")
81 : {
82 0 : value += std::to_string(static_cast<int>(sev));
83 0 : variable::process_value(msg, value);
84 0 : return;
85 : }
86 : throw invalid_variable(
87 : "the ${severity:format=alpha|number} variable cannot be set to \""
88 0 : + v
89 0 : + "\".");
90 : }
91 : }
92 : }
93 :
94 0 : value += severity->get_description();
95 :
96 0 : variable::process_value(msg, value);
97 : }
98 :
99 :
100 :
101 45605 : DEFINE_LOGGER_VARIABLE(message)
102 : {
103 45546 : if(msg.get_recursive_message())
104 : {
105 : // do nothing if we find a ${message} inside the message itself
106 1 : return;
107 : }
108 :
109 91090 : std::string const m(msg.get_message());
110 45545 : if(m.find("${") == std::string::npos)
111 : {
112 45541 : value += m;
113 : }
114 : else
115 : {
116 4 : msg.set_recursive_message(true);
117 8 : format f(m);
118 4 : value += f.process_message(msg);
119 4 : msg.set_recursive_message(false);
120 : }
121 :
122 45545 : variable::process_value(msg, value);
123 : }
124 :
125 :
126 :
127 24 : DEFINE_LOGGER_VARIABLE(project_name)
128 : {
129 : // when the advgetopt is properly connected to the logger, then the
130 : // logger will save the program name in its diagnostic map
131 : //
132 8 : map_diagnostics_t map(get_map_diagnostics(msg));
133 4 : auto it(map.find(DIAG_KEY_PROJECT_NAME));
134 4 : if(it != map.end())
135 : {
136 4 : value += it->second;
137 : }
138 :
139 4 : variable::process_value(msg, value);
140 4 : }
141 :
142 :
143 :
144 11 : DEFINE_LOGGER_VARIABLE(progname)
145 : {
146 : // when the advgetopt is properly connected to the logger, then the
147 : // logger will save the program name in its diagnostic map
148 : //
149 0 : map_diagnostics_t map(get_map_diagnostics(msg));
150 0 : auto it(map.find(DIAG_KEY_PROGNAME));
151 0 : if(it != map.end())
152 : {
153 0 : value += it->second;
154 : }
155 :
156 0 : variable::process_value(msg, value);
157 0 : }
158 :
159 :
160 :
161 24 : DEFINE_LOGGER_VARIABLE(version)
162 : {
163 : // when the advgetopt is properly connected to the logger, then the
164 : // logger will save the program name in its diagnostic map
165 : //
166 8 : map_diagnostics_t map(get_map_diagnostics(msg));
167 4 : auto it(map.find(DIAG_KEY_VERSION));
168 4 : if(it != map.end())
169 : {
170 4 : value += it->second;
171 : }
172 :
173 4 : variable::process_value(msg, value);
174 4 : }
175 :
176 :
177 :
178 8 : DEFINE_LOGGER_VARIABLE(build_date)
179 : {
180 : // when the advgetopt is properly connected to the logger, then the
181 : // logger will save the program name in its diagnostic map
182 : //
183 0 : map_diagnostics_t map(get_map_diagnostics(msg));
184 0 : auto it(map.find(DIAG_KEY_BUILD_DATE));
185 0 : if(it != map.end())
186 : {
187 0 : value += it->second;
188 : }
189 :
190 0 : variable::process_value(msg, value);
191 0 : }
192 :
193 :
194 :
195 8 : DEFINE_LOGGER_VARIABLE(build_time)
196 : {
197 : // when the advgetopt is properly connected to the logger, then the
198 : // logger will save the program name in its diagnostic map
199 : //
200 0 : map_diagnostics_t map(get_map_diagnostics(msg));
201 0 : auto it(map.find(DIAG_KEY_BUILD_TIME));
202 0 : if(it != map.end())
203 : {
204 0 : value += it->second;
205 : }
206 :
207 0 : variable::process_value(msg, value);
208 0 : }
209 :
210 :
211 :
212 8 : DEFINE_LOGGER_VARIABLE(filename)
213 : {
214 0 : value += msg.get_filename();
215 :
216 0 : variable::process_value(msg, value);
217 0 : }
218 :
219 :
220 :
221 11 : DEFINE_LOGGER_VARIABLE(basename)
222 : {
223 0 : std::string const filename(msg.get_filename());
224 0 : std::string::size_type const pos(filename.rfind('/'));
225 0 : if(pos == std::string::npos)
226 : {
227 0 : value += filename;
228 : }
229 : else
230 : {
231 0 : value += filename.substr(pos + 1);
232 : }
233 :
234 0 : variable::process_value(msg, value);
235 0 : }
236 :
237 :
238 :
239 8 : DEFINE_LOGGER_VARIABLE(path)
240 : {
241 0 : std::string const filename(msg.get_filename());
242 0 : std::string::size_type const pos(filename.rfind('/'));
243 0 : if(pos != std::string::npos)
244 : {
245 0 : value += filename.substr(0, pos);
246 : }
247 :
248 0 : variable::process_value(msg, value);
249 0 : }
250 :
251 :
252 :
253 11 : DEFINE_LOGGER_VARIABLE(function)
254 : {
255 0 : value += msg.get_function();
256 :
257 0 : variable::process_value(msg, value);
258 0 : }
259 :
260 :
261 :
262 11 : DEFINE_LOGGER_VARIABLE(line)
263 : {
264 0 : value += std::to_string(msg.get_line());
265 :
266 0 : variable::process_value(msg, value);
267 0 : }
268 :
269 :
270 :
271 8 : DEFINE_LOGGER_VARIABLE(diagnostic)
272 : {
273 0 : constexpr int FLAG_NESTED = 0x01;
274 0 : constexpr int FLAG_MAP = 0x02;
275 :
276 0 : std::int64_t nested_depth(-1);
277 0 : std::string key;
278 0 : int flags(0);
279 :
280 0 : for(auto p : get_params())
281 : {
282 0 : if(p->get_name() == "nested")
283 : {
284 0 : nested_depth = p->get_integer();
285 0 : flags |= FLAG_NESTED;
286 : }
287 0 : else if(p->get_name() == "map")
288 : {
289 0 : key = p->get_value();
290 0 : flags |= FLAG_MAP;
291 : }
292 : }
293 :
294 0 : if(flags == 0
295 0 : || (flags & FLAG_NESTED) != 0)
296 : {
297 0 : char sep('{');
298 0 : string_vector_t nested(get_nested_diagnostics(msg));
299 0 : size_t idx(0);
300 0 : if((flags & FLAG_NESTED) != 0
301 0 : && static_cast<ssize_t>(nested.size()) > nested_depth)
302 : {
303 0 : idx = nested.size() - nested_depth;
304 0 : value += sep;
305 0 : value += "...";
306 0 : sep = '/';
307 : }
308 :
309 0 : for(; idx < nested.size(); ++idx)
310 : {
311 0 : value += sep;
312 0 : sep = '/';
313 0 : value += nested[idx];
314 : }
315 0 : value += "}";
316 : }
317 :
318 0 : if(flags == 0
319 0 : || (flags & FLAG_MAP) != 0)
320 : {
321 0 : auto const diagnostics(get_map_diagnostics(msg));
322 0 : if(!diagnostics.empty())
323 : {
324 0 : if(key.empty())
325 : {
326 0 : char sep('<');
327 0 : for(auto d : diagnostics)
328 : {
329 0 : value += sep;
330 0 : sep = ':';
331 0 : value += d.first;
332 0 : value += '=';
333 0 : value += d.second;
334 : }
335 0 : value += '>';
336 : }
337 : else
338 : {
339 0 : auto it(diagnostics.find(key));
340 0 : if(it != diagnostics.end())
341 : {
342 0 : value += '<';
343 0 : value += key;
344 0 : value += '=';
345 0 : value += it->second;
346 0 : value += '>';
347 : }
348 : }
349 : }
350 : }
351 :
352 0 : variable::process_value(msg, value);
353 0 : }
354 :
355 :
356 : }
357 : // no name namespace
358 :
359 :
360 6 : } // snaplogger namespace
361 : // vim: ts=4 sw=4 et
|