Completed
Branch master (7e8cc2)
by Kenny
03:21 queued 19s
created

Stat.proc_stat_cpu()   C

Complexity

Conditions 4

Size

Total Lines 22

Duplication

Lines 1
Ratio 4.55 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
c 1
b 0
f 0
dl 1
loc 22
rs 6.203
1
# -*- coding: utf-8 -*-
2
3
__author__ = 'Kenny Freeman'
4
__email__ = '[email protected]'
5
__license__ = "ISCL"
6
__docformat__ = 'reStructuredText'
7
8
import time
9
from collections import deque
10
11
import plumd
12
import plumd.plugins
13
from plumd.calc import Differential
14
from plumd.util import get_file_map
15
16
17
## todo: switch from list with pop(0) to deque
18
class Stat(plumd.plugins.Reader):
19
    """Class to read metrics from /proc/stat"""
20
    defaults = {
21
        'proc_stat_gauges': ['procs_running', 'procs_blocked'],
22
        'proc_stat_rates': ['intr', 'ctxt', 'softirq'],
23
        'cpu_metrics': ["user", "nice", "system", "idle", "iowait", "irq",
24
                        "softirq","steal", "guest", "guest_nice"],
25
        'per_cpu': False,
26
    }
27
28 View Code Duplication
    def __init__(self, log, config):
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
29
        """Plugin to measure various kernel metrics from /proc/stat
30
31
        :param log: A logger
32
        :type log: logging.RootLogger
33
        :param config: a plumd.config.Conf configuration helper instance.
34
        :type config: plumd.config.Conf
35
        """
36
        super(Stat, self).__init__(log, config)
37
        self.config.defaults(Stat.defaults)
38
        self.calc = Differential()
39
        self.proc_file = "{0}/stat".format(config.get('proc_path'))
40
        self.per_cpu = self.config.get('per_cpu')
41
        self.cpu_metrics = self.config.get('cpu_metrics')
42
        self.gauges = self.config.get('proc_stat_gauges')
43
        self.rates = self.config.get('proc_stat_rates')
44
45
46
    def poll(self):
47
        """Return cpu utilization and process metrics from proc file stat.
48
49
        :rtype: plumd.ResultSet
50
        """
51
        return plumd.ResultSet(self.check())
52
53
54
    def check(self):
55
        """Return cpu utilization and process metrics from proc file stat.
56
57
        :rtype: collections.deque
58
        """
59
        results = deque()
60
        result = plumd.Result("stat")
61
62
        dat = get_file_map(self.proc_file, 0, 0)
63
        ts = time.time()
64
65
        # record gauges
66
        for i, metric in enumerate(self.gauges):
67
            if metric not in dat:
68
                self.log.warn("stat: unknown metric {0}".format(metric))
69
                del(self.gauges[i])
70
                continue
71
            result.add(plumd.Int(metric, dat[metric][0]))
72
73
        # record rates
74
        for i, metric in enumerate(self.rates):
75
            if metric not in dat:
76
                self.log.warn("stat: unknown metric {0}".format(metric))
77 View Code Duplication
                del(self.rates[i])
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
78
                continue
79
            mval = self.calc.per_second(metric, float(dat[metric][0]), ts)
80
            result.add(plumd.Int(metric, mval))
81
82
        # record cpu
83
        if "cpu" in dat:
84
            results.append(self.proc_stat_cpu_percent("cpu", dat["cpu"]))
85
86
        # record each cpu if configured
87
        if self.per_cpu:
88
            for i in xrange(0, len(dat)):
89
                mstr = "cpu{0}".format(i)
90
                if mstr not in dat:
91
                    break
92
                results.append(self.proc_stat_cpu(mstr, dat[mstr], ts))
93
94
        results.append(result)
95
        return results
96
97
98
    def proc_stat_cpu_percent(self, key, val):
99 View Code Duplication
        """Return cpu utilization metrics in percentage.
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
100
101
        :param key: The metric name (eg. cpu, cpu0, cpu1, etc)
102
        :type key: str
103
        :param val: A deque populated with the metric values from stat
104
        :type val: deque
105
        :rtype: list
106
        """
107
        result = plumd.Result("cpu")
108
        total = sum([ float(i) for i in val])
109
        cpu = self.config.get('cpu_metrics')
110
        for map_val in cpu:
111
            if len(val) < 1:
112
                break
113
            metric_val = float(val.popleft())
114
            mstr = "{0}_{1}".format(key, map_val)
115
            percent_val = metric_val / total * 100.00
116
            result.add(plumd.Float(mstr, percent_val))
117
        return result
118
119
120
    def proc_stat_cpu(self, key, val, ts):
121
        """Return cpu utilization metrics in USER_HZ or Jiffies
122
        (most likely units of 100Hz intervals ie. 100ms intervals).
123
124
        :param key: The metric name (eg. cpu, cpu0, cpu1, etc)
125
        :type key: str
126
        :param val: A deque populated with the metric values from stat
127
        :type val: deque
128
        :rtype: list
129
        """
130
        result = plumd.Result("cpus")
131
        total = sum([ float(i) for i in val])
132
        cpu = self.config.get('cpu_metrics')
133
        for map_val in cpu:
134
            if len(val) < 1:
135
                break
136
            metric_val = float(val.popleft())
137
            mstr = "{0}_{1}".format(key, map_val)
138
            percent_val = float(metric_val / total) * 100.00
139
            mval = self.calc.per_second(key, percent_val, ts)
140
            result.add(plumd.Float(mstr, mval))
141
        return result
142