@cryptotaxi247 / netdata-1 / commits / 711e6fc5e

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