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