diff options
Diffstat (limited to '')
-rw-r--r-- | src/go/plugin/go.d/modules/hddtemp/collect.go | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/hddtemp/collect.go b/src/go/plugin/go.d/modules/hddtemp/collect.go new file mode 100644 index 000000000..f5c75db04 --- /dev/null +++ b/src/go/plugin/go.d/modules/hddtemp/collect.go @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package hddtemp + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +type diskStats struct { + devPath string + model string + temperature string + unit string +} + +func (h *HddTemp) collect() (map[string]int64, error) { + conn := h.newHddTempConn(h.Config) + + if err := conn.connect(); err != nil { + return nil, err + } + + defer conn.disconnect() + + msg, err := conn.queryHddTemp() + if err != nil { + return nil, err + } + + h.Debugf("hddtemp daemon response: %s", msg) + + disks, err := parseHddTempMessage(msg) + if err != nil { + return nil, err + } + + mx := make(map[string]int64) + + for _, disk := range disks { + id := getDiskID(disk) + if id == "" { + h.Debugf("can not extract disk id from '%s'", disk.devPath) + continue + } + + if !h.disks[id] { + h.disks[id] = true + h.addDiskTempSensorStatusChart(id, disk) + } + + px := fmt.Sprintf("disk_%s_", id) + + for _, st := range []string{"ok", "na", "unk", "nos", "slp", "err"} { + mx[px+"temp_sensor_status_"+st] = 0 + } + switch disk.temperature { + case "NA": + mx[px+"temp_sensor_status_na"] = 1 + case "UNK": + mx[px+"temp_sensor_status_unk"] = 1 + case "NOS": + mx[px+"temp_sensor_status_nos"] = 1 + case "SLP": + mx[px+"temp_sensor_status_slp"] = 1 + case "ERR": + mx[px+"temp_sensor_status_err"] = 1 + default: + if v, ok := getTemperature(disk); ok { + if !h.disksTemp[id] { + h.disksTemp[id] = true + h.addDiskTempChart(id, disk) + } + mx[px+"temp_sensor_status_ok"] = 1 + mx[px+"temperature"] = v + } else { + mx[px+"temp_sensor_status_unk"] = 1 + } + } + } + + return mx, nil +} + +func getDiskID(d diskStats) string { + i := strings.LastIndexByte(d.devPath, '/') + if i == -1 { + return "" + } + return d.devPath[i+1:] +} + +func getTemperature(d diskStats) (int64, bool) { + v, err := strconv.ParseInt(d.temperature, 10, 64) + if err != nil { + return 0, false + } + if d.unit == "F" { + v = (v - 32) * 5 / 9 + } + return v, true +} + +func parseHddTempMessage(msg string) ([]diskStats, error) { + if msg == "" { + return nil, errors.New("empty hddtemp message") + } + + // https://github.com/guzu/hddtemp/blob/e16aed6d0145d7ad8b3308dd0b9199fc701c0417/src/daemon.c#L165 + parts := strings.Split(msg, "|") + + var i int + // remove empty values + for _, v := range parts { + if v = strings.TrimSpace(v); v != "" { + parts[i] = v + i++ + } + } + parts = parts[:i] + + if len(parts) == 0 || len(parts)%4 != 0 { + return nil, errors.New("invalid hddtemp output format") + } + + var disks []diskStats + + for i := 0; i < len(parts); i += 4 { + disks = append(disks, diskStats{ + devPath: parts[i], + model: parts[i+1], + temperature: parts[i+2], + unit: parts[i+3], + }) + } + + return disks, nil +} |