Line data Source code
1 : // Copyright (c) 2013-2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snaplogger
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : #pragma once
20 :
21 : /** \file
22 : * \brief Variables are used to dynamically add parameters to log messages.
23 : *
24 : * This file declares the base variable class.
25 : *
26 : * The format defines \em functions which are written as in
27 : * `${function-name}`.
28 : *
29 : * Parameters can be passed to these functions by adding `:<param>`
30 : * to those definitions. These are named parameters and their default
31 : * value is "present" or not. A specific value can be assignd using
32 : * the equal sign as in `:param=<value>`.
33 : *
34 : * For example, the date function can be called as follow:
35 : *
36 : * \code
37 : * ${date:year:align=right:exact_width=2}
38 : * \endcode
39 : *
40 : * The `year` parameter is specific to the `date` function. The other
41 : * parameters are available whatever the function. This variable asks
42 : * to truncate the year to 2 character right aligned (i.e. "18" in
43 : * "2018".)
44 : *
45 : * In C++, this would look something like:
46 : *
47 : * \code
48 : * date(FLAG_YEAR, ALIGN_RIGHT, 2);
49 : * \endcode
50 : */
51 :
52 :
53 : // self
54 : //
55 : #include "snaplogger/message.h"
56 :
57 :
58 : // libutf8 lib
59 : //
60 : #include <libutf8/libutf8.h>
61 :
62 :
63 : // C++
64 : //
65 : #include <vector>
66 :
67 :
68 :
69 : namespace snaplogger
70 : {
71 :
72 : // variables
73 : //
74 : #define SNAPLOGGER_VAR_BASENAME "basename"
75 : #define SNAPLOGGER_VAR_DATE "date"
76 : #define SNAPLOGGER_VAR_DIAGNOSTIC "diagnostic"
77 : #define SNAPLOGGER_VAR_DOMAINNAME "domainname"
78 : #define SNAPLOGGER_VAR_ENV "env"
79 : #define SNAPLOGGER_VAR_FILENAME "filename"
80 : #define SNAPLOGGER_VAR_FUNCTION "function"
81 : #define SNAPLOGGER_VAR_GID "gid"
82 : #define SNAPLOGGER_VAR_GROUPNAME "groupname"
83 : #define SNAPLOGGER_VAR_HOSTBYNAME "hostbyname"
84 : #define SNAPLOGGER_VAR_HOSTNAME "hostname"
85 : #define SNAPLOGGER_VAR_LINE "line"
86 : #define SNAPLOGGER_VAR_LOCALE "locale"
87 : #define SNAPLOGGER_VAR_MESSAGE "message"
88 : #define SNAPLOGGER_VAR_PATH "path"
89 : #define SNAPLOGGER_VAR_PID "pid"
90 : #define SNAPLOGGER_VAR_PROGNAME "progname"
91 : #define SNAPLOGGER_VAR_SEVERITY "severity"
92 : #define SNAPLOGGER_VAR_TID "tid"
93 : #define SNAPLOGGER_VAR_TIME "time"
94 : #define SNAPLOGGER_VAR_THREADNAME "threadname"
95 : #define SNAPLOGGER_VAR_UID "uid"
96 : #define SNAPLOGGER_VAR_USERNAME "username"
97 : #define SNAPLOGGER_VAR_VERSION "version"
98 :
99 : // functions
100 : //
101 : #define SNAPLOGGER_VAR_ALIGN "align"
102 : #define SNAPLOGGER_VAR_APPEND "append"
103 : #define SNAPLOGGER_VAR_CAPS "caps"
104 : #define SNAPLOGGER_VAR_ESCAPE "escape"
105 : #define SNAPLOGGER_VAR_EXACT_WIDTH "exact_width"
106 : #define SNAPLOGGER_VAR_LOWER "lower"
107 : #define SNAPLOGGER_VAR_MAX_WIDTH "max_width"
108 : #define SNAPLOGGER_VAR_MIN_WIDTH "min_width"
109 : #define SNAPLOGGER_VAR_PADDING "padding"
110 : #define SNAPLOGGER_VAR_PREPEND "prepend"
111 : #define SNAPLOGGER_VAR_UPPER "upper"
112 :
113 : // parameters
114 : //
115 : #define SNAPLOGGER_VAR_ALIGN_LEFT "left"
116 : #define SNAPLOGGER_VAR_ALIGN_RIGHT "right"
117 :
118 :
119 :
120 193 : class param
121 : {
122 : public:
123 : typedef std::shared_ptr<param> pointer_t;
124 : typedef std::vector<pointer_t> vector_t;
125 :
126 : enum class type_t
127 : {
128 : TYPE_STRING,
129 : TYPE_INTEGER
130 : };
131 :
132 : param(std::string const & name);
133 :
134 : std::string const & get_name() const;
135 :
136 : type_t get_type() const;
137 :
138 : std::string get_value() const;
139 : void set_value(std::string const & value);
140 :
141 : int64_t get_integer() const;
142 : void set_integer(std::int64_t integer);
143 :
144 : private:
145 : std::string const f_name;
146 : type_t f_type = type_t::TYPE_STRING;
147 : std::string f_value = std::string();
148 : std::int64_t f_integer = 0;
149 : };
150 :
151 :
152 : template<typename CharT, typename Traits>
153 : inline std::basic_ostream<CharT, Traits> &
154 : operator << (std::basic_ostream<CharT, Traits> & os, param::pointer_t p)
155 : {
156 : if(p != nullptr)
157 : {
158 : os << p->get_name();
159 : }
160 : else
161 : {
162 : os << "(nullptr)";
163 : }
164 : return os;
165 : }
166 :
167 :
168 : template<typename CharT, typename Traits>
169 : inline std::basic_ostream<CharT, Traits> &
170 : operator << (std::basic_ostream<CharT, Traits> & os, param::type_t t)
171 : {
172 : switch(t)
173 : {
174 : case param::type_t::TYPE_STRING:
175 : os << "string";
176 : break;
177 :
178 : case param::type_t::TYPE_INTEGER:
179 : os << "integer";
180 : break;
181 :
182 : default:
183 : os << "(unknown)";
184 : break;
185 :
186 : }
187 : return os;
188 : }
189 :
190 :
191 :
192 :
193 :
194 217 : class variable
195 : {
196 : public:
197 : typedef std::shared_ptr<variable> pointer_t;
198 : typedef std::vector<pointer_t> vector_t;
199 :
200 : virtual ~variable();
201 :
202 : virtual bool ignore_on_no_repeat() const = 0;
203 : void add_param(param::pointer_t p);
204 : param::vector_t get_params() const;
205 : std::string get_value(message const & msg) const;
206 :
207 : protected:
208 : virtual void process_value(message const & msg, std::string & value) const;
209 :
210 : private:
211 : param::vector_t f_params = param::vector_t();
212 : };
213 :
214 :
215 : class variable_factory
216 : {
217 : public:
218 : typedef std::shared_ptr<variable_factory> pointer_t;
219 :
220 : variable_factory(std::string const & type);
221 : virtual ~variable_factory();
222 :
223 : std::string const & get_type() const;
224 : virtual variable::pointer_t create_variable() = 0;
225 :
226 : private:
227 : std::string const f_type;
228 : };
229 :
230 :
231 : void register_variable_factory(variable_factory::pointer_t factory);
232 : variable::pointer_t get_variable(std::string const & type);
233 :
234 :
235 : #define DEFINE_LOGGER_VARIABLE_IMPL_(type, do_ignore_on_no_repeat) \
236 : class type##_variable \
237 : : public ::snaplogger::variable \
238 : { \
239 : protected: \
240 : virtual bool ignore_on_no_repeat() const override \
241 : { return do_ignore_on_no_repeat; } \
242 : virtual void process_value( \
243 : ::snaplogger::message const & msg \
244 : , std::string & value) const override; \
245 : }; \
246 : class type##_variable_factory final \
247 : : public ::snaplogger::variable_factory \
248 : { \
249 : public: \
250 : type##_variable_factory() \
251 : : variable_factory(#type) \
252 : {} \
253 : virtual ::snaplogger::variable::pointer_t \
254 : create_variable() override final \
255 : { \
256 : return std::make_shared<type##_variable>(); \
257 : } \
258 : }; \
259 : int __attribute__((unused)) \
260 : g_##type##_variable_factory = []() { \
261 : ::snaplogger::register_variable_factory \
262 : (std::make_shared< \
263 : type##_variable_factory>()); \
264 : return 0; \
265 : } (); \
266 : void type##_variable::process_value( \
267 : ::snaplogger::message const & msg \
268 : , std::string & value) const
269 :
270 :
271 : #define DEFINE_LOGGER_VARIABLE(type) \
272 : DEFINE_LOGGER_VARIABLE_IMPL_(type, false)
273 :
274 : #define DEFINE_LOGGER_VARIABLE_IGNORED_ON_NO_REPEAT(type) \
275 : DEFINE_LOGGER_VARIABLE_IMPL_(type, true)
276 :
277 :
278 :
279 :
280 :
281 :
282 90932 : class function_data
283 : {
284 : public:
285 : void set_value(std::string value);
286 : void set_value(std::u32string value);
287 : std::u32string & get_value();
288 : void set_param(std::string const & name, std::string const & value);
289 : void set_param(std::string const & name, std::u32string const & value);
290 : std::u32string get_param(std::string const & name, std::u32string const & default_value);
291 :
292 : private:
293 : std::u32string f_value = std::u32string();
294 : u8u32string_map_t f_params = u8u32string_map_t();
295 : };
296 :
297 :
298 :
299 :
300 : class function
301 : {
302 : public:
303 : typedef std::shared_ptr<function> pointer_t;
304 :
305 : function(std::string const & function_name);
306 : virtual ~function();
307 :
308 : std::string const & get_name() const;
309 :
310 : virtual void apply(
311 : message const & msg
312 : , function_data & data
313 : , param::pointer_t const & p) = 0;
314 :
315 : private:
316 : std::string const f_name;
317 : };
318 :
319 :
320 : void register_function(function::pointer_t func);
321 :
322 :
323 : #define DECLARE_FUNCTION(name) \
324 : class name##_function : public function \
325 : { \
326 : public: \
327 : name##_function() : function(#name) {} \
328 : virtual void apply( \
329 : ::snaplogger::message const & msg \
330 : , ::snaplogger::function_data & d \
331 : , ::snaplogger::param::pointer_t const & p) override; \
332 : }; \
333 : int __attribute__((unused)) g_##name##_function = []() { \
334 : register_function(std::make_shared<name##_function>()); \
335 : return 0; \
336 : } (); \
337 : void name##_function::apply( \
338 : ::snaplogger::message const & msg \
339 : , ::snaplogger::function_data & d \
340 : , ::snaplogger::param::pointer_t const & p)
341 :
342 :
343 :
344 :
345 :
346 : } // snaplogger namespace
347 : // vim: ts=4 sw=4 et
|