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 35 : DEFINE_LOGGER_VARIABLE(severity)
60 : {
61 12 : severity_t sev(msg.get_severity());
62 24 : severity::pointer_t severity(get_severity(msg, sev));
63 12 : 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 24 : auto params(get_params());
73 12 : 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 12 : value += severity->get_description();
95 :
96 12 : variable::process_value(msg, value);
97 : }
98 :
99 :
100 :
101 48289 : DEFINE_LOGGER_VARIABLE(message)
102 : {
103 48152 : if(msg.get_recursive_message())
104 : {
105 : // do nothing if we find a ${message} inside the message itself
106 2 : return;
107 : }
108 :
109 96300 : std::string const m(msg.get_message());
110 48150 : if(m.find("${") == std::string::npos)
111 : {
112 48135 : value += m;
113 : }
114 : else
115 : {
116 15 : msg.set_recursive_message(true);
117 30 : format f(m);
118 15 : value += f.process_message(msg);
119 15 : msg.set_recursive_message(false);
120 : }
121 :
122 48150 : variable::process_value(msg, value);
123 : }
124 :
125 :
126 :
127 37 : DEFINE_LOGGER_VARIABLE(project_name)
128 : {
129 : // when the advgetopt is properly connected to the logger, then the
130 : // logger will save the project name in its diagnostic map
131 : //
132 22 : map_diagnostics_t map(get_map_diagnostics(msg));
133 11 : auto it(map.find(DIAG_KEY_PROJECT_NAME));
134 11 : if(it != map.end())
135 : {
136 11 : value += it->second;
137 : }
138 :
139 11 : variable::process_value(msg, value);
140 11 : }
141 :
142 :
143 :
144 20 : 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 12 : map_diagnostics_t map(get_map_diagnostics(msg));
150 6 : auto it(map.find(DIAG_KEY_PROGNAME));
151 6 : if(it != map.end())
152 : {
153 6 : value += it->second;
154 : }
155 :
156 6 : variable::process_value(msg, value);
157 6 : }
158 :
159 :
160 :
161 46 : DEFINE_LOGGER_VARIABLE(version)
162 : {
163 : // when the advgetopt is properly connected to the logger, then the
164 : // logger will save the program version in its diagnostic map
165 : //
166 34 : map_diagnostics_t map(get_map_diagnostics(msg));
167 17 : auto it(map.find(DIAG_KEY_VERSION));
168 17 : if(it != map.end())
169 : {
170 15 : value += it->second;
171 : }
172 :
173 17 : variable::process_value(msg, value);
174 17 : }
175 :
176 :
177 :
178 8 : DEFINE_LOGGER_VARIABLE(build_date)
179 : {
180 0 : map_diagnostics_t map(get_map_diagnostics(msg));
181 0 : auto it(map.find(DIAG_KEY_BUILD_DATE));
182 0 : if(it != map.end())
183 : {
184 0 : value += it->second;
185 : }
186 :
187 0 : variable::process_value(msg, value);
188 0 : }
189 :
190 :
191 :
192 8 : DEFINE_LOGGER_VARIABLE(build_time)
193 : {
194 0 : map_diagnostics_t map(get_map_diagnostics(msg));
195 0 : auto it(map.find(DIAG_KEY_BUILD_TIME));
196 0 : if(it != map.end())
197 : {
198 0 : value += it->second;
199 : }
200 :
201 0 : variable::process_value(msg, value);
202 0 : }
203 :
204 :
205 :
206 8 : DEFINE_LOGGER_VARIABLE(filename)
207 : {
208 0 : value += msg.get_filename();
209 :
210 0 : variable::process_value(msg, value);
211 0 : }
212 :
213 :
214 :
215 11 : DEFINE_LOGGER_VARIABLE(basename)
216 : {
217 0 : std::string const filename(msg.get_filename());
218 0 : std::string::size_type const pos(filename.rfind('/'));
219 0 : if(pos == std::string::npos)
220 : {
221 0 : value += filename;
222 : }
223 : else
224 : {
225 0 : value += filename.substr(pos + 1);
226 : }
227 :
228 0 : variable::process_value(msg, value);
229 0 : }
230 :
231 :
232 :
233 8 : DEFINE_LOGGER_VARIABLE(path)
234 : {
235 0 : std::string const filename(msg.get_filename());
236 0 : std::string::size_type const pos(filename.rfind('/'));
237 0 : if(pos != std::string::npos)
238 : {
239 0 : value += filename.substr(0, pos);
240 : }
241 :
242 0 : variable::process_value(msg, value);
243 0 : }
244 :
245 :
246 :
247 11 : DEFINE_LOGGER_VARIABLE(function)
248 : {
249 0 : value += msg.get_function();
250 :
251 0 : variable::process_value(msg, value);
252 0 : }
253 :
254 :
255 :
256 11 : DEFINE_LOGGER_VARIABLE(line)
257 : {
258 0 : value += std::to_string(msg.get_line());
259 :
260 0 : variable::process_value(msg, value);
261 0 : }
262 :
263 :
264 :
265 80 : DEFINE_LOGGER_VARIABLE(diagnostic)
266 : {
267 18 : constexpr int FLAG_NESTED = 0x01;
268 18 : constexpr int FLAG_MAP = 0x02;
269 :
270 18 : std::int64_t nested_depth(-1);
271 36 : std::string key;
272 18 : int flags(0);
273 :
274 36 : for(auto p : get_params())
275 : {
276 18 : if(p->get_name() == "nested")
277 : {
278 8 : nested_depth = p->get_integer();
279 8 : flags |= FLAG_NESTED;
280 : }
281 10 : else if(p->get_name() == "map")
282 : {
283 10 : key = p->get_value();
284 10 : flags |= FLAG_MAP;
285 : }
286 : }
287 :
288 18 : if(flags == 0
289 18 : || (flags & FLAG_NESTED) != 0)
290 : {
291 8 : char sep('{');
292 16 : string_vector_t nested(get_nested_diagnostics(msg));
293 8 : size_t idx(0);
294 16 : if((flags & FLAG_NESTED) != 0
295 8 : && static_cast<ssize_t>(nested.size()) > nested_depth)
296 : {
297 2 : idx = nested.size() - nested_depth;
298 2 : value += sep;
299 2 : value += "...";
300 2 : sep = '/';
301 : }
302 :
303 40 : for(; idx < nested.size(); ++idx)
304 : {
305 16 : value += sep;
306 16 : sep = '/';
307 16 : value += nested[idx];
308 : }
309 8 : value += "}";
310 : }
311 :
312 18 : if(flags == 0
313 18 : || (flags & FLAG_MAP) != 0)
314 : {
315 20 : auto const diagnostics(get_map_diagnostics(msg));
316 10 : if(!diagnostics.empty())
317 : {
318 10 : if(key.empty())
319 : {
320 0 : char sep('<');
321 0 : for(auto d : diagnostics)
322 : {
323 0 : value += sep;
324 0 : sep = ':';
325 0 : value += d.first;
326 0 : value += '=';
327 0 : value += d.second;
328 : }
329 0 : value += '>';
330 : }
331 : else
332 : {
333 10 : auto it(diagnostics.find(key));
334 10 : if(it != diagnostics.end())
335 : {
336 10 : value += '<';
337 10 : value += key;
338 10 : value += '=';
339 10 : value += it->second;
340 10 : value += '>';
341 : }
342 : }
343 : }
344 : }
345 :
346 18 : variable::process_value(msg, value);
347 18 : }
348 :
349 :
350 : }
351 : // no name namespace
352 :
353 :
354 6 : } // snaplogger namespace
355 : // vim: ts=4 sw=4 et
|