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