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