Skip to content

Commit 4cbddac

Browse files
committed
[sensors][linux]: add ExLinux on sensors.
This commit references and fixes #1589. Thank you!
1 parent d235f41 commit 4cbddac

File tree

2 files changed

+111
-22
lines changed

2 files changed

+111
-22
lines changed

sensors/ex_linux.go

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//go:build linux
3+
4+
package sensors
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"os"
10+
"path/filepath"
11+
"strings"
12+
)
13+
14+
// ExTemperature represents Linux dependent temperature sensor data
15+
type ExTemperature struct {
16+
SensorKey string `json:"key"`
17+
Min float64 `json:"min"` // Temperature min value.
18+
Lowest float64 `json:"lowest"` // Historical minimum temperature
19+
Highest float64 `json:"highest"` // Historical maximum temperature
20+
}
21+
22+
type ExLinux struct{}
23+
24+
func NewExLinux() *ExLinux {
25+
return &ExLinux{}
26+
}
27+
28+
func (ex *ExLinux) TemperatureWithContext(ctx context.Context) ([]ExTemperature, error) {
29+
var warns Warnings
30+
31+
files, err := getTemperatureFiles(ctx)
32+
if err != nil {
33+
return nil, fmt.Errorf("failed to get temperature files, %w", err)
34+
}
35+
36+
temperatures := make([]ExTemperature, 0, len(files))
37+
for _, file := range files {
38+
var raw []byte
39+
40+
// Get the base directory location
41+
directory := filepath.Dir(file)
42+
43+
// Get the base filename prefix like temp1
44+
basename := strings.Split(filepath.Base(file), "_")[0]
45+
46+
// Get the base path like <dir>/temp1
47+
basepath := filepath.Join(directory, basename)
48+
49+
// Get the label of the temperature you are reading
50+
label := ""
51+
52+
if raw, _ = os.ReadFile(basepath + "_label"); len(raw) != 0 {
53+
// Format the label from "Core 0" to "core_0"
54+
label = strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(raw))), " "), "_")
55+
}
56+
57+
// Get the name of the temperature you are reading
58+
if raw, err = os.ReadFile(filepath.Join(directory, "name")); err != nil {
59+
warns.Add(err)
60+
continue
61+
}
62+
63+
name := strings.TrimSpace(string(raw))
64+
65+
if label != "" {
66+
name = name + "_" + label
67+
}
68+
69+
// Add discovered temperature sensor to the list
70+
temperatures = append(temperatures, ExTemperature{
71+
SensorKey: name,
72+
Min: optionalValueReadFromFile(basepath+"_min") / hostTemperatureScale,
73+
Lowest: optionalValueReadFromFile(basepath+"_lowest") / hostTemperatureScale,
74+
Highest: optionalValueReadFromFile(basepath+"_highest") / hostTemperatureScale,
75+
})
76+
}
77+
78+
return temperatures, warns.Reference()
79+
}

sensors/sensors_linux.go

+32-22
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package sensors
55

66
import (
77
"context"
8+
"fmt"
89
"os"
910
"path/filepath"
1011
"strconv"
@@ -19,34 +20,20 @@ const (
1920
)
2021

2122
func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
22-
var err error
23-
24-
var files []string
25-
26-
temperatures := make([]TemperatureStat, 0)
27-
28-
// Only the temp*_input file provides current temperature
29-
// value in millidegree Celsius as reported by the temperature to the device:
30-
// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
31-
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/temp*_input")); err != nil {
32-
return temperatures, err
33-
}
23+
var warns Warnings
3424

35-
if len(files) == 0 {
36-
// CentOS has an intermediate /device directory:
37-
// https://github.com/giampaolo/psutil/issues/971
38-
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/device/temp*_input")); err != nil {
39-
return temperatures, err
40-
}
25+
files, err := getTemperatureFiles(ctx)
26+
if err != nil {
27+
return nil, fmt.Errorf("failed to get tempreteure files, %w", err)
4128
}
4229

43-
var warns Warnings
44-
4530
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
4631
files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/thermal/thermal_zone*/"))
4732
if err != nil {
48-
return temperatures, err
33+
return nil, err
4934
}
35+
temperatures := make([]TemperatureStat, 0, len(files))
36+
5037
for _, file := range files {
5138
// Get the name of the temperature you are reading
5239
name, err := os.ReadFile(filepath.Join(file, "type"))
@@ -74,7 +61,7 @@ func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
7461
return temperatures, warns.Reference()
7562
}
7663

77-
temperatures = make([]TemperatureStat, 0, len(files))
64+
temperatures := make([]TemperatureStat, 0, len(files))
7865

7966
// example directory
8067
// device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm
@@ -139,6 +126,29 @@ func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
139126
return temperatures, warns.Reference()
140127
}
141128

129+
func getTemperatureFiles(ctx context.Context) ([]string, error) {
130+
var files []string
131+
var err error
132+
133+
// Only the temp*_input file provides current temperature
134+
// value in millidegree Celsius as reported by the temperature to the device:
135+
// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
136+
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/temp*_input")); err != nil {
137+
return nil, err
138+
}
139+
140+
if len(files) == 0 {
141+
// CentOS has an intermediate /device directory:
142+
// https://github.com/giampaolo/psutil/issues/971
143+
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/device/temp*_input")); err != nil {
144+
return nil, err
145+
}
146+
}
147+
148+
return files, nil
149+
150+
}
151+
142152
func optionalValueReadFromFile(filename string) float64 {
143153
var raw []byte
144154

0 commit comments

Comments
 (0)