Skip to content

Commit 9e14bc2

Browse files
committed
extend self-test log processing
Signed-off-by: Aritas1 <[email protected]>
1 parent 75c76b3 commit 9e14bc2

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

Diff for: metrics.go

+11
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,17 @@ var (
242242
},
243243
nil,
244244
)
245+
metricDeviceSelfTest = prometheus.NewDesc(
246+
"smartctl_device_self_test_log_seconds",
247+
"Device SMART self test log execution lifetime seconds",
248+
[]string{
249+
"device",
250+
"self_test_log_type",
251+
"self_test_passed",
252+
},
253+
nil,
254+
)
255+
245256
metricDeviceSelfTestLogCount = prometheus.NewDesc(
246257
"smartctl_device_self_test_log_count",
247258
"Device SMART self test log count",

Diff for: readjson.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func readFakeSMARTctl(logger log.Logger, device string) gjson.Result {
6464
// Get json from smartctl and parse it
6565
func readSMARTctl(logger log.Logger, device string) (gjson.Result, bool) {
6666
level.Debug(logger).Log("msg", "Collecting S.M.A.R.T. counters", "device", device)
67-
out, err := exec.Command(*smartctlPath, "--json", "--info", "--health", "--attributes", "--tolerance=verypermissive", "--nocheck=standby", "--format=brief", "--log=error", device).Output()
67+
out, err := exec.Command(*smartctlPath, "--json", "--info", "--health", "--attributes", "--tolerance=verypermissive", "--nocheck=standby", "--format=brief", "--log=error", "--log=selftest", device).Output()
6868
if err != nil {
6969
level.Warn(logger).Log("msg", "S.M.A.R.T. output reading", "err", err, "device", device)
7070
}

Diff for: smartctl.go

+46
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package main
1515

1616
import (
1717
"fmt"
18+
"strconv"
1819
"strings"
1920

2021
"github.com/go-kit/log"
@@ -69,6 +70,7 @@ func (smart *SMARTctl) Collect() {
6970
smart.mineDeviceSCTStatus()
7071
smart.mineDeviceStatistics()
7172
smart.mineDeviceErrorLog()
73+
smart.mineDeviceSelfTest()
7274
smart.mineDeviceSelfTestLog()
7375
smart.mineDeviceERC()
7476
smart.minePercentageUsed()
@@ -399,6 +401,50 @@ func (smart *SMARTctl) mineDeviceErrorLog() {
399401
}
400402
}
401403

404+
func (smart *SMARTctl) mineDeviceSelfTest() {
405+
validTypes := map[int]string{
406+
255: "vendor",
407+
129: "short_captive",
408+
2: "long",
409+
1: "short",
410+
}
411+
412+
// assume the table will always be in descending order
413+
processedTypes := make(map[string]bool)
414+
415+
for _, logEntry := range smart.json.Get("ata_smart_self_test_log.standard.table").Array() {
416+
testType := int(logEntry.Get("type.value").Int())
417+
testTime := float64(logEntry.Get("lifetime_hours").Int())
418+
testRunningIndicator := int(logEntry.Get("status.value").Int())
419+
testStatus := strconv.FormatBool(logEntry.Get("status.passed").Bool())
420+
421+
// stick with seconds
422+
testTime = testTime * 60 * 60
423+
424+
// skip running tests
425+
if testRunningIndicator != 0 {
426+
continue
427+
}
428+
429+
logTestType, exists := validTypes[testType]
430+
if !exists {
431+
logTestType = "unknown"
432+
}
433+
434+
if !processedTypes[logTestType] {
435+
smart.ch <- prometheus.MustNewConstMetric(
436+
metricDeviceSelfTest,
437+
prometheus.GaugeValue,
438+
testTime,
439+
smart.device.device,
440+
logTestType,
441+
testStatus,
442+
)
443+
processedTypes[logTestType] = true
444+
}
445+
}
446+
}
447+
402448
func (smart *SMARTctl) mineDeviceSelfTestLog() {
403449
for logType, status := range smart.json.Get("ata_smart_self_test_log").Map() {
404450
smart.ch <- prometheus.MustNewConstMetric(

0 commit comments

Comments
 (0)