@cryptotaxi247 / netdata-1 / commits / e3c740c2b

mongodb_plugin: replica set members state charts added

Ilya committed Feb 23, 2017 at 02:18 UTC e3c740c2bd0a54ab43af91338d4bcf3ef2574282
1 file changed +109 -40
python.d/mongodb.chart.py
+109 -40
@@ -3,6 +3,7 @@
3 # Author: l2isbad
4
5 from base import SimpleService
6 +from copy import deepcopy
7 try:
8 from pymongo import MongoClient
9 from pymongo.errors import PyMongoError
@@ -15,6 +16,19 @@ except ImportError:
16 priority = 60000
17 retries = 60
18
19 +REPLSET_STATES = [
20 + ('1', 'primary'),
21 + ('8', 'down'),
22 + ('2', 'secondary'),
23 + ('3', 'recovering'),
24 + ('5', 'startup2'),
25 + ('4', 'fatal'),
26 + ('7', 'arbiter'),
27 + ('6', 'unknown'),
28 + ('9', 'rollback'),
29 + ('10', 'removed'),
30 + ('0', 'startup')]
31 +
32 # charts order (can be overridden if you want less charts, or different order)
33 ORDER = ['read_operations', 'write_operations', 'active_clients', 'journaling_transactions',
34 'journaling_volume', 'background_flush_average', 'background_flush_last', 'background_flush_rate',
@@ -139,12 +153,11 @@ CHARTS = {
153 ['errors_user', 'user', 'incremental', 1, 1]
154 ]},
155 'wiredtiger_cache': {
142 - 'options': [None, "Amount of space taken by cached data/dirty data in the cache and maximum cache size",
156 + 'options': [None, "Amount of space taken by cached data and by dirty data in the cache",
157 "KB", 'resource utilization', 'mongodb.wiredtiger_cache', 'stacked'],
158 'lines': [
159 ['wiredTiger_bytes_in_cache', 'cached', 'absolute', 1, 1024],
146 - ['wiredTiger_dirty_in_cache', 'dirty', 'absolute', 1, 1024],
147 - ['wiredTiger_maximum_in_conf', 'maximum', 'absolute', 1, 1024]
160 + ['wiredTiger_dirty_in_cache', 'dirty', 'absolute', 1, 1024]
161 ]},
162 'wiredtiger_pages_evicted': {
163 'options': [None, "Pages evicted from the cache",
@@ -218,6 +231,8 @@ class Service(SimpleService):
231 self.error(error)
232 return False
233
234 + self.repl = 'repl' in server_status
235 + self.databases = self.connection.database_names()
236 self._create_charts(server_status)
237
238 return True
@@ -225,7 +240,7 @@ class Service(SimpleService):
240 def _create_charts(self, server_status):
241
242 self.order = ORDER[:]
228 - self.definitions = CHARTS
243 + self.definitions = deepcopy(CHARTS)
244 self.ss = dict()
245
246 for elem in ['dur', 'backgroundFlushing', 'wiredTiger', 'tcmalloc', 'cursor', 'commands']:
@@ -255,8 +270,6 @@ class Service(SimpleService):
270 self.order.remove('command_total_rate')
271 self.order.remove('command_failed_rate')
272
258 - self.databases = self.connection.database_names()
259 -
273 for dbase in self.databases:
274 self.order.append('_'.join([dbase, 'dbstats']))
275 self.definitions['_'.join([dbase, 'dbstats'])] = {
@@ -269,17 +282,61 @@ class Service(SimpleService):
282 ]}
283 self.definitions['dbstats_objects']['lines'].append(['_'.join([dbase, 'objects']), dbase, 'absolute'])
284
285 + if server_status.get('repl'):
286 + hosts = server_status['repl']['hosts']
287 + for host in hosts:
288 + chart_name = '_'.join([host, 'state'])
289 + self.order.append(chart_name)
290 + self.definitions[chart_name] = {
291 + 'options': [None, "%s state" % host, "state",
292 + 'replication', 'mongodb.replication_state', 'line'],
293 + 'lines': [
294 + ]}
295 + for state, description in REPLSET_STATES:
296 + self.definitions[chart_name]['lines'].append(['_'.join([host, 'state', state]), description, 'absolute', 1, 1])
297 +
298 +
299
300 def _get_raw_data(self):
301 raw_data = dict()
302
303 + raw_data.update(self.get_serverstatus_() or dict())
304 + raw_data.update(self.get_dbstats_() or dict())
305 + raw_data.update(self.get_replsetgetstatus_() or dict())
306 +
307 + return raw_data or None
308 +
309 + def get_serverstatus_(self):
310 + raw_data = dict()
311 try:
312 raw_data['serverStatus'] = self.connection.admin.command('serverStatus')
313 + except PyMongoError:
314 + return None
315 + else:
316 + return raw_data
317 +
318 + def get_dbstats_(self):
319 + raw_data = dict()
320 + raw_data['dbStats'] = dict()
321 + try:
322 for dbase in self.databases:
279 - raw_data[dbase] = self.connection[dbase].command('dbStats')
323 + raw_data['dbStats'][dbase] = self.connection[dbase].command('dbStats')
324 + except PyMongoError:
325 + return None
326 + else:
327 + return raw_data
328 +
329 + def get_replsetgetstatus_(self):
330 + if not self.repl:
331 + return None
332 +
333 + raw_data = dict()
334 + try:
335 + raw_data['replSetGetStatus'] = self.connection.admin.command('replSetGetStatus')
336 except PyMongoError:
281 - return None
282 - return raw_data
337 + return None
338 + else:
339 + return raw_data
340
341 def _get_data(self):
342 """
@@ -291,66 +348,78 @@ class Service(SimpleService):
348 return None
349
350 to_netdata = dict()
294 - server_status = raw_data['serverStatus']
295 -
296 - to_netdata.update(update_dict_key(server_status['opcounters'], 'readWriteOper'))
297 - to_netdata.update(update_dict_key(server_status['globalLock']['activeClients'], 'activeClients'))
298 - to_netdata.update(update_dict_key(server_status['connections'], 'connections'))
299 - to_netdata.update(update_dict_key(server_status['mem'], 'memory'))
300 - to_netdata.update(update_dict_key(server_status['globalLock']['currentQueue'], 'currentQueue'))
301 - to_netdata.update(update_dict_key(server_status['asserts'], 'errors'))
302 - to_netdata['page_faults'] = server_status['extra_info']['page_faults']
303 - to_netdata['record_moves'] = server_status['metrics']['record']['moves']
351 + serverStatus = raw_data['serverStatus']
352 + dbStats = raw_data['dbStats']
353 + replSetGetStatus = raw_data.get('replSetGetStatus')
354 +
355 + # serverStatus
356 + to_netdata.update(update_dict_key(serverStatus['opcounters'], 'readWriteOper'))
357 + to_netdata.update(update_dict_key(serverStatus['globalLock']['activeClients'], 'activeClients'))
358 + to_netdata.update(update_dict_key(serverStatus['connections'], 'connections'))
359 + to_netdata.update(update_dict_key(serverStatus['mem'], 'memory'))
360 + to_netdata.update(update_dict_key(serverStatus['globalLock']['currentQueue'], 'currentQueue'))
361 + to_netdata.update(update_dict_key(serverStatus['asserts'], 'errors'))
362 + to_netdata['page_faults'] = serverStatus['extra_info']['page_faults']
363 + to_netdata['record_moves'] = serverStatus['metrics']['record']['moves']
364
365 if self.ss['dur']:
306 - to_netdata['journalTrans_commits'] = server_status['dur']['commits']
307 - to_netdata['journalTrans_journaled'] = int(server_status['dur']['journaledMB'] * 100)
366 + to_netdata['journalTrans_commits'] = serverStatus['dur']['commits']
367 + to_netdata['journalTrans_journaled'] = int(serverStatus['dur']['journaledMB'] * 100)
368
369 if self.ss['backgroundFlushing']:
310 - to_netdata['background_flush_average'] = int(server_status['backgroundFlushing']['average_ms'] * 100)
311 - to_netdata['background_flush_last'] = int(server_status['backgroundFlushing']['last_ms'] * 100)
312 - to_netdata['background_flush_rate'] = server_status['backgroundFlushing']['flushes']
370 + to_netdata['background_flush_average'] = int(serverStatus['backgroundFlushing']['average_ms'] * 100)
371 + to_netdata['background_flush_last'] = int(serverStatus['backgroundFlushing']['last_ms'] * 100)
372 + to_netdata['background_flush_rate'] = serverStatus['backgroundFlushing']['flushes']
373
374 if self.ss['cursor']:
315 - to_netdata['cursor_timedOut'] = server_status['metrics']['cursor']['timedOut']
316 - to_netdata.update(update_dict_key(server_status['metrics']['cursor']['open'], 'cursor'))
375 + to_netdata['cursor_timedOut'] = serverStatus['metrics']['cursor']['timedOut']
376 + to_netdata.update(update_dict_key(serverStatus['metrics']['cursor']['open'], 'cursor'))
377
378 if self.ss['wiredTiger']:
319 - wired_tiger = server_status['wiredTiger']
320 - to_netdata.update(update_dict_key(server_status['wiredTiger']['concurrentTransactions']['read'],
379 + wired_tiger = serverStatus['wiredTiger']
380 + to_netdata.update(update_dict_key(serverStatus['wiredTiger']['concurrentTransactions']['read'],
381 'wiredTigerRead'))
322 - to_netdata.update(update_dict_key(server_status['wiredTiger']['concurrentTransactions']['write'],
382 + to_netdata.update(update_dict_key(serverStatus['wiredTiger']['concurrentTransactions']['write'],
383 'wiredTigerWrite'))
384 to_netdata['wiredTiger_bytes_in_cache'] = wired_tiger['cache']['bytes currently in the cache']
325 - to_netdata['wiredTiger_maximum_in_conf'] = wired_tiger['cache']['maximum bytes configured']
385 to_netdata['wiredTiger_dirty_in_cache'] = wired_tiger['cache']['tracked dirty bytes in the cache']
386 to_netdata['wiredTiger_unmodified_pages_evicted'] = wired_tiger['cache']['unmodified pages evicted']
387 to_netdata['wiredTiger_modified_pages_evicted'] = wired_tiger['cache']['modified pages evicted']
388
389 if self.ss['tcmalloc']:
331 - to_netdata.update(server_status['tcmalloc']['generic'])
332 - to_netdata.update(dict([(k, v) for k, v in server_status['tcmalloc']['tcmalloc'].items()
390 + to_netdata.update(serverStatus['tcmalloc']['generic'])
391 + to_netdata.update(dict([(k, v) for k, v in serverStatus['tcmalloc']['tcmalloc'].items()
392 if int_or_float(v)]))
393
394 if self.ss['commands']:
395 for elem in ['count', 'createIndexes', 'delete', 'eval', 'findAndModify', 'insert', 'update']:
337 - to_netdata.update(update_dict_key(server_status['metrics']['commands'][elem], elem))
396 + to_netdata.update(update_dict_key(serverStatus['metrics']['commands'][elem], elem))
397
339 - for dbase in self.databases:
340 - dbase_dbstats = raw_data[dbase]
341 - dbase_dbstats = dict([(k, v) for k, v in dbase_dbstats.items() if int_or_float(v)])
342 - to_netdata.update(update_dict_key(dbase_dbstats, dbase))
398 + # dbStats
399 + for dbase in dbStats:
400 + to_netdata.update(update_dict_key(dbStats[dbase], dbase))
401 +
402 + # replSetGetStatus
403 + if replSetGetStatus:
404 + members = replSetGetStatus['members']
405 + for member in members:
406 + for elem in REPLSET_STATES:
407 + state = elem[0]
408 + to_netdata.update({'_'.join([member['name'], 'state', state]): 0})
409 + to_netdata.update({'_'.join([member['name'], 'state', str(member['state'])]): member['state']})
410
411 return to_netdata
412
413 def _create_connection(self):
414 conn_vars = {'host': self.host, 'port': self.port}
348 - if 'server_selection_timeout' in dir(MongoClient):
415 + if hasattr(MongoClient, 'server_selection_timeout'):
416 conn_vars.update({'serverselectiontimeoutms': self.timeout})
417 try:
418 connection = MongoClient(**conn_vars)
419 if self.user and self.password:
420 connection.admin.authenticate(name=self.user, password=self.password)
421 + # elif self.user:
422 + # connection.admin.authenticate(name=self.user, mechanism='MONGODB-X509')
423 server_status = connection.admin.command('serverStatus')
424 except PyMongoError as error:
425 return None, None, str(error)
@@ -359,11 +428,11 @@ class Service(SimpleService):
428
429
430 def update_dict_key(collection, string):
362 - return dict([('_'.join([string, k]), int(round(v))) for k, v in collection.items()])
431 + return dict([('_'.join([string, k]), int(round(v))) for k, v in collection.items() if int_or_float(v)])
432
433
434 def int_or_float(value):
366 - return isinstance(value, int) or isinstance(value, float)
435 + return isinstance(value, (int, float))
436
437
438 def in_server_status(elem, server_status):