feat(python.d/sensors): discover chips, features at runtime (#13545)
Ilya Mashchenko committed
Aug 23, 2022 at 13:15 UTC
711e6fc5e75eb12455054116eea159b8ac83d7a9
1 file changed
+70
-53
collectors/python.d.plugin/sensors/sensors.chart.py
+70
-53
@@ -3,6 +3,8 @@
3
# Author: Pawel Krupa (paulfantom)
4
# SPDX-License-Identifier: GPL-3.0-or-later
5
6
+from collections import defaultdict
7
+
8
from bases.FrameworkServices.SimpleService import SimpleService
9
from third_party import lm_sensors as sensors
10
@@ -77,11 +79,11 @@ TYPE_MAP = {
79
4: 'energy',
80
5: 'current',
81
6: 'humidity',
80
- 7: 'max_main',
81
- 16: 'vid',
82
- 17: 'intrusion',
83
- 18: 'max_other',
84
- 24: 'beep_enable'
82
+ # 7: 'max_main',
83
+ # 16: 'vid',
84
+ # 17: 'intrusion',
85
+ # 18: 'max_other',
86
+ # 24: 'beep_enable'
87
}
88
89
@@ -91,64 +93,73 @@ class Service(SimpleService):
93
self.order = list()
94
self.definitions = dict()
95
self.chips = configuration.get('chips')
96
+ self.priority = 60000
97
98
def get_data(self):
96
- data = dict()
99
+ seen, data = dict(), dict()
100
try:
101
for chip in sensors.ChipIterator():
99
- prefix = sensors.chip_snprintf_name(chip)
100
- for feature in sensors.FeatureIterator(chip):
101
- sfi = sensors.SubFeatureIterator(chip, feature)
102
- val = None
103
- for sf in sfi:
104
- try:
105
- val = sensors.get_value(chip, sf.number)
106
- break
107
- except sensors.SensorsError:
108
- continue
109
- if val is None:
102
+ chip_name = sensors.chip_snprintf_name(chip)
103
+ seen[chip_name] = defaultdict(list)
104
+
105
+ for feat in sensors.FeatureIterator(chip):
106
+ if feat.type not in TYPE_MAP:
107
+ continue
108
+
109
+ feat_type = TYPE_MAP[feat.type]
110
+ feat_name = str(feat.name.decode())
111
+ feat_label = sensors.get_label(chip, feat)
112
+ feat_limits = LIMITS.get(feat_type)
113
+ sub_feat = next(sensors.SubFeatureIterator(chip, feat)) # current value
114
+
115
+ if not sub_feat:
116
+ continue
117
+
118
+ try:
119
+ v = sensors.get_value(chip, sub_feat.number)
120
+ except sensors.SensorsError:
121
+ continue
122
+
123
+ if v is None:
124
+ continue
125
+
126
+ seen[chip_name][feat_type].append((feat_name, feat_label))
127
+
128
+ if feat_limits and (v < feat_limits[0] or v > feat_limits[1]):
129
continue
111
- type_name = TYPE_MAP[feature.type]
112
- if type_name in LIMITS:
113
- limit = LIMITS[type_name]
114
- if val < limit[0] or val > limit[1]:
115
- continue
116
- data[prefix + '_' + str(feature.name.decode())] = int(val * 1000)
130
+
131
+ data[chip_name + '_' + feat_name] = int(v * 1000)
132
+
133
except sensors.SensorsError as error:
134
self.error(error)
135
return None
136
137
+ self.update_sensors_charts(seen)
138
+
139
return data or None
140
123
- def create_definitions(self):
124
- for sensor in ORDER:
125
- for chip in sensors.ChipIterator():
126
- chip_name = sensors.chip_snprintf_name(chip)
127
- if self.chips and not any([chip_name.startswith(ex) for ex in self.chips]):
141
+ def update_sensors_charts(self, seen):
142
+ for chip_name, feat in seen.items():
143
+ if self.chips and not any([chip_name.startswith(ex) for ex in self.chips]):
144
+ continue
145
+
146
+ for feat_type, sub_feat in feat.items():
147
+ if feat_type not in ORDER or feat_type not in CHARTS:
148
+ continue
149
+
150
+ chart_id = '{}_{}'.format(chip_name, feat_type)
151
+ if chart_id in self.charts:
152
continue
129
- for feature in sensors.FeatureIterator(chip):
130
- sfi = sensors.SubFeatureIterator(chip, feature)
131
- vals = list()
132
- for sf in sfi:
133
- try:
134
- vals.append(sensors.get_value(chip, sf.number))
135
- except sensors.SensorsError as error:
136
- self.error('{0}: {1}'.format(sf.name, error))
137
- continue
138
- if not vals or (vals[0] == 0 and feature.type != 1):
139
- continue
140
- if TYPE_MAP[feature.type] == sensor:
141
- # create chart
142
- name = chip_name + '_' + TYPE_MAP[feature.type]
143
- if name not in self.order:
144
- self.order.append(name)
145
- chart_def = list(CHARTS[sensor]['options'])
146
- self.definitions[name] = {'options': chart_def}
147
- self.definitions[name]['lines'] = []
148
- line = list(CHARTS[sensor]['lines'][0])
149
- line[0] = chip_name + '_' + str(feature.name.decode())
150
- line[1] = sensors.get_label(chip, feature)
151
- self.definitions[name]['lines'].append(line)
153
+
154
+ params = [chart_id] + list(CHARTS[feat_type]['options'])
155
+ new_chart = self.charts.add_chart(params)
156
+ new_chart.params['priority'] = self.get_chart_priority(feat_type)
157
+
158
+ for name, label in sub_feat:
159
+ lines = list(CHARTS[feat_type]['lines'][0])
160
+ lines[0] = chip_name + '_' + name
161
+ lines[1] = label
162
+ new_chart.add_dimension(lines)
163
164
def check(self):
165
try:
@@ -157,6 +168,12 @@ class Service(SimpleService):
168
self.error(error)
169
return False
170
160
- self.create_definitions()
171
+ self.priority = self.charts.priority
172
+
173
+ return bool(self.get_data() and self.charts)
174
162
- return bool(self.get_data())
175
+ def get_chart_priority(self, feat_type):
176
+ for i, v in enumerate(ORDER):
177
+ if v == feat_type:
178
+ return self.priority + i
179
+ return self.priority