Fawkes API Fawkes Development Version
mongodb_log_logger_thread.cpp
1
2/***************************************************************************
3 * mongodb_logger_thread.cpp - MongoDB logger thread
4 *
5 * Created: Tue Dec 07 22:59:47 2010
6 * Copyright 2006-2017 Tim Niemueller [www.niemueller.de]
7 ****************************************************************************/
8
9/* This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Library General Public License for more details.
18 *
19 * Read the full text in the LICENSE.GPL file in the doc directory.
20 */
21
22#include "mongodb_log_logger_thread.h"
23
24#include <core/threading/mutex.h>
25#include <core/threading/mutex_locker.h>
26
27#include <bsoncxx/builder/basic/document.hpp>
28#include <mongocxx/client.hpp>
29#include <mongocxx/exception/operation_exception.hpp>
30
31using namespace mongocxx;
32using namespace fawkes;
33
34/** @class MongoLogLoggerThread "mongodb_log_logger_thread.h"
35 * Thread that provides a logger writing to MongoDB.
36 * This thread provides a logger, which writes log information to a
37 * MongoDB collection.
38 * @author Tim Niemueller
39 */
40
41/** Constructor. */
43: Thread("MongoLogLoggerThread", Thread::OPMODE_WAITFORWAKEUP),
44 LoggerAspect(this),
45 MongoDBAspect("default")
46{
47 mutex_ = new Mutex();
48}
49
50/** Destructor. */
52{
53 delete mutex_;
54}
55
56void
58{
59 database_ = config->get_string_or_default("/plugins/mongodb/logger/database", "fawkes");
60 collection_ = config->get_string_or_default("/plugins/mongodb/logger/collection", "msglog");
61}
62
63void
65{
66}
67
68void
70{
71}
72
73void
74MongoLogLoggerThread::insert_message(LogLevel ll,
75 const char *component,
76 const char *format,
77 va_list va)
78{
79 if (log_level <= ll) {
80 MutexLocker lock(mutex_);
81 bsoncxx::types::b_date nowd{std::chrono::high_resolution_clock::now()};
82
83 char *msg;
84 if (vasprintf(&msg, format, va) == -1) {
85 // Cannot do anything useful, drop log message
86 return;
87 }
88
89 using namespace bsoncxx::builder;
90 basic::document b;
91 switch (ll) {
92 case LL_DEBUG: b.append(basic::kvp("level", "DEBUG")); break;
93 case LL_INFO: b.append(basic::kvp("level", "INFO")); break;
94 case LL_WARN: b.append(basic::kvp("level", "WARN")); break;
95 case LL_ERROR: b.append(basic::kvp("level", "ERROR")); break;
96 default: b.append(basic::kvp("level", "UNKN")); break;
97 }
98 b.append(basic::kvp("component", component));
99 b.append(basic::kvp("time", nowd));
100 b.append(basic::kvp("message", msg));
101
102 free(msg);
103
104 try {
105 mongodb_client->database(database_)[collection_].insert_one(b.view());
106 } catch (operation_exception &e) {
107 } // ignored
108 }
109}
110
111void
112MongoLogLoggerThread::insert_message(LogLevel ll, const char *component, Exception &e)
113{
114 if (log_level <= ll) {
115 MutexLocker lock(mutex_);
116 bsoncxx::types::b_date nowd{std::chrono::high_resolution_clock::now()};
117
118 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
119 using namespace bsoncxx::builder;
120 basic::document b;
121 switch (ll) {
122 case LL_DEBUG: b.append(basic::kvp("level", "DEBUG")); break;
123 case LL_INFO: b.append(basic::kvp("level", "INFO")); break;
124 case LL_WARN: b.append(basic::kvp("level", "WARN")); break;
125 case LL_ERROR: b.append(basic::kvp("level", "ERROR")); break;
126 default: b.append(basic::kvp("level", "UNKN")); break;
127 }
128 b.append(basic::kvp("component", component));
129 b.append(basic::kvp("time", nowd));
130 b.append(basic::kvp("message", std::string("[EXCEPTION] ") + *i));
131 try {
132 mongodb_client->database(database_)[collection_].insert_one(b.view());
133 } catch (operation_exception &e) {
134 } // ignored
135 }
136 }
137}
138
139void
140MongoLogLoggerThread::vlog_debug(const char *component, const char *format, va_list va)
141{
142 insert_message(LL_DEBUG, component, format, va);
143}
144
145void
146MongoLogLoggerThread::vlog_info(const char *component, const char *format, va_list va)
147{
148 insert_message(LL_INFO, component, format, va);
149}
150
151void
152MongoLogLoggerThread::vlog_warn(const char *component, const char *format, va_list va)
153{
154 insert_message(LL_WARN, component, format, va);
155}
156
157void
158MongoLogLoggerThread::vlog_error(const char *component, const char *format, va_list va)
159{
160 insert_message(LL_ERROR, component, format, va);
161}
162
163void
164MongoLogLoggerThread::log_debug(const char *component, const char *format, ...)
165{
166 va_list arg;
167 va_start(arg, format);
168 insert_message(LL_DEBUG, component, format, arg);
169 va_end(arg);
170}
171
172void
173MongoLogLoggerThread::log_info(const char *component, const char *format, ...)
174{
175 va_list arg;
176 va_start(arg, format);
177 insert_message(LL_INFO, component, format, arg);
178 va_end(arg);
179}
180
181void
182MongoLogLoggerThread::log_warn(const char *component, const char *format, ...)
183{
184 va_list arg;
185 va_start(arg, format);
186 insert_message(LL_WARN, component, format, arg);
187 va_end(arg);
188}
189
190void
191MongoLogLoggerThread::log_error(const char *component, const char *format, ...)
192{
193 va_list arg;
194 va_start(arg, format);
195 insert_message(LL_ERROR, component, format, arg);
196 va_end(arg);
197}
198
199void
201{
202 insert_message(LL_DEBUG, component, e);
203}
204
205void
207{
208 insert_message(LL_INFO, component, e);
209}
210
211void
213{
214 insert_message(LL_WARN, component, e);
215}
216
217void
219{
220 insert_message(LL_ERROR, component, e);
221}
222
223void
224MongoLogLoggerThread::tlog_insert_message(LogLevel ll,
225 struct timeval *t,
226 const char * component,
227 const char * format,
228 va_list va)
229{
230 if (log_level <= ll) {
231 MutexLocker lock(mutex_);
232 char * msg;
233 if (vasprintf(&msg, format, va) == -1) {
234 return;
235 }
236
237 bsoncxx::types::b_date nowd{
238 std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>{
239 std::chrono::milliseconds{t->tv_sec * 1000 + t->tv_usec / 1000}}};
240
241 using namespace bsoncxx::builder;
242 basic::document b;
243 switch (ll) {
244 case LL_DEBUG: b.append(basic::kvp("level", "DEBUG")); break;
245 case LL_INFO: b.append(basic::kvp("level", "INFO")); break;
246 case LL_WARN: b.append(basic::kvp("level", "WARN")); break;
247 case LL_ERROR: b.append(basic::kvp("level", "ERROR")); break;
248 default: b.append(basic::kvp("level", "UNKN")); break;
249 }
250 b.append(basic::kvp("component", component));
251 b.append(basic::kvp("time", nowd));
252 b.append(basic::kvp("message", msg));
253 try {
254 mongodb_client->database(database_)[collection_].insert_one(b.view());
255 } catch (operation_exception &e) {
256 } // ignored
257
258 free(msg);
259
260 mutex_->unlock();
261 }
262}
263
264void
265MongoLogLoggerThread::tlog_insert_message(LogLevel ll,
266 struct timeval *t,
267 const char * component,
268 Exception & e)
269{
270 if (log_level <= ll) {
271 MutexLocker lock(mutex_);
272 bsoncxx::types::b_date nowd{
273 std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>{
274 std::chrono::milliseconds{t->tv_sec * 1000 + t->tv_usec / 1000}}};
275 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
276 using namespace bsoncxx::builder;
277 basic::document b;
278 switch (ll) {
279 case LL_DEBUG: b.append(basic::kvp("level", "DEBUG")); break;
280 case LL_INFO: b.append(basic::kvp("level", "INFO")); break;
281 case LL_WARN: b.append(basic::kvp("level", "WARN")); break;
282 case LL_ERROR: b.append(basic::kvp("level", "ERROR")); break;
283 default: b.append(basic::kvp("level", "UNKN")); break;
284 }
285 b.append(basic::kvp("component", component));
286 b.append(basic::kvp("time", nowd));
287 b.append(basic::kvp("message", std::string("[EXCEPTION] ") + *i));
288 try {
289 mongodb_client->database(database_)[collection_].insert_one(b.view());
290 } catch (operation_exception &e) {
291 } // ignored
292 }
293 }
294}
295
296void
297MongoLogLoggerThread::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
298{
299 va_list arg;
300 va_start(arg, format);
301 tlog_insert_message(LL_DEBUG, t, component, format, arg);
302 va_end(arg);
303}
304
305void
306MongoLogLoggerThread::tlog_info(struct timeval *t, const char *component, const char *format, ...)
307{
308 va_list arg;
309 va_start(arg, format);
310 tlog_insert_message(LL_INFO, t, component, format, arg);
311 va_end(arg);
312}
313
314void
315MongoLogLoggerThread::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
316{
317 va_list arg;
318 va_start(arg, format);
319 tlog_insert_message(LL_WARN, t, component, format, arg);
320 va_end(arg);
321}
322
323void
324MongoLogLoggerThread::tlog_error(struct timeval *t, const char *component, const char *format, ...)
325{
326 va_list arg;
327 va_start(arg, format);
328 tlog_insert_message(LL_ERROR, t, component, format, arg);
329 va_end(arg);
330}
331
332void
333MongoLogLoggerThread::tlog_debug(struct timeval *t, const char *component, Exception &e)
334{
335 tlog_insert_message(LL_DEBUG, t, component, e);
336}
337
338void
339MongoLogLoggerThread::tlog_info(struct timeval *t, const char *component, Exception &e)
340{
341 tlog_insert_message(LL_INFO, t, component, e);
342}
343
344void
345MongoLogLoggerThread::tlog_warn(struct timeval *t, const char *component, Exception &e)
346{
347 tlog_insert_message(LL_WARN, t, component, e);
348}
349
350void
351MongoLogLoggerThread::tlog_error(struct timeval *t, const char *component, Exception &e)
352{
353 tlog_insert_message(LL_ERROR, t, component, e);
354}
355
356void
358 const char * component,
359 const char * format,
360 va_list va)
361{
362 tlog_insert_message(LL_DEBUG, t, component, format, va);
363}
364
365void
367 const char * component,
368 const char * format,
369 va_list va)
370{
371 tlog_insert_message(LL_INFO, t, component, format, va);
372}
373
374void
376 const char * component,
377 const char * format,
378 va_list va)
379{
380 tlog_insert_message(LL_WARN, t, component, format, va);
381}
382
383void
385 const char * component,
386 const char * format,
387 va_list va)
388{
389 tlog_insert_message(LL_ERROR, t, component, format, va);
390}
virtual void vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
Log informational message for specific time.
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
virtual void vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
Log warning message for specific time.
virtual void log_info(const char *component, const char *format,...)
Log informational message.
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
virtual void init()
Initialize the thread.
virtual void loop()
Code to execute in the thread.
virtual void finalize()
Finalize the thread.
virtual ~MongoLogLoggerThread()
Destructor.
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Log warning message for specific time.
virtual void vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
Log error message for specific time.
virtual void log_error(const char *component, const char *format,...)
Log error message.
virtual void vlog_error(const char *component, const char *format, va_list va)
Log error message.
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Log informational message for specific time.
virtual void vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
Log debug message for specific time.
virtual void vlog_debug(const char *component, const char *format, va_list va)
Log debug message.
virtual void tlog_error(struct timeval *t, const char *component, const char *format,...)
Log error message for specific time.
virtual void vlog_info(const char *component, const char *format, va_list va)
Log informational message.
virtual void tlog_debug(struct timeval *t, const char *component, const char *format,...)
Log debug message for specific time.
virtual void vlog_warn(const char *component, const char *format, va_list va)
Log warning message.
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:41
virtual std::string get_string_or_default(const char *path, const std::string &default_val)
Get value from configuration which is of type string, or the given default if the path does not exist...
Definition: config.cpp:736
Message iterator for exceptions.
Definition: exception.h:73
Base class for exceptions in Fawkes.
Definition: exception.h:36
iterator end() noexcept
Get end iterator for messages.
Definition: exception.cpp:692
iterator begin() noexcept
Get iterator for messages.
Definition: exception.cpp:676
Thread aspect that allows to provide a logger to Fawkes.
Definition: logger.h:34
@ LL_INFO
informational output about normal procedures
Definition: logger.h:53
@ LL_WARN
warning, should be investigated but software still functions, an example is that something was reques...
Definition: logger.h:54
@ LL_ERROR
error, may be recoverable (software still running) or not (software has to terminate).
Definition: logger.h:57
@ LL_DEBUG
debug output, relevant only when tracking down problems
Definition: logger.h:52
LogLevel log_level
Minimum log level.
Definition: logger.h:126
Thread aspect to access MongoDB.
Definition: mongodb.h:39
mongocxx::client * mongodb_client
MongoDB client to use to interact with the database.
Definition: mongodb.h:54
Mutex locking helper.
Definition: mutex_locker.h:34
Mutex mutual exclusion lock.
Definition: mutex.h:33
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
Thread class encapsulation of pthreads.
Definition: thread.h:46
Fawkes library namespace.