Completed
Push — master ( f1337f...ab2213 )
by Kenny
01:06
created

DiskStats.__init__()   B

Complexity

Conditions 4

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
c 1
b 0
f 0
dl 0
loc 29
rs 8.5806
1
# -*- coding: utf-8 -*-
2
3
__author__ = 'Kenny Freeman'
4
__email__ = '[email protected]'
5
__license__ = "ISCL"
6
__docformat__ = 'reStructuredText'
7
8
import re
9
import time
10
11
import plumd
12
import plumd.plugins
13
from plumd.calc import Differential
14
from plumd.util import get_file_map, get_file
15
16
17
class DiskStats(plumd.plugins.Reader):
18
19
    proc_colums = 14
20
21
    """Plugin to measure various kernel metrics from /proc."""
22
    defaults = {
23
        'poll.interval': 10,
24
        'proc_path': '/proc',
25
        'diskstats_dev_re': "dm-\d",
26
        'diskstats_cols': ["r", "r_merge", "r_sector", "r_time", "w", "w_merge",
27
                           "w_sector", "w_time", "io_inprog", "io_time",
28
                           "io_weighted_time"]
29
    }
30
31
    def __init__(self, log, config):
32
        """Plugin to measure various kernel metrics from /proc.
33
34
        :param log: A logger
35
        :type log: logging.RootLogger
36
        :param config: a plumd.config.Conf configuration helper instance.
37
        :type config: plumd.config.Conf
38
        """
39
        super(DiskStats, self).__init__(log, config)
40
        config.defaults(DiskStats.defaults)
41
        self.calc = Differential()
42
        self.proc_file = "{0}/diskstats".format(config.get('proc_path'))
43
        self.diskstats_dev_re = re.compile(config.get('diskstats_dev_re'))
44
        self.diskstats_cols = self.config.get('diskstats_cols')
45
        self.devices = [] # list of device names to record metrics for
46
        self.enabled = True
47
        # get list of available devices:
48
        dat = get_file_map(self.proc_file, 2, 0)
49
        # key is the device name, exclude ones matching the re
50
        for key, val in dat.items():
51
            if not self.diskstats_dev_re.match(key):
52
                self.devices.append(key)
53
        # check format of proc file
54
        ncols = len(get_file(self.proc_file).split("\n")[0].split())
55
        self.enabled = ncols == DiskStats.proc_colums
56
        if not self.enabled:
57
            msg = "DiskStats: invalid format: {0} has {1} cols, not {2}"
58
            self.log.error(msg.format(self.proc_file, ncols,
59
                                     DiskStats.proc_colums))
60
61
    def poll(self):
62
        """Poll for kernel metrics under /proc.
63
64
        :rtype: ResultSet
65
        """
66
        return plumd.ResultSet(self.check())
67
68
69
    def check(self):
70
        """Return disk io metrics from proc file diskstats.
71
72
        :rtype: plumd.Result
73
        """
74
        # times in ms
75
        cols = self.diskstats_cols
76
        result = plumd.Result("diskstats")
77
        if not self.enabled:
78
            return [result]
79
        dat = {}
80
        # read and process /proc/diskstats
81
        dat = get_file_map(self.proc_file, 2, 0)
82
        ts = time.time()
83
        for dev in self.devices:
84
            if dev not in dat:
85
                continue
86
            for mname in cols:
87
                mval = float(dat[dev].popleft())
88
                mstr = "{0}.{1}".format(dev, mname)
89
                dval = self.calc.per_second(mstr, mval, ts)
90
                result.add(plumd.Float(mstr, dval))
91
        return [result]
92