Fawkes API Fawkes Development Version
mongorrd_thread.cpp
1
2/***************************************************************************
3 * mongorrd_thread.cpp - MongoDB RRD Thread
4 *
5 * Created: Sat Jan 15 18:42:39 2011
6 * Copyright 2006-2011 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library General Public License for more details.
19 *
20 * Read the full text in the LICENSE.GPL file in the doc directory.
21 */
22
23#include "mongorrd_thread.h"
24
25#include "utils.h"
26
27#include <utils/time/wait.h>
28
29// from MongoDB
30#include <bsoncxx/builder/basic/document.hpp>
31#include <bsoncxx/json.hpp>
32#include <mongocxx/client.hpp>
33#include <mongocxx/exception/exception.hpp>
34
35using namespace mongocxx;
36using namespace fawkes;
37
38#define DB_CONF_PREFIX "/plugins/mongorrd/databases/"
39
40/** @class MongoRRDThread "mongorrd_thread.h"
41 * MongoDB RRD Thread.
42 * This thread queries performance data from MongoDB every 10 seconds and
43 * writes it to RRD databases.
44 *
45 * @author Tim Niemueller
46 */
47
48/** Constructor. */
50: Thread("MongoRRDThread", Thread::OPMODE_CONTINUOUS),
51 MongoDBAspect("default"),
52 ConfigurationChangeHandler(DB_CONF_PREFIX)
53{
55}
56
57/** Destructor. */
59{
60}
61
62void
64{
65 timewait_ = new TimeWait(clock, 10 * 1000000);
66
67 opcounters_graph_ = NULL;
68 memory_graph_ = NULL;
69 indexes_graph_ = NULL;
70
71 std::vector<RRDDataSource> rrds;
72 rrds.push_back(RRDDataSource("insert", RRDDataSource::COUNTER));
73 rrds.push_back(RRDDataSource("query", RRDDataSource::COUNTER));
74 rrds.push_back(RRDDataSource("update", RRDDataSource::COUNTER));
75 rrds.push_back(RRDDataSource("delete", RRDDataSource::COUNTER));
76 rrds.push_back(RRDDataSource("getmore", RRDDataSource::COUNTER));
77 rrds.push_back(RRDDataSource("command", RRDDataSource::COUNTER));
78 opcounters_rrd_ = new RRDDefinition("opcounters", rrds);
79
80 rrds.clear();
81 rrds.push_back(RRDDataSource("resident", RRDDataSource::GAUGE));
82 rrds.push_back(RRDDataSource("virtual", RRDDataSource::GAUGE));
83 rrds.push_back(RRDDataSource("mapped", RRDDataSource::GAUGE));
84 memory_rrd_ = new RRDDefinition("memory", rrds);
85
86 rrds.clear();
87 rrds.push_back(RRDDataSource("accesses", RRDDataSource::COUNTER));
88 rrds.push_back(RRDDataSource("hits", RRDDataSource::COUNTER));
89 rrds.push_back(RRDDataSource("misses", RRDDataSource::COUNTER));
90 rrds.push_back(RRDDataSource("resets", RRDDataSource::COUNTER));
91 indexes_rrd_ = new RRDDefinition("indexes", rrds);
92
93 rrds.clear();
94 rrds.push_back(RRDDataSource("locktime", RRDDataSource::COUNTER));
95 locks_rrd_ = new RRDDefinition("locks", rrds);
96
97 try {
98 rrd_manager->add_rrd(opcounters_rrd_);
99 rrd_manager->add_rrd(memory_rrd_);
100 rrd_manager->add_rrd(indexes_rrd_);
101 rrd_manager->add_rrd(locks_rrd_);
102 } catch (Exception &e) {
103 finalize();
104 throw;
105 }
106
107 std::vector<RRDGraphDataDefinition> defs;
108 std::vector<RRDGraphElement *> els;
109
110 defs.push_back(RRDGraphDataDefinition("insert", RRDArchive::AVERAGE, opcounters_rrd_));
111 defs.push_back(RRDGraphDataDefinition("query", RRDArchive::AVERAGE, opcounters_rrd_));
112 defs.push_back(RRDGraphDataDefinition("update", RRDArchive::AVERAGE, opcounters_rrd_));
113 defs.push_back(RRDGraphDataDefinition("delete", RRDArchive::AVERAGE, opcounters_rrd_));
114 defs.push_back(RRDGraphDataDefinition("getmore", RRDArchive::AVERAGE, opcounters_rrd_));
115 defs.push_back(RRDGraphDataDefinition("command", RRDArchive::AVERAGE, opcounters_rrd_));
116
117 els.push_back(new RRDGraphLine("insert", 1, "FF7200", "Inserts"));
118 els.push_back(new RRDGraphGPrint("insert", RRDArchive::LAST, " Current\\:%8.2lf %s"));
119 els.push_back(new RRDGraphGPrint("insert", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
120 els.push_back(new RRDGraphGPrint("insert", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
121
122 els.push_back(new RRDGraphLine("query", 1, "503001", "Queries"));
123 els.push_back(new RRDGraphGPrint("query", RRDArchive::LAST, " Current\\:%8.2lf %s"));
124 els.push_back(new RRDGraphGPrint("query", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
125 els.push_back(new RRDGraphGPrint("query", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
126
127 els.push_back(new RRDGraphLine("update", 1, "EDAC00", "Updates"));
128 els.push_back(new RRDGraphGPrint("update", RRDArchive::LAST, " Current\\:%8.2lf %s"));
129 els.push_back(new RRDGraphGPrint("update", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
130 els.push_back(new RRDGraphGPrint("update", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
131
132 els.push_back(new RRDGraphLine("delete", 1, "506101", "Deletes"));
133 els.push_back(new RRDGraphGPrint("delete", RRDArchive::LAST, " Current\\:%8.2lf %s"));
134 els.push_back(new RRDGraphGPrint("delete", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
135 els.push_back(new RRDGraphGPrint("delete", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
136
137 els.push_back(new RRDGraphLine("getmore", 1, "0CCCCC", "Getmores"));
138 els.push_back(new RRDGraphGPrint("getmore", RRDArchive::LAST, "Current\\:%8.2lf %s"));
139 els.push_back(new RRDGraphGPrint("getmore", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
140 els.push_back(new RRDGraphGPrint("getmore", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
141
142 els.push_back(new RRDGraphLine("command", 1, "53CA05", "Commands"));
143 els.push_back(new RRDGraphGPrint("command", RRDArchive::LAST, "Current\\:%8.2lf %s"));
144 els.push_back(new RRDGraphGPrint("command", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
145 els.push_back(new RRDGraphGPrint("command", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
146
147 opcounters_graph_ = new RRDGraphDefinition(
148 "opcounters", opcounters_rrd_, "MongoDB Op Counters", "Ops/sec", defs, els);
149
150 defs.clear();
151 els.clear();
152 defs.push_back(
153 RRDGraphDataDefinition("rawresident", RRDArchive::AVERAGE, memory_rrd_, "resident"));
154 defs.push_back(RRDGraphDataDefinition("rawvirtual", RRDArchive::AVERAGE, memory_rrd_, "virtual"));
155 defs.push_back(RRDGraphDataDefinition("rawmapped", RRDArchive::AVERAGE, memory_rrd_, "mapped"));
156 defs.push_back(RRDGraphDataDefinition("resident", "rawresident,1048576,*"));
157 defs.push_back(RRDGraphDataDefinition("virtual", "rawvirtual,1048576,*"));
158 defs.push_back(RRDGraphDataDefinition("mapped", "rawmapped,1048576,*"));
159
160 els.push_back(new RRDGraphArea("virtual", "3B7AD9", "Virtual"));
161 els.push_back(new RRDGraphGPrint("virtual", RRDArchive::LAST, " Current\\:%8.2lf %s"));
162 els.push_back(new RRDGraphGPrint("virtual", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
163 els.push_back(new RRDGraphGPrint("virtual", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
164
165 els.push_back(new RRDGraphArea("mapped", "6FD1BF", "Mapped"));
166 els.push_back(new RRDGraphGPrint("mapped", RRDArchive::LAST, " Current\\:%8.2lf %s"));
167 els.push_back(new RRDGraphGPrint("mapped", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
168 els.push_back(new RRDGraphGPrint("mapped", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
169
170 els.push_back(new RRDGraphArea("resident", "0E6E5C", "Resident"));
171 els.push_back(new RRDGraphGPrint("resident", RRDArchive::LAST, "Current\\:%8.2lf %s"));
172 els.push_back(new RRDGraphGPrint("resident", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
173 els.push_back(new RRDGraphGPrint("resident", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
174
175 memory_graph_ =
176 new RRDGraphDefinition("memory", memory_rrd_, "MongoDB Memory Usage", "MB", defs, els);
177
178 defs.clear();
179 els.clear();
180 defs.push_back(RRDGraphDataDefinition("accesses", RRDArchive::AVERAGE, indexes_rrd_));
181 defs.push_back(RRDGraphDataDefinition("hits", RRDArchive::AVERAGE, indexes_rrd_));
182 defs.push_back(RRDGraphDataDefinition("misses", RRDArchive::AVERAGE, indexes_rrd_));
183 defs.push_back(RRDGraphDataDefinition("resets", RRDArchive::AVERAGE, indexes_rrd_));
184
185 els.push_back(new RRDGraphLine("accesses", 1, "FF7200", "Accesses"));
186 els.push_back(new RRDGraphGPrint("accesses", RRDArchive::LAST, "Current\\:%8.2lf %s"));
187 els.push_back(new RRDGraphGPrint("accesses", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
188 els.push_back(new RRDGraphGPrint("accesses", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
189
190 els.push_back(new RRDGraphLine("hits", 1, "503001", "Hits"));
191 els.push_back(new RRDGraphGPrint("hits", RRDArchive::LAST, " Current\\:%8.2lf %s"));
192 els.push_back(new RRDGraphGPrint("hits", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
193 els.push_back(new RRDGraphGPrint("hits", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
194
195 els.push_back(new RRDGraphLine("misses", 1, "EDAC00", "Misses"));
196 els.push_back(new RRDGraphGPrint("misses", RRDArchive::LAST, " Current\\:%8.2lf %s"));
197 els.push_back(new RRDGraphGPrint("misses", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
198 els.push_back(new RRDGraphGPrint("misses", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
199
200 els.push_back(new RRDGraphLine("resets", 1, "506101", "Resets"));
201 els.push_back(new RRDGraphGPrint("resets", RRDArchive::LAST, " Current\\:%8.2lf %s"));
202 els.push_back(new RRDGraphGPrint("resets", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
203 els.push_back(new RRDGraphGPrint("resets", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
204
205 indexes_graph_ =
206 new RRDGraphDefinition("indexes", indexes_rrd_, "MongoDB Indexes", "", defs, els);
207
208 try {
209 rrd_manager->add_graph(opcounters_graph_);
210 rrd_manager->add_graph(memory_graph_);
211 rrd_manager->add_graph(indexes_graph_);
212 } catch (Exception &e) {
213 finalize();
214 throw;
215 }
216
217 // Add DB Stats
218 std::string dbprefix = DB_CONF_PREFIX;
219
220 Configuration::ValueIterator *i = config->search(dbprefix.c_str());
221 while (i->next()) {
222 if (!i->is_string()) {
224 "Entry %s is not a string, but of type %s, "
225 "ignoring",
226 i->path(),
227 i->type());
228 continue;
229 }
230
231 std::string dbname = i->get_string();
232 if (dbname.find(".") != std::string::npos) {
233 logger->log_warn(name(), "Database name %s contains dot, ignoring", dbname.c_str());
234 continue;
235 }
236
237 try {
238 add_dbstats(i->path(), dbname);
239 } catch (Exception &e) {
240 finalize();
241 throw;
242 }
243 }
244
246}
247
248void
250{
252 delete timewait_;
253
254 rrd_manager->remove_rrd(opcounters_rrd_);
255 rrd_manager->remove_rrd(memory_rrd_);
256 rrd_manager->remove_rrd(indexes_rrd_);
257 rrd_manager->remove_rrd(locks_rrd_);
258
259 for (DbStatsMap::iterator i = dbstats_.begin(); i != dbstats_.end(); ++i) {
260 DbStatsInfo &info = i->second;
261 rrd_manager->remove_rrd(info.rrd);
262 delete info.graph1;
263 delete info.graph2;
264 delete info.graph3;
265 delete info.rrd;
266 }
267 dbstats_.clear();
268
269 delete opcounters_graph_;
270 delete memory_graph_;
271 delete indexes_graph_;
272
273 delete opcounters_rrd_;
274 delete memory_rrd_;
275 delete indexes_rrd_;
276 delete locks_rrd_;
277}
278
279void
280MongoRRDThread::add_dbstats(const char *path, std::string dbname)
281{
282 if (dbstats_.find(path) != dbstats_.end()) {
283 throw Exception("Database stats for config %s already monitored", path);
284 }
285
286 DbStatsInfo info;
287
288 std::vector<RRDDataSource> rrds;
289 rrds.push_back(RRDDataSource("collections", RRDDataSource::GAUGE));
290 rrds.push_back(RRDDataSource("objects", RRDDataSource::GAUGE));
291 rrds.push_back(RRDDataSource("avgObjSize", RRDDataSource::GAUGE));
292 rrds.push_back(RRDDataSource("dataSize", RRDDataSource::GAUGE));
293 rrds.push_back(RRDDataSource("storageSize", RRDDataSource::GAUGE));
294 rrds.push_back(RRDDataSource("numExtents", RRDDataSource::GAUGE));
295 rrds.push_back(RRDDataSource("indexes", RRDDataSource::GAUGE));
296 rrds.push_back(RRDDataSource("indexSize", RRDDataSource::GAUGE));
297 rrds.push_back(RRDDataSource("fileSize", RRDDataSource::GAUGE));
298
299 info.db_name = dbname;
300 info.rrd_name = std::string("dbstats_") + dbname;
301 info.rrd = new RRDDefinition(info.rrd_name.c_str(), rrds);
302
303 std::vector<RRDGraphDataDefinition> defs;
304 std::vector<RRDGraphElement *> els;
305
306 defs.push_back(RRDGraphDataDefinition("collections", RRDArchive::AVERAGE, info.rrd));
307 defs.push_back(RRDGraphDataDefinition("indexes", RRDArchive::AVERAGE, info.rrd));
308 defs.push_back(RRDGraphDataDefinition("numExtents", RRDArchive::AVERAGE, info.rrd));
309
310 els.push_back(new RRDGraphLine("collections", 1, "FF7200", "Collections"));
311 els.push_back(new RRDGraphGPrint("collections", RRDArchive::LAST, "Current\\:%8.2lf %s"));
312 els.push_back(new RRDGraphGPrint("collections", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
313 els.push_back(new RRDGraphGPrint("collections", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
314
315 els.push_back(new RRDGraphLine("indexes", 1, "EDAC00", "Indexes"));
316 els.push_back(new RRDGraphGPrint("indexes", RRDArchive::LAST, " Current\\:%8.2lf %s"));
317 els.push_back(new RRDGraphGPrint("indexes", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
318 els.push_back(new RRDGraphGPrint("indexes", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
319
320 els.push_back(new RRDGraphLine("numExtents", 1, "506101", "Extents"));
321 els.push_back(new RRDGraphGPrint("numExtents", RRDArchive::LAST, " Current\\:%8.2lf %s"));
322 els.push_back(new RRDGraphGPrint("numExtents", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
323 els.push_back(new RRDGraphGPrint("numExtents", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
324
325 std::string g1name = info.rrd_name + "_collindext";
326 std::string g1title = std::string("MongoDB Collections, Indexes, Extents for ") + dbname;
327 info.graph1 = new RRDGraphDefinition(g1name.c_str(), info.rrd, g1title.c_str(), "", defs, els);
328
329 defs.clear();
330 els.clear();
331 defs.push_back(RRDGraphDataDefinition("objects", RRDArchive::AVERAGE, info.rrd));
332
333 els.push_back(new RRDGraphLine("objects", 1, "FF7200", "Objects"));
334 els.push_back(new RRDGraphGPrint("objects", RRDArchive::LAST, " Current\\:%8.2lf %s"));
335 els.push_back(new RRDGraphGPrint("objects", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
336 els.push_back(new RRDGraphGPrint("objects", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
337
338 std::string g2name = info.rrd_name + "_objects";
339 std::string g2title = std::string("MongoDB Objects for ") + dbname;
340 info.graph2 = new RRDGraphDefinition(g2name.c_str(), info.rrd, g2title.c_str(), "", defs, els);
341
342 defs.clear();
343 els.clear();
344 defs.push_back(RRDGraphDataDefinition("avgObjSize", RRDArchive::AVERAGE, info.rrd));
345 defs.push_back(RRDGraphDataDefinition("dataSize", RRDArchive::AVERAGE, info.rrd));
346 defs.push_back(RRDGraphDataDefinition("storageSize", RRDArchive::AVERAGE, info.rrd));
347 defs.push_back(RRDGraphDataDefinition("indexSize", RRDArchive::AVERAGE, info.rrd));
348 defs.push_back(RRDGraphDataDefinition("fileSize", RRDArchive::AVERAGE, info.rrd));
349
350 els.push_back(new RRDGraphLine("avgObjSize", 1, "FF7200", "Avg Obj Sz"));
351 els.push_back(new RRDGraphGPrint("avgObjSize", RRDArchive::LAST, "Current\\:%8.2lf %s"));
352 els.push_back(new RRDGraphGPrint("avgObjSize", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
353 els.push_back(new RRDGraphGPrint("avgObjSize", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
354
355 els.push_back(new RRDGraphLine("dataSize", 1, "503001", "Data"));
356 els.push_back(new RRDGraphGPrint("dataSize", RRDArchive::LAST, " Current\\:%8.2lf %s"));
357 els.push_back(new RRDGraphGPrint("dataSize", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
358 els.push_back(new RRDGraphGPrint("dataSize", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
359
360 els.push_back(new RRDGraphLine("storageSize", 1, "EDAC00", "Storage"));
361 els.push_back(new RRDGraphGPrint("storageSize", RRDArchive::LAST, " Current\\:%8.2lf %s"));
362 els.push_back(new RRDGraphGPrint("storageSize", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
363 els.push_back(new RRDGraphGPrint("storageSize", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
364
365 els.push_back(new RRDGraphLine("indexSize", 1, "506101", "Index"));
366 els.push_back(new RRDGraphGPrint("indexSize", RRDArchive::LAST, " Current\\:%8.2lf %s"));
367 els.push_back(new RRDGraphGPrint("indexSize", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
368 els.push_back(new RRDGraphGPrint("indexSize", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
369
370 els.push_back(new RRDGraphLine("fileSize", 1, "0CCCCC", "File"));
371 els.push_back(new RRDGraphGPrint("fileSize", RRDArchive::LAST, " Current\\:%8.2lf %s"));
372 els.push_back(new RRDGraphGPrint("fileSize", RRDArchive::AVERAGE, "Average\\:%8.2lf %s"));
373 els.push_back(new RRDGraphGPrint("fileSize", RRDArchive::MAX, "Maximum\\:%8.2lf %s\\n"));
374
375 std::string g3name = info.rrd_name + "_sizes";
376 std::string g3title = std::string("MongoDB Sizes for ") + dbname;
377 info.graph3 = new RRDGraphDefinition(g3name.c_str(), info.rrd, g3title.c_str(), "Mem", defs, els);
378
379 rrd_manager->add_rrd(info.rrd);
380 try {
381 rrd_manager->add_graph(info.graph1);
382 rrd_manager->add_graph(info.graph2);
383 rrd_manager->add_graph(info.graph3);
384
385 dbstats_[dbname] = info;
386 logger->log_info(name(), "Started monitoring MongoDB %s", info.db_name.c_str());
387 } catch (Exception &e) {
388 rrd_manager->remove_rrd(info.rrd);
389 delete info.graph1;
390 delete info.graph2;
391 delete info.graph3;
392 delete info.rrd;
393 throw;
394 }
395}
396
397void
398MongoRRDThread::remove_dbstats(const char *path)
399{
400 if (dbstats_.find(path) != dbstats_.end()) {
401 DbStatsInfo &info = dbstats_[path];
402 rrd_manager->remove_rrd(info.rrd);
403 delete info.graph1;
404 delete info.graph2;
405 delete info.graph3;
406 delete info.rrd;
407
408 logger->log_info(name(), "Stopped monitoring MongoDB %s", info.db_name.c_str());
409 dbstats_.erase(path);
410 }
411}
412
413void
415{
416 timewait_->mark_start();
417 using namespace bsoncxx::builder;
418
419 try {
420 auto reply = mongodb_client->database("admin").run_command(
421 basic::make_document(basic::kvp("serverStatus", 1)));
422 if (check_mongodb_ok(reply.view())) {
423 auto opcounters = reply.view()["opcounters"].get_document().view();
424 int64_t insert, query, update, del, getmore, command;
425 insert = opcounters["insert"].get_int64();
426 query = opcounters["query"].get_int64();
427 update = opcounters["update"].get_int64();
428 del = opcounters["delete"].get_int64();
429 getmore = opcounters["getmore"].get_int64();
430 command = opcounters["command"].get_int64();
431
432 try {
434 "opcounters", "N:%i:%i:%i:%i:%i:%i", insert, query, update, del, getmore, command);
435 } catch (Exception &e) {
437 "Failed to update opcounters RRD, "
438 "exception follows");
439 logger->log_warn(name(), e);
440 }
441
442 auto mem = reply.view()["mem"].get_document().view();
443 int64_t resident, virtmem, mapped;
444 resident = mem["resident"].get_int64();
445 virtmem = mem["virtual"].get_int64();
446 mapped = mem["mapped"].get_int64();
447
448 try {
449 rrd_manager->add_data("memory", "N:%i:%i:%i", resident, virtmem, mapped);
450 } catch (Exception &e) {
451 logger->log_warn(name(), "Failed to update memory RRD, exception follows");
452 logger->log_warn(name(), e);
453 }
454
455 auto indexc = reply.view()["indexCounters"]["btree"].get_document().view();
456 int accesses, hits, misses, resets;
457 accesses = indexc["accesses"].get_int64();
458 hits = indexc["hits"].get_int64();
459 misses = indexc["misses"].get_int64();
460 resets = indexc["resets"].get_int64();
461
462 try {
463 rrd_manager->add_data("indexes", "N:%i:%i:%i:%i", accesses, hits, misses, resets);
464 } catch (Exception &e) {
466 "Failed to update indexes RRD, "
467 "exception follows");
468 logger->log_warn(name(), e);
469 }
470
471 for (DbStatsMap::iterator i = dbstats_.begin(); i != dbstats_.end(); ++i) {
472 auto dbstats = mongodb_client->database(i->second.db_name)
473 .run_command(basic::make_document(basic::kvp("dbStats", 1)));
474 if (int(dbstats.view()["ok"].get_double()) == 1) {
475 try {
476 int64_t collections, objects, numExtents, indexes, dataSize, storageSize, indexSize,
477 fileSize;
478 double avgObjSize;
479
480 collections = dbstats.view()["collections"].get_int64();
481 objects = dbstats.view()["objects"].get_int64();
482 avgObjSize = dbstats.view()["avgObjSize"].get_double();
483 dataSize = dbstats.view()["dataSize"].get_int64();
484 storageSize = dbstats.view()["storageSize"].get_int64();
485 numExtents = dbstats.view()["numExtents"].get_int64();
486 indexes = dbstats.view()["indexes"].get_int64();
487 indexSize = dbstats.view()["indexSize"].get_int64();
488 fileSize = dbstats.view()["fileSize"].get_int64();
489
490 try {
491 rrd_manager->add_data(i->second.rrd_name.c_str(),
492 "N:%li:%li:%f:%li:%li:%li:%li:%li:%li",
493 collections,
494 objects,
495 avgObjSize,
496 dataSize,
497 storageSize,
498 numExtents,
499 indexes,
500 indexSize,
501 fileSize);
502 } catch (Exception &e) {
504 "Failed to update dbstates RRD for "
505 "%s exception follows",
506 i->second.db_name.c_str());
507 logger->log_warn(name(), e);
508 }
509
510 } catch (mongocxx::exception &e) {
512 "Failed to update MongoDB RRD for database "
513 "%s: %s",
514 i->second.db_name.c_str(),
515 e.what());
516 }
517 } else {
519 "Failed to retrieve db stats for %s, reply: %s",
520 i->second.db_name.c_str(),
521 bsoncxx::to_json(dbstats.view()).c_str());
522 }
523 }
524
525 //double locktime = reply.view()["globalLock"].get_document().view()["lockTime"].get_double();
526
527 } else {
529 "Failed to retrieve server status, reply: %s",
530 bsoncxx::to_json(reply.view()).c_str());
531 }
532
533 } catch (mongocxx::exception &e) {
534 logger->log_warn(name(), "Failed to update MongoDB RRD: %s", e.what());
535 }
536
537 timewait_->wait_systime();
538}
539
540void
541MongoRRDThread::config_tag_changed(const char *new_tag)
542{
543 // ignored
544}
545
546void
547MongoRRDThread::config_value_changed(const Configuration::ValueIterator *v)
548{
549 if (v->is_string()) {
550 remove_dbstats(v->path());
551 add_dbstats(v->path(), v->get_string());
552 } else {
553 logger->log_warn(name(), "Non-string value at %s, ignoring", v->path());
554 }
555}
556
557void
558MongoRRDThread::config_comment_changed(const Configuration::ValueIterator *v)
559{
560}
561
562void
563MongoRRDThread::config_value_erased(const char *path)
564{
565 remove_dbstats(path);
566}
virtual ~MongoRRDThread()
Destructor.
MongoRRDThread()
Constructor.
virtual void finalize()
Finalize the thread.
virtual void loop()
Code to execute in the thread.
virtual void init()
Initialize the thread.
Clock * clock
By means of this member access to the clock is given.
Definition: clock.h:42
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:41
Interface for configuration change handling.
Iterator interface to iterate over config values.
Definition: config.h:75
virtual const char * path() const =0
Path of value.
virtual bool next()=0
Check if there is another element and advance to this if possible.
virtual bool is_string() const =0
Check if current value is a string.
virtual const char * type() const =0
Type of value.
virtual std::string get_string() const =0
Get string value.
virtual void rem_change_handler(ConfigurationChangeHandler *h)
Remove a configuration change handler.
Definition: config.cpp:619
virtual ValueIterator * search(const char *path)=0
Iterator with search results.
virtual void add_change_handler(ConfigurationChangeHandler *h)
Add a configuration change handler.
Definition: config.cpp:603
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:41
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
RRDManager * rrd_manager
Manager class to access RRD features.
Definition: rrd.h:44
Class to represent a RRD data source.
Print graph area.
Represent data definition in graph arguments.
Class representing a graph definition.
Print string inside graph.
Print graph line.
virtual void add_rrd(RRDDefinition *rrd_def)=0
Add RRD.
virtual void add_graph(RRDGraphDefinition *rrd_graph_def)=0
Add graph.
virtual void add_data(const char *rrd_name, const char *format,...)=0
Add data.
virtual void remove_rrd(RRDDefinition *rrd_def)=0
Remove RRD.
Thread class encapsulation of pthreads.
Definition: thread.h:46
void set_prepfin_conc_loop(bool concurrent=true)
Set concurrent execution of prepare_finalize() and loop().
Definition: thread.cpp:716
const char * name() const
Get name of thread.
Definition: thread.h:100
Time wait utility.
Definition: wait.h:33
void mark_start()
Mark start of loop.
Definition: wait.cpp:68
void wait_systime()
Wait until minimum loop time has been reached in real time.
Definition: wait.cpp:96
Fawkes library namespace.