]> arthur.barton.de Git - netdata.git/blob - python.d/cpufreq.chart.py
ab-debian 0.20170311.01-0ab1, upstream v1.5.0-573-g0fba967b
[netdata.git] / python.d / cpufreq.chart.py
1 # -*- coding: utf-8 -*-
2 # Description: cpufreq netdata python.d module
3 # Author: Pawel Krupa (paulfantom) and Steven Noonan (tycho)
4
5 import glob
6 import os
7 import time
8 from base import SimpleService
9
10 # default module values (can be overridden per job in `config`)
11 # update_every = 2
12
13 ORDER = ['cpufreq']
14
15 CHARTS = {
16     'cpufreq': {
17         'options': [None, 'CPU Clock', 'MHz', 'cpufreq', None, 'line'],
18         'lines': [
19             # lines are created dynamically in `check()` method
20         ]}
21 }
22
23 class Service(SimpleService):
24     def __init__(self, configuration=None, name=None):
25         prefix = os.getenv('NETDATA_HOST_PREFIX', "")
26         if prefix.endswith('/'):
27             prefix = prefix[:-1]
28         self.sys_dir = prefix + "/sys/devices"
29         SimpleService.__init__(self, configuration=configuration, name=name)
30         self.order = ORDER
31         self.definitions = CHARTS
32         self._orig_name = ""
33         self.assignment = {}
34         self.accurate_exists = True
35         self.accurate_last = {}
36
37     def _get_data(self):
38         data = {}
39
40         if self.accurate_exists:
41             elapsed = time.time() - self.timetable['last']
42
43             accurate_ok = True
44
45             for name, paths in self.assignment.items():
46                 last = self.accurate_last[name]
47                 current = 0
48                 for line in open(paths['accurate'], 'r'):
49                     line = list(map(int, line.split()))
50                     current += (line[0] * line[1]) / 100
51                 delta = current - last
52                 data[name] = delta
53                 self.accurate_last[name] = current
54                 if delta == 0 or abs(delta) > 1e7:
55                     # Delta is either too large or nonexistent, fall back to
56                     # less accurate reading. This can happen if we switch
57                     # to/from the 'schedutil' governor, which doesn't report
58                     # stats.
59                     accurate_ok = False
60
61             if accurate_ok:
62                 return data
63             else:
64                 self.alert("accurate method failed, falling back")
65
66
67         for name, paths in self.assignment.items():
68             data[name] = open(paths['inaccurate'], 'r').read()
69
70         return data
71
72     def check(self):
73         try:
74             self.sys_dir = str(self.configuration['sys_dir'])
75         except (KeyError, TypeError):
76             self.error("No path specified. Using: '" + self.sys_dir + "'")
77
78         self._orig_name = self.chart_name
79
80         for path in glob.glob(self.sys_dir + '/system/cpu/cpu*/cpufreq/stats/time_in_state'):
81             path_elem = path.split('/')
82             cpu = path_elem[-4]
83             if cpu not in self.assignment:
84                 self.assignment[cpu] = {}
85             self.assignment[cpu]['accurate'] = path
86             self.accurate_last[cpu] = 0
87
88         if len(self.assignment) == 0:
89             self.accurate_exists = False
90
91         for path in glob.glob(self.sys_dir + '/system/cpu/cpu*/cpufreq/scaling_cur_freq'):
92             path_elem = path.split('/')
93             cpu = path_elem[-3]
94             if cpu not in self.assignment:
95                 self.assignment[cpu] = {}
96             self.assignment[cpu]['inaccurate'] = path
97
98         if len(self.assignment) == 0:
99             self.error("couldn't find a method to read cpufreq statistics")
100             return False
101
102         for name in self.assignment.keys():
103             self.definitions[ORDER[0]]['lines'].append([name, name, 'absolute', 1, 1000])
104
105         return True
106
107     def create(self):
108         self.chart_name = "cpu"
109         status = SimpleService.create(self)
110         self.chart_name = self._orig_name
111         return status
112
113     def update(self, interval):
114         self.chart_name = "cpu"
115         status = SimpleService.update(self, interval=interval)
116         self.chart_name = self._orig_name
117         return status