go.d smartctl improve units (#17564)
Ilya Mashchenko committed
May 1, 2024 at 00:20 UTC
cdd89c9e4bb89e0bbb578ccfc61262c7574d6f97
1 file changed
+60
-11
src/go/collectors/go.d.plugin/modules/smartctl/charts.go
+60
-11
@@ -193,7 +193,9 @@ func (s *Smartctl) newDeviceSmartAttrCharts(dev *smartDevice) *module.Charts {
193
charts := module.Charts{}
194
195
for _, attr := range attrs {
196
- if !isSmartAttrValid(attr) || strings.HasPrefix(attr.name(), "Unknown") {
196
+ if !isSmartAttrValid(attr) ||
197
+ strings.HasPrefix(attr.name(), "Unknown") ||
198
+ strings.HasPrefix(attr.name(), "Not_In_Use") {
199
continue
200
}
201
@@ -202,14 +204,17 @@ func (s *Smartctl) newDeviceSmartAttrCharts(dev *smartDevice) *module.Charts {
204
deviceSmartAttributeNormalizedChartTmpl.Copy(),
205
}
206
205
- name := cleanAttributeName(attr)
207
+ attrName := attributeNameMap(attr.name())
208
+ cleanAttrName := cleanAttributeName(attrName)
209
207
- // FIXME: attribute charts unit
210
for _, chart := range cs {
209
- chart.ID = fmt.Sprintf(chart.ID, dev.deviceName(), dev.deviceType(), name)
210
- chart.Title = fmt.Sprintf(chart.Title, attr.name())
211
- chart.Fam = fmt.Sprintf(chart.Fam, name)
212
- chart.Ctx = fmt.Sprintf(chart.Ctx, name)
211
+ if chart.ID == deviceSmartAttributeDecodedChartTmpl.ID {
212
+ chart.Units = attributeUnit(attrName)
213
+ }
214
+ chart.ID = fmt.Sprintf(chart.ID, dev.deviceName(), dev.deviceType(), cleanAttrName)
215
+ chart.Title = fmt.Sprintf(chart.Title, attrName)
216
+ chart.Fam = fmt.Sprintf(chart.Fam, cleanAttrName)
217
+ chart.Ctx = fmt.Sprintf(chart.Ctx, cleanAttrName)
218
chart.Labels = []module.Label{
219
{Key: "device_name", Value: dev.deviceName()},
220
{Key: "device_type", Value: dev.deviceType()},
@@ -217,8 +222,8 @@ func (s *Smartctl) newDeviceSmartAttrCharts(dev *smartDevice) *module.Charts {
222
{Key: "serial_number", Value: dev.serialNumber()},
223
}
224
for _, dim := range chart.Dims {
220
- dim.ID = fmt.Sprintf(dim.ID, dev.deviceName(), dev.deviceType(), name)
221
- dim.Name = fmt.Sprintf(dim.Name, name)
225
+ dim.ID = fmt.Sprintf(dim.ID, dev.deviceName(), dev.deviceType(), cleanAttrName)
226
+ dim.Name = fmt.Sprintf(dim.Name, cleanAttrName)
227
}
228
}
229
@@ -232,6 +237,50 @@ func (s *Smartctl) newDeviceSmartAttrCharts(dev *smartDevice) *module.Charts {
237
238
var attrNameReplacer = strings.NewReplacer(" ", "_", "/", "_")
239
235
-func cleanAttributeName(attr *smartAttribute) string {
236
- return strings.ToLower(attrNameReplacer.Replace(attr.name()))
240
+func cleanAttributeName(attrName string) string {
241
+ return strings.ToLower(attrNameReplacer.Replace(attrName))
242
+}
243
+
244
+func attributeUnit(attrName string) string {
245
+ units := map[string]string{
246
+ "Airflow_Temperature_Cel": "Celsius",
247
+ "Case_Temperature": "Celsius",
248
+ "Drive_Temperature": "Celsius",
249
+ "Temperature_Case": "Celsius",
250
+ "Temperature_Celsius": "Celsius",
251
+ "Temperature_Internal": "Celsius",
252
+ "Power_On_Hours": "hours",
253
+ "Spin_Up_Time": "milliseconds",
254
+ "Media_Wearout_Indicator": "percent",
255
+ "Percent_Life_Remaining": "percent",
256
+ "Percent_Lifetime_Remain": "percent",
257
+ "Total_LBAs_Read": "sectors",
258
+ "Total_LBAs_Written": "sectors",
259
+ "Offline_Uncorrectable": "sectors",
260
+ "Pending_Sector_Count": "sectors",
261
+ "Reallocated_Sector_Ct": "sectors",
262
+ }
263
+
264
+ if unit, ok := units[attrName]; ok {
265
+ return unit
266
+ }
267
+
268
+ if strings.Contains(attrName, "Error") {
269
+ return "errors"
270
+ }
271
+
272
+ for _, s := range []string{"_Count", "_Cnt", "_Ct"} {
273
+ if strings.HasSuffix(attrName, s) {
274
+ return "events"
275
+ }
276
+ }
277
+
278
+ return "value"
279
+}
280
+
281
+func attributeNameMap(attrName string) string {
282
+ // TODO: Handle Vendor-Specific S.M.A.R.T. Attribute Naming
283
+ // S.M.A.R.T. attribute names can vary slightly between vendors (e.g., "Thermal_Throttle_St" vs. "Thermal_Throttle_Status").
284
+ // This function ensures consistent naming.
285
+ return attrName
286
}