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