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 Variables are used to dynamically add parameters to log messages.
24 : *
25 : * This file declares the base variable class.
26 : *
27 : * The format defines \em functions which are written as in
28 : * `${function-name}`.
29 : *
30 : * Parameters can be passed to these functions by adding `:<param>`
31 : * to those definitions. These are named parameters and their default
32 : * value is "present" or not. A specific value can be assignd using
33 : * the equal sign as in `:param=<value>`.
34 : *
35 : * For example, the date function can be called as follow:
36 : *
37 : * \code
38 : * ${date:year:align=right:exact_width=2}
39 : * \endcode
40 : *
41 : * The `year` parameter is specific to the `date` function. The other
42 : * parameters are available whatever the function. This variable asks
43 : * to truncate the year to 2 character right aligned (i.e. "18" in
44 : * "2018".)
45 : *
46 : * In C, this would look something like:
47 : *
48 : * \code
49 : * date(FLAG_YEAR, ALIGN_RIGHT, 2);
50 : * \endcode
51 : */
52 :
53 :
54 : // self
55 : //
56 : #include "snaplogger/variable.h"
57 :
58 : #include "snaplogger/exception.h"
59 : #include "snaplogger/guard.h"
60 : #include "snaplogger/private_logger.h"
61 :
62 :
63 : // libutf8 lib
64 : //
65 : #include <libutf8/libutf8.h>
66 :
67 :
68 : // C++ lib
69 : //
70 : #include <iostream>
71 : #include <queue>
72 :
73 :
74 : // last include
75 : //
76 : #include <snapdev/poison.h>
77 :
78 :
79 :
80 : namespace snaplogger
81 : {
82 :
83 :
84 :
85 : namespace
86 : {
87 :
88 :
89 :
90 :
91 :
92 130 : DEFINE_LOGGER_VARIABLE(direct)
93 : {
94 23 : snap::NOTUSED(msg);
95 :
96 : // apply all our parameters as is
97 : //
98 46 : auto const & params(get_params());
99 46 : for(auto p : params)
100 : {
101 23 : value += p->get_value();
102 : }
103 :
104 : // do NOT apply parameters further, the user has no access to those
105 : // anyway; this is the direct text we find in between variables
106 : //
107 : //variable::process_value(msg, value);
108 23 : }
109 :
110 :
111 :
112 : }
113 : // no name namespace
114 :
115 :
116 :
117 : //////////////////////////////
118 : // PARAM
119 : //
120 :
121 54 : param::param(std::string const & name)
122 55 : : f_name(name)
123 : {
124 54 : if(f_name.empty())
125 : {
126 1 : throw invalid_parameter("a parameter must have a non-empty name.");
127 : }
128 53 : }
129 :
130 :
131 27 : std::string const & param::get_name() const
132 : {
133 27 : return f_name;
134 : }
135 :
136 :
137 4 : param::type_t param::get_type() const
138 : {
139 4 : return f_type;
140 : }
141 :
142 :
143 34 : std::string param::get_value() const
144 : {
145 34 : if(f_type != type_t::TYPE_STRING)
146 : {
147 : // TBD: we may instead want to return the integer as a string
148 : //
149 : throw invalid_parameter(
150 : "the ${...:"
151 2 : + f_name
152 3 : + "=<value>} parameter must be a valid string (not an integer).");
153 : }
154 33 : return f_value;
155 : }
156 :
157 :
158 41 : void param::set_value(std::string const & value)
159 : {
160 41 : f_value = value;
161 41 : f_type = type_t::TYPE_STRING;
162 41 : }
163 :
164 :
165 5 : int64_t param::get_integer() const
166 : {
167 5 : if(f_type != type_t::TYPE_INTEGER)
168 : {
169 : // TBD: we may want to check whether the string represents a valid
170 : // integer first and return that if so
171 : //
172 : throw invalid_parameter(
173 : "the ${...:"
174 2 : + f_name
175 3 : + "=<value>} parameter must be a valid integer.");
176 : }
177 4 : return f_integer;
178 : }
179 :
180 :
181 7 : void param::set_integer(std::int64_t integer)
182 : {
183 7 : f_integer = integer;
184 7 : f_type = type_t::TYPE_INTEGER;
185 7 : }
186 :
187 :
188 :
189 :
190 :
191 : //////////////////////////////
192 : // VARIABLE
193 : //
194 :
195 77 : variable::~variable()
196 : {
197 77 : }
198 :
199 :
200 53 : void variable::add_param(param::pointer_t p)
201 : {
202 106 : guard g;
203 :
204 53 : f_params.push_back(p);
205 53 : }
206 :
207 :
208 33 : param::vector_t variable::get_params() const
209 : {
210 66 : guard g;
211 :
212 66 : return f_params;
213 : }
214 :
215 :
216 45587 : std::string variable::get_value(message const & msg) const
217 : {
218 91174 : guard g;
219 :
220 45587 : std::string value;
221 45587 : process_value(msg, value);
222 91170 : return value;
223 : }
224 :
225 :
226 45563 : void variable::process_value(message const & msg, std::string & value) const
227 : {
228 91126 : auto l(get_private_logger(msg));
229 :
230 : {
231 91126 : guard g;
232 :
233 45563 : if(!l->has_functions())
234 : {
235 : // no functions available, we're done
236 : return; // LCOV_EXCL_LINE
237 : }
238 : }
239 :
240 91126 : function_data d;
241 45563 : d.set_value(value);
242 :
243 45581 : for(auto p : f_params)
244 : {
245 18 : std::string const & name(p->get_name());
246 36 : auto func(l->get_function(name));
247 18 : if(func != nullptr)
248 : {
249 14 : func->apply(msg, d, p);
250 : }
251 : // else -- ignore missing functions
252 : }
253 :
254 45561 : value = libutf8::to_u8string(d.get_value());
255 : }
256 :
257 :
258 :
259 :
260 :
261 :
262 :
263 :
264 :
265 :
266 :
267 : //////////////////////////////
268 : // VARIABLE FACTORY
269 : //
270 :
271 56 : variable_factory::variable_factory(std::string const & type)
272 56 : : f_type(type)
273 : {
274 56 : }
275 :
276 :
277 56 : variable_factory::~variable_factory()
278 : {
279 56 : }
280 :
281 :
282 112 : std::string const & variable_factory::get_type() const
283 : {
284 112 : return f_type;
285 : }
286 :
287 :
288 :
289 :
290 56 : void register_variable_factory(variable_factory::pointer_t factory)
291 : {
292 56 : get_private_logger()->register_variable_factory(factory);
293 56 : }
294 :
295 :
296 :
297 77 : variable::pointer_t get_variable(std::string const & type)
298 : {
299 77 : return get_private_logger()->get_variable(type);
300 : }
301 :
302 :
303 :
304 :
305 :
306 :
307 :
308 : //////////////////////////////
309 : // FUNCTION DATA
310 : //
311 :
312 45563 : void function_data::set_value(std::string value)
313 : {
314 45563 : f_value = libutf8::to_u32string(value);
315 45563 : }
316 :
317 4 : void function_data::set_value(std::u32string value)
318 : {
319 4 : f_value = value;
320 4 : }
321 :
322 45569 : std::u32string & function_data::get_value()
323 : {
324 45569 : return f_value;
325 : }
326 :
327 3 : void function_data::set_param(std::string const & name, std::string const & value)
328 : {
329 3 : f_params[name] = libutf8::to_u32string(value);
330 3 : }
331 :
332 4 : void function_data::set_param(std::string const & name, std::u32string const & value)
333 : {
334 4 : f_params[name] = value;
335 4 : }
336 :
337 5 : std::u32string function_data::get_param(std::string const & name, std::u32string const & default_value)
338 : {
339 5 : auto it(f_params.find(name));
340 5 : if(it == f_params.end())
341 : {
342 1 : return default_value;
343 : }
344 4 : return it->second;
345 : }
346 :
347 :
348 :
349 :
350 :
351 : //////////////////////////////
352 : // FUNCTION
353 : //
354 :
355 22 : function::function(std::string const & function_name)
356 22 : : f_name(function_name)
357 : {
358 22 : }
359 :
360 :
361 22 : function::~function()
362 : {
363 22 : }
364 :
365 :
366 44 : std::string const & function::get_name() const
367 : {
368 44 : return f_name;
369 : }
370 :
371 :
372 :
373 22 : void register_function(function::pointer_t func)
374 : {
375 44 : guard g;
376 :
377 22 : get_private_logger()->register_function(func);
378 22 : }
379 :
380 :
381 :
382 :
383 6 : } // snaplogger namespace
384 : // vim: ts=4 sw=4 et
|