summaryrefslogtreecommitdiffstats
path: root/python.d/cpufreq.chart.py
diff options
context:
space:
mode:
Diffstat (limited to 'python.d/cpufreq.chart.py')
-rw-r--r--python.d/cpufreq.chart.py83
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