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 
35 using namespace mongocxx;
36 using 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 
62 void
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()) {
223  logger->log_warn(name(),
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 
245  config->add_change_handler(this);
246 }
247 
248 void
250 {
251  config->rem_change_handler(this);
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 
279 void
280 MongoRRDThread::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 
397 void
398 MongoRRDThread::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 
413 void
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) {
436  logger->log_warn(name(),
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) {
465  logger->log_warn(name(),
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) {
503  logger->log_warn(name(),
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) {
511  logger->log_warn(name(),
512  "Failed to update MongoDB RRD for database "
513  "%s: %s",
514  i->second.db_name.c_str(),
515  e.what());
516  }
517  } else {
518  logger->log_warn(name(),
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 {
528  logger->log_warn(name(),
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 
540 void
541 MongoRRDThread::config_tag_changed(const char *new_tag)
542 {
543  // ignored
544 }
545 
546 void
547 MongoRRDThread::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 
557 void
558 MongoRRDThread::config_comment_changed(const Configuration::ValueIterator *v)
559 {
560 }
561 
562 void
563 MongoRRDThread::config_value_erased(const char *path)
564 {
565  remove_dbstats(path);
566 }
fawkes::RRDGraphDefinition
Definition: rrd_descriptions.h:470
fawkes::MongoDBAspect
Definition: mongodb.h:43
fawkes::Thread::set_prepfin_conc_loop
void set_prepfin_conc_loop(bool concurrent=true)
Set concurrent execution of prepare_finalize() and loop().
Definition: thread.cpp:722
fawkes::RRDManager::add_graph
virtual void add_graph(RRDGraphDefinition *rrd_graph_def)=0
Add graph.
fawkes::RRDGraphGPrint
Definition: rrd_descriptions.h:313
fawkes::MongoDBAspect::mongodb_client
mongocxx::client * mongodb_client
Definition: mongodb.h:59
fawkes::Configuration::ValueIterator::is_string
virtual bool is_string() const =0
fawkes::RRDDataSource
Definition: rrd_descriptions.h:40
fawkes::Logger::log_info
virtual void log_info(const char *component, const char *format,...)=0
fawkes::Configuration::ValueIterator::get_string
virtual std::string get_string() const =0
MongoRRDThread::~MongoRRDThread
virtual ~MongoRRDThread()
Destructor.
Definition: mongorrd_thread.cpp:58
fawkes::ConfigurationChangeHandler
Definition: change_handler.h:37
fawkes::Thread::name
const char * name() const
Definition: thread.h:100
fawkes::ClockAspect::clock
Clock * clock
Definition: clock.h:56
fawkes::RRDManager::remove_rrd
virtual void remove_rrd(RRDDefinition *rrd_def)=0
Remove RRD.
fawkes::Configuration::ValueIterator
Definition: config.h:77
MongoRRDThread::MongoRRDThread
MongoRRDThread()
Constructor.
Definition: mongorrd_thread.cpp:49
fawkes::Configuration::search
virtual ValueIterator * search(const char *path)=0
fawkes::RRDGraphDataDefinition
Definition: rrd_descriptions.h:248
fawkes::LoggingAspect::logger
Logger * logger
Definition: logging.h:53
fawkes
fawkes::Logger::log_warn
virtual void log_warn(const char *component, const char *format,...)=0
MongoRRDThread::init
virtual void init()
Initialize the thread.
Definition: mongorrd_thread.cpp:63
fawkes::RRDGraphArea
Definition: rrd_descriptions.h:419
fawkes::TimeWait::mark_start
void mark_start()
Mark start of loop.
Definition: wait.cpp:74
fawkes::ConfigurableAspect::config
Configuration * config
Definition: configurable.h:53
MongoRRDThread::loop
virtual void loop()
Code to execute in the thread.
Definition: mongorrd_thread.cpp:414
fawkes::RRDManager::add_data
virtual void add_data(const char *rrd_name, const char *format,...)=0
Add data.
fawkes::Configuration::rem_change_handler
virtual void rem_change_handler(ConfigurationChangeHandler *h)
Remove a configuration change handler.
Definition: config.cpp:625
fawkes::RRDAspect::rrd_manager
RRDManager * rrd_manager
Definition: rrd.h:50
fawkes::Thread
Definition: thread.h:45
fawkes::TimeWait
Definition: wait.h:38
fawkes::RRDDefinition
Definition: rrd_descriptions.h:168
fawkes::Configuration::ValueIterator::type
virtual const char * type() const =0
fawkes::Configuration::add_change_handler
virtual void add_change_handler(ConfigurationChangeHandler *h)
Add a configuration change handler.
Definition: config.cpp:609
fawkes::Configuration::ValueIterator::path
virtual const char * path() const =0
fawkes::Configuration::ValueIterator::next
virtual bool next()=0
fawkes::RRDManager::add_rrd
virtual void add_rrd(RRDDefinition *rrd_def)=0
Add RRD.
fawkes::RRDGraphLine
Definition: rrd_descriptions.h:357
MongoRRDThread::finalize
virtual void finalize()
Finalize the thread.
Definition: mongorrd_thread.cpp:249
fawkes::Exception
Definition: exception.h:41