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 Severity levels for your log messages.
24 : *
25 : * The severity implementation loads the severity configuration file
26 : * and generates a set of severity levels that one can attach to
27 : * log messages.
28 : */
29 :
30 :
31 : // self
32 : //
33 : #include "snaplogger/severity.h"
34 :
35 : #include "snaplogger/exception.h"
36 : #include "snaplogger/guard.h"
37 : #include "snaplogger/private_logger.h"
38 :
39 :
40 : // advgetopt lib
41 : //
42 : #include <advgetopt/advgetopt.h>
43 : #include <advgetopt/options.h>
44 :
45 :
46 : // C++ lib
47 : //
48 : #include <iostream>
49 : #include <map>
50 :
51 :
52 : // C lib
53 : //
54 : #include <sys/time.h>
55 :
56 :
57 : // last include
58 : //
59 : #include <snapdev/poison.h>
60 :
61 :
62 :
63 : namespace snaplogger
64 : {
65 :
66 :
67 :
68 : namespace
69 : {
70 :
71 :
72 : bool g_severity_auto_added = false;
73 :
74 :
75 : struct system_severity
76 : {
77 : severity_t f_severity = severity_t::SEVERITY_ALL;
78 : char const * f_name = nullptr;
79 : char const * f_alias = nullptr; // at most 1 alias for system severities
80 : char const * f_description = nullptr;
81 : char const * f_styles = nullptr;
82 : };
83 :
84 : #pragma GCC diagnostic push
85 : #pragma GCC diagnostic ignored "-Wpedantic"
86 : constexpr system_severity g_system_severity[] =
87 : {
88 : {
89 : .f_severity = severity_t::SEVERITY_ALL,
90 : .f_name = "all",
91 : .f_alias = "everything",
92 : .f_description = "all",
93 : .f_styles = nullptr
94 : },
95 : {
96 : .f_severity = severity_t::SEVERITY_TRACE,
97 : .f_name = "trace",
98 : .f_alias = nullptr,
99 : .f_description = "trace",
100 : .f_styles = nullptr
101 : },
102 : {
103 : .f_severity = severity_t::SEVERITY_DEBUG,
104 : .f_name = "debug",
105 : .f_alias = "dbg",
106 : .f_description = "debug",
107 : .f_styles = nullptr
108 : },
109 : {
110 : .f_severity = severity_t::SEVERITY_NOTICE,
111 : .f_name = "notice",
112 : .f_alias = "note",
113 : .f_description = "notice",
114 : .f_styles = nullptr
115 : },
116 : {
117 : .f_severity = severity_t::SEVERITY_UNIMPORTANT,
118 : .f_name = "unimportant",
119 : .f_alias = nullptr,
120 : .f_description = "unimportant",
121 : .f_styles = nullptr
122 : },
123 : {
124 : .f_severity = severity_t::SEVERITY_INFORMATION,
125 : .f_name = "information",
126 : .f_alias = "info",
127 : .f_description = "info",
128 : .f_styles = nullptr
129 : },
130 : {
131 : .f_severity = severity_t::SEVERITY_IMPORTANT,
132 : .f_name = "important",
133 : .f_alias = "significant",
134 : .f_description = "important",
135 : .f_styles = "green"
136 : },
137 : {
138 : .f_severity = severity_t::SEVERITY_MINOR,
139 : .f_name = "minor",
140 : .f_alias = nullptr,
141 : .f_description = "minor",
142 : .f_styles = "green"
143 : },
144 : {
145 : .f_severity = severity_t::SEVERITY_DEPRECATED,
146 : .f_name = "deprecated",
147 : .f_alias = nullptr,
148 : .f_description = "deprecated",
149 : .f_styles = "orange"
150 : },
151 : {
152 : .f_severity = severity_t::SEVERITY_WARNING,
153 : .f_name = "warning",
154 : .f_alias = "warn",
155 : .f_description = "warning",
156 : .f_styles = "orange"
157 : },
158 : {
159 : .f_severity = severity_t::SEVERITY_MAJOR,
160 : .f_name = "major",
161 : .f_alias = "paramount",
162 : .f_description = "major",
163 : .f_styles = "orange"
164 : },
165 : {
166 : .f_severity = severity_t::SEVERITY_RECOVERABLE_ERROR,
167 : .f_name = "recoverable-error",
168 : .f_alias = "recoverable",
169 : .f_description = "recoverable error",
170 : .f_styles = "red"
171 : },
172 : {
173 : .f_severity = severity_t::SEVERITY_ERROR,
174 : .f_name = "error",
175 : .f_alias = "err",
176 : .f_description = "error",
177 : .f_styles = "red"
178 : },
179 : {
180 : .f_severity = severity_t::SEVERITY_CRITICAL,
181 : .f_name = "critical",
182 : .f_alias = "crit",
183 : .f_description = "critical",
184 : .f_styles = "red"
185 : },
186 : {
187 : .f_severity = severity_t::SEVERITY_ALERT,
188 : .f_name = "alert",
189 : .f_alias = nullptr,
190 : .f_description = "alert",
191 : .f_styles = "red"
192 : },
193 : {
194 : .f_severity = severity_t::SEVERITY_EMERGENCY,
195 : .f_name = "emergency",
196 : .f_alias = "emerg",
197 : .f_description = "emergency",
198 : .f_styles = "red"
199 : },
200 : {
201 : .f_severity = severity_t::SEVERITY_FATAL,
202 : .f_name = "fatal",
203 : .f_alias = "fatal-error",
204 : .f_description = "fatal",
205 : .f_styles = "red"
206 : },
207 : {
208 : .f_severity = severity_t::SEVERITY_OFF,
209 : .f_name = "off",
210 : .f_alias = nullptr,
211 : .f_description = "off",
212 : .f_styles = nullptr
213 : }
214 : };
215 :
216 :
217 :
218 :
219 : advgetopt::options_environment g_config_option =
220 : {
221 : .f_project_name = "logger",
222 : .f_options = nullptr,
223 : .f_options_files_directory = "/etc/snaplogger",
224 : .f_environment_variable_name = nullptr,
225 : .f_configuration_files = nullptr,
226 : .f_configuration_filename = "severity.ini",
227 : .f_configuration_directories = nullptr,
228 : .f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_DYNAMIC_PARAMETERS
229 :
230 : //.f_help_header = nullptr,
231 : //.f_help_footer = nullptr,
232 : //.f_version = nullptr,
233 : //.f_license = nullptr,
234 : //.f_copyright = nullptr,
235 : //.f_build_date = UTC_BUILD_DATE,
236 : //.f_build_time = UTC_BUILD_TIME,
237 : //.f_groups = nullptr
238 : };
239 : #pragma GCC diagnostic pop
240 :
241 :
242 :
243 33 : void auto_add_severities()
244 : {
245 34 : guard g;
246 :
247 33 : if(g_severity_auto_added)
248 : {
249 32 : return;
250 : }
251 1 : g_severity_auto_added = true;
252 :
253 2 : private_logger::pointer_t l(get_private_logger());
254 :
255 19 : for(auto ss : g_system_severity)
256 : {
257 36 : severity::pointer_t sev(std::make_shared<severity>(ss.f_severity, ss.f_name, true));
258 18 : if(ss.f_alias != nullptr)
259 : {
260 : // at this time we have one at the most here
261 : //
262 12 : sev->add_alias(ss.f_alias);
263 : }
264 18 : sev->set_description(ss.f_description);
265 18 : if(ss.f_styles != nullptr)
266 : {
267 11 : sev->set_styles(ss.f_styles);
268 : }
269 :
270 18 : l->add_severity(sev);
271 : }
272 :
273 : // load user editable parameters
274 : //
275 2 : advgetopt::getopt::pointer_t config(std::make_shared<advgetopt::getopt>(g_config_option));
276 1 : config->parse_configuration_files();
277 2 : advgetopt::option_info::map_by_name_t options(config->get_options());
278 1 : for(auto o : options)
279 : {
280 0 : std::string const name(o.second->get_name());
281 0 : std::string const basename(o.second->get_basename());
282 0 : if(name == basename)
283 : {
284 : // we found a section name, this is the name of a severity,
285 : // gather the info and create the new severity
286 : //
287 0 : severity::pointer_t sev(get_severity(name));
288 0 : if(sev != nullptr)
289 : {
290 : // it already exists...
291 : //
292 0 : if(sev->is_system())
293 : {
294 0 : std::string const severity_field(name + "::severity");
295 0 : if(config->is_defined(severity_field))
296 : {
297 0 : long const level(o.second->get_long());
298 0 : if(level < 0 || level > 255)
299 : {
300 0 : throw invalid_severity("severity level must be between 0 and 255.");
301 : }
302 0 : if(static_cast<severity_t>(level) != sev->get_severity())
303 : {
304 0 : throw invalid_severity("severity level of a system entry cannot be changed.");
305 : }
306 : }
307 : }
308 : else
309 : {
310 : throw duplicate_error("we found two severity levels named \""
311 0 : + name
312 0 : + "\" in your severity.ini file.");
313 : }
314 : }
315 : else
316 : {
317 0 : std::string const severity_field(name + "::severity");
318 0 : if(!config->is_defined(severity_field))
319 : {
320 0 : throw invalid_severity("severity level must be defined for non-system severity entries.");
321 : }
322 0 : long const level(config->get_long(severity_field));
323 0 : if(level < 0 || level > 255)
324 : {
325 : throw invalid_severity("severity level must be between 0 and 255, "
326 0 : + std::to_string(level)
327 0 : + " is not valid.");
328 : }
329 :
330 0 : sev = get_severity(static_cast<severity_t>(level));
331 0 : if(sev != nullptr)
332 : {
333 : throw duplicate_error("there is another severity with level "
334 0 : + std::to_string(level)
335 0 : + ", try using aliases=... instead.");
336 : }
337 :
338 0 : sev = std::make_shared<severity>(static_cast<severity_t>(level), name);
339 0 : l->add_severity(sev);
340 : }
341 :
342 0 : std::string const aliases_field(name + "::aliases");
343 0 : if(config->is_defined(aliases_field))
344 : {
345 0 : std::string const aliases(config->get_string(aliases_field));
346 0 : advgetopt::string_list_t names;
347 0 : advgetopt::split_string(aliases, names, {","});
348 0 : for(auto n : names)
349 : {
350 0 : sev->add_alias(n);
351 : }
352 : }
353 :
354 0 : std::string const description_field(name + "::description");
355 0 : if(config->is_defined(description_field))
356 : {
357 0 : sev->set_description(config->get_string(description_field));
358 : }
359 :
360 0 : std::string const styles_field(name + "::styles");
361 0 : if(config->is_defined(styles_field))
362 : {
363 0 : sev->set_styles(config->get_string(styles_field));
364 : }
365 : }
366 : }
367 : }
368 :
369 :
370 :
371 : }
372 : // no name namespace
373 :
374 :
375 :
376 :
377 24 : severity::severity(severity_t sev, std::string const & name, bool system)
378 : : f_severity(sev)
379 24 : , f_names(string_vector_t({name}))
380 48 : , f_system(system)
381 : {
382 24 : }
383 :
384 :
385 49 : severity_t severity::get_severity() const
386 : {
387 49 : return f_severity;
388 : }
389 :
390 :
391 6 : bool severity::is_system() const
392 : {
393 6 : return f_system;
394 : }
395 :
396 :
397 6 : std::string severity::get_name() const
398 : {
399 6 : return f_names[0];
400 : }
401 :
402 :
403 13 : void severity::add_alias(std::string const & name)
404 : {
405 13 : f_names.push_back(name);
406 :
407 26 : private_logger::pointer_t l(get_private_logger());
408 26 : severity::pointer_t s(l->get_severity(f_names[0]));
409 13 : if(s != nullptr)
410 : {
411 1 : l->add_severity(s);
412 : }
413 13 : }
414 :
415 :
416 49 : string_vector_t severity::get_all_names() const
417 : {
418 49 : return f_names;
419 : }
420 :
421 :
422 20 : void severity::set_description(std::string const & description)
423 : {
424 20 : f_description = description;
425 20 : }
426 :
427 :
428 15 : std::string severity::get_description() const
429 : {
430 15 : if(f_description.empty())
431 : {
432 2 : return get_name();
433 : }
434 13 : return f_description;
435 : }
436 :
437 :
438 12 : void severity::set_styles(std::string const & styles)
439 : {
440 12 : f_styles = styles;
441 12 : }
442 :
443 :
444 1 : std::string severity::get_styles() const
445 : {
446 1 : return f_styles;
447 : }
448 :
449 :
450 :
451 :
452 :
453 6 : void add_severity(severity::pointer_t sev)
454 : {
455 6 : auto_add_severities();
456 10 : get_private_logger()->add_severity(sev);
457 2 : }
458 :
459 :
460 9 : severity::pointer_t get_severity(std::string const & name)
461 : {
462 9 : auto_add_severities();
463 9 : return get_private_logger()->get_severity(name);
464 : }
465 :
466 :
467 2 : severity::pointer_t get_severity(message const & msg, std::string const & name)
468 : {
469 2 : auto_add_severities();
470 2 : return get_private_logger(msg)->get_severity(name);
471 : }
472 :
473 :
474 4 : severity::pointer_t get_severity(severity_t sev)
475 : {
476 4 : auto_add_severities();
477 4 : return get_private_logger()->get_severity(sev);
478 : }
479 :
480 :
481 12 : severity::pointer_t get_severity(message const & msg, severity_t sev)
482 : {
483 12 : auto_add_severities();
484 12 : return get_private_logger(msg)->get_severity(sev);
485 : }
486 :
487 :
488 :
489 : } // snaplogger namespace
490 :
491 :
492 1 : snaplogger::severity::pointer_t operator ""_sev (char const * name, unsigned long size)
493 : {
494 1 : return snaplogger::get_severity(std::string(name, size));
495 6 : }
496 :
497 :
498 : // vim: ts=4 sw=4 et
|