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