--- /dev/null
+# netdata python.d.plugin configuration for mdstat
+#
+# This file is in YaML format. Generally the format is:
+#
+# name: value
+#
+
+# ----------------------------------------------------------------------
+# Global Variables
+# These variables set the defaults for all JOBs, however each JOB
+# may define its own, overriding the defaults.
+
+# update_every sets the default data collection frequency.
+# If unset, the python.d.plugin default is used.
+# update_every: 1
+
+# priority controls the order of charts at the netdata dashboard.
+# Lower numbers move the charts towards the top of the page.
+# If unset, the default for python.d.plugin is used.
+# priority: 60000
+
+# retries sets the number of retries to be made in case of failures.
+# If unset, the default for python.d.plugin is used.
+# Attempts to restore the service are made once every update_every
+# and only if the module has collected values in the past.
+# retries: 5
--- /dev/null
+# -*- coding: utf-8 -*-
+# Description: mdstat netdata python.d module
+# Author: l2isbad
+
+from base import SimpleService
+from re import compile
+priority = 60000
+retries = 60
+update_every = 1
+
+
+class Service(SimpleService):
+ def __init__(self, configuration=None, name=None):
+ SimpleService.__init__(self, configuration=configuration, name=name)
+ self.order = ['agr_health']
+ self.definitions = {'agr_health':
+ {'options':
+ [None, 'Faulty devices in MD', 'failed disks', 'health', 'md.health', 'line'],
+ 'lines': []}}
+ self.proc_mdstat = '/proc/mdstat'
+ self.regex_disks = compile(r'((?<=\ )[a-zA-Z_0-9]+(?= : active)).*?((?<= \[)[0-9]+)/([0-9]+(?=\] ))')
+ self.regex_status = compile(r'([a-zA-Z_0-9]+)( : active)[^:]*?([a-z]+) = ([0-9.]+(?=%)).*?((?<=finish=)[0-9.]+)min speed=([0-9]+)')
+
+ def check(self):
+ raw_data = self._get_raw_data()
+ if not raw_data:
+ self.error('Cant read mdstat data from %s' % (self.proc_mdstat))
+ return False
+ else:
+ md_list = [md[0] for md in self.regex_disks.findall(raw_data)]
+ for md in md_list:
+ self.order.append(md)
+ self.order.append(''.join([md, '_status']))
+ self.order.append(''.join([md, '_rate']))
+ self.definitions['agr_health']['lines'].append([''.join([md, '_health']), md, 'absolute'])
+ self.definitions[md] = {'options':
+ [None, 'MD disks stats', 'disks', md, 'md.disks', 'stacked'],
+ 'lines': [[''.join([md, '_total']), 'total', 'absolute'],
+ [''.join([md, '_inuse']), 'inuse', 'absolute']]}
+ self.definitions[''.join([md, '_status'])] = {'options':
+ [None, 'MD current status', 'percent', md, 'md.status', 'line'],
+ 'lines': [[''.join([md, '_resync']), 'resync', 'absolute', 1, 100],
+ [''.join([md, '_recovery']), 'recovery', 'absolute', 1, 100],
+ [''.join([md, '_check']), 'check', 'absolute', 1, 100]]}
+ self.definitions[''.join([md, '_rate'])] = {'options':
+ [None, 'MD operation status', 'rate', md, 'md.rate', 'line'],
+ 'lines': [[''.join([md, '_finishin']), 'finish min', 'absolute', 1, 100],
+ [''.join([md, '_rate']), 'megabyte/s', 'absolute', -1, 100]]}
+ self.info('Plugin was started successfully. MDs to monitor %s' % (md_list))
+ to_netdata = {}
+
+ return True
+
+ def _get_raw_data(self):
+ """
+ Read data from /proc/mdstat
+ :return: str
+ """
+ try:
+ with open(self.proc_mdstat, 'rt') as proc_mdstat:
+ raw_result = proc_mdstat.read()
+ except Exception:
+ return None
+ else:
+ raw_result = ' '.join(raw_result.split())
+ return raw_result
+
+ def _get_data(self):
+ """
+ Parse data from _get_raw_data()
+ :return: dict
+ """
+ raw_mdstat = self._get_raw_data()
+ mdstat_disks = self.regex_disks.findall(raw_mdstat)
+ mdstat_status = self.regex_status.findall(raw_mdstat)
+ to_netdata = {}
+
+ for md in mdstat_disks:
+ to_netdata[''.join([md[0], '_total'])] = int(md[1])
+ to_netdata[''.join([md[0], '_inuse'])] = int(md[2])
+ to_netdata[''.join([md[0], '_health'])] = int(md[1]) - int(md[2])
+ to_netdata[''.join([md[0], '_check'])] = 0
+ to_netdata[''.join([md[0], '_resync'])] = 0
+ to_netdata[''.join([md[0], '_recovery'])] = 0
+ to_netdata[''.join([md[0], '_finishin'])] = 0
+ to_netdata[''.join([md[0], '_rate'])] = 0
+
+ for md in mdstat_status:
+ to_netdata[''.join([md[0], '_' + md[2]])] = round(float(md[3]) * 100)
+ to_netdata[''.join([md[0], '_finishin'])] = round(float(md[4]) * 100)
+ to_netdata[''.join([md[0], '_rate'])] = round(float(md[5]) / 1000 * 100)
+
+ return to_netdata
} else break;
}
}
- total_xsw.bytes_used += xsw.xsw_used * system_pagesize;
- total_xsw.bytes_total += xsw.xsw_nblks * system_pagesize;
+ total_xsw.bytes_used += xsw.xsw_used;
+ total_xsw.bytes_total += xsw.xsw_nblks;
}
if (likely(do_swap)) {
st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
st->isdetail = 1;
- rrddim_add(st, "free", NULL, 1, 1048576, RRDDIM_ABSOLUTE);
- rrddim_add(st, "used", NULL, 1, 1048576, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "free", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "used", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
}
else rrdset_next(st);