X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=python.d%2Fcpufreq.chart.py;h=e28bdea8f6abeba09752edda468075cebca779d4;hb=8679670bdbe3c5928ec2e266d9c72e1a758fdf37;hp=600786bfeeefd85454fb80b5e90db03041d604ae;hpb=4d80b11402bc0a4d2e8c56086fde6e27d6d6516a;p=netdata.git diff --git a/python.d/cpufreq.chart.py b/python.d/cpufreq.chart.py index 600786bf..e28bdea8 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,26 +20,54 @@ CHARTS = { ]} } - class Service(SimpleService): def __init__(self, configuration=None, name=None): - self.sys_dir = "/sys/devices" - self.filename = "scaling_cur_freq" + prefix = os.getenv('NETDATA_HOST_PREFIX', "") + if prefix.endswith('/'): + prefix = prefix[:-1] + self.sys_dir = prefix + "/sys/devices" 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") + self.accurate_exists = False + + + for name, paths in self.assignment.items(): + data[name] = open(paths['inaccurate'], 'r').read() + return data def check(self): @@ -48,23 +78,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