]> arthur.barton.de Git - netdata.git/blob - python.d/cpufreq.chart.py
Merge branch 'master' into ab-debian
[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                 self.accurate_exists = False
66
67
68         for name, paths in self.assignment.items():
69             data[name] = open(paths['inaccurate'], 'r').read()
70
71         return data
72
73     def check(self):
74         try:
75             self.sys_dir = str(self.configuration['sys_dir'])
76         except (KeyError, TypeError):
77             self.error("No path specified. Using: '" + self.sys_dir + "'")
78
79         self._orig_name = self.chart_name
80
81         for path in glob.glob(self.sys_dir + '/system/cpu/cpu*/cpufreq/stats/time_in_state'):
82             path_elem = path.split('/')
83             cpu = path_elem[-4]
84             if cpu not in self.assignment:
85                 self.assignment[cpu] = {}
86             self.assignment[cpu]['accurate'] = path
87             self.accurate_last[cpu] = 0
88
89         if len(self.assignment) == 0:
90             self.accurate_exists = False
91
92         for path in glob.glob(self.sys_dir + '/system/cpu/cpu*/cpufreq/scaling_cur_freq'):
93             path_elem = path.split('/')
94             cpu = path_elem[-3]
95             if cpu not in self.assignment:
96                 self.assignment[cpu] = {}
97             self.assignment[cpu]['inaccurate'] = path
98
99         if len(self.assignment) == 0:
100             self.error("couldn't find a method to read cpufreq statistics")
101             return False
102
103         for name in self.assignment.keys():
104             self.definitions[ORDER[0]]['lines'].append([name, name, 'absolute', 1, 1000])
105
106         return True
107
108     def create(self):
109         self.chart_name = "cpu"
110         status = SimpleService.create(self)
111         self.chart_name = self._orig_name
112         return status
113
114     def update(self, interval):
115         self.chart_name = "cpu"
116         status = SimpleService.update(self, interval=interval)
117         self.chart_name = self._orig_name
118         return status