diff options
Diffstat (limited to 'python.d/cpufreq.chart.py')
-rw-r--r-- | python.d/cpufreq.chart.py | 83 |
1 files changed, 58 insertions, 25 deletions
diff --git a/python.d/cpufreq.chart.py b/python.d/cpufreq.chart.py index a9de5cedd..c761aae88 100644 --- a/python.d/cpufreq.chart.py +++ b/python.d/cpufreq.chart.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- # Description: cpufreq netdata python.d module -# Author: Pawel Krupa (paulfantom) +# Author: Pawel Krupa (paulfantom) and Steven Noonan (tycho) +import glob import os +import time from base import SimpleService # default module values (can be overridden per job in `config`) @@ -18,29 +20,53 @@ CHARTS = { ]} } - class Service(SimpleService): def __init__(self, configuration=None, name=None): prefix = os.getenv('NETDATA_HOST_PREFIX', "") if prefix.endswith('/'): prefix = prefix[:-1] self.sys_dir = prefix + "/sys/devices" - self.filename = "scaling_cur_freq" SimpleService.__init__(self, configuration=configuration, name=name) self.order = ORDER self.definitions = CHARTS self._orig_name = "" self.assignment = {} - self.paths = [] + self.accurate_exists = True + self.accurate_last = {} def _get_data(self): - raw = {} - for path in self.paths: - with open(path, 'r') as f: - raw[path] = f.read() data = {} - for path in self.paths: - data[self.assignment[path]] = raw[path] + + if self.accurate_exists: + elapsed = time.time() - self.timetable['last'] + + accurate_ok = True + + for name, paths in self.assignment.items(): + last = self.accurate_last[name] + current = 0 + for line in open(paths['accurate'], 'r'): + line = list(map(int, line.split())) + current += (line[0] * line[1]) / 100 + delta = current - last + data[name] = delta + self.accurate_last[name] = current + if delta == 0 or abs(delta) > 1e7: + # Delta is either too large or nonexistent, fall back to + # less accurate reading. This can happen if we switch + # to/from the 'schedutil' governor, which doesn't report + # stats. + accurate_ok = False + + if accurate_ok: + return data + else: + self.alert("accurate method failed, falling back") + + + for name, paths in self.assignment.items(): + data[name] = open(paths['inaccurate'], 'r').read() + return data def check(self): @@ -51,23 +77,30 @@ class Service(SimpleService): self._orig_name = self.chart_name - for dirpath, _, filenames in os.walk(self.sys_dir): - if self.filename in filenames: - self.paths.append(dirpath + "/" + self.filename) - - if len(self.paths) == 0: - self.error("cannot find", self.filename) + for path in glob.glob(self.sys_dir + '/system/cpu/cpu*/cpufreq/stats/time_in_state'): + path_elem = path.split('/') + cpu = path_elem[-4] + if cpu not in self.assignment: + self.assignment[cpu] = {} + self.assignment[cpu]['accurate'] = path + self.accurate_last[cpu] = 0 + + if len(self.assignment) == 0: + self.accurate_exists = False + + for path in glob.glob(self.sys_dir + '/system/cpu/cpu*/cpufreq/scaling_cur_freq'): + path_elem = path.split('/') + cpu = path_elem[-3] + if cpu not in self.assignment: + self.assignment[cpu] = {} + self.assignment[cpu]['inaccurate'] = path + + if len(self.assignment) == 0: + self.error("couldn't find a method to read cpufreq statistics") return False - self.paths.sort() - i = 0 - for path in self.paths: - self.assignment[path] = "cpu" + str(i) - i += 1 - - for name in self.assignment: - dim = self.assignment[name] - self.definitions[ORDER[0]]['lines'].append([dim, dim, 'absolute', 1, 1000]) + for name in self.assignment.keys(): + self.definitions[ORDER[0]]['lines'].append([name, name, 'absolute', 1, 1000]) return True |