diff --git a/sysfs/system_cpu.go b/sysfs/system_cpu.go index c90f569c4..3ea56d050 100644 --- a/sysfs/system_cpu.go +++ b/sysfs/system_cpu.go @@ -16,7 +16,6 @@ package sysfs import ( - "fmt" "os" "path/filepath" "strings" @@ -26,16 +25,19 @@ import ( // SystemCPUCpufreqStats contains stats from devices/system/cpu/cpu[0-9]*/cpufreq/... type SystemCPUCpufreqStats struct { - Name string - CurrentFrequency uint64 - MinimumFrequency uint64 - MaximumFrequency uint64 - TransitionLatency uint64 - AvailableGovernors string - Driver string - Govenor string - RelatedCpus string - SetSpeed string + Name string + CpuinfoCurrentFrequency *uint64 + CpuinfoMinimumFrequency *uint64 + CpuinfoMaximumFrequency *uint64 + CpuinfoTransitionLatency *uint64 + ScalingCurrentFrequency *uint64 + ScalingMinimumFrequency *uint64 + ScalingMaximumFrequency *uint64 + AvailableGovernors string + Driver string + Govenor string + RelatedCpus string + SetSpeed string } // TODO: Add topology support. @@ -74,14 +76,7 @@ func (fs FS) NewSystemCpufreq() ([]SystemCPUCpufreqStats, error) { return []SystemCPUCpufreqStats{}, err } - if _, err = os.Stat(filepath.Join(cpuCpufreqPath, "scaling_cur_freq")); err == nil { - cpufreq, err = parseCpufreqCpuinfo("scaling", cpuCpufreqPath) - } else if _, err = os.Stat(filepath.Join(cpuCpufreqPath, "cpuinfo_cur_freq")); err == nil { - // Older kernels have metrics named `cpuinfo_...`. - cpufreq, err = parseCpufreqCpuinfo("cpuinfo", cpuCpufreqPath) - } else { - return []SystemCPUCpufreqStats{}, fmt.Errorf("CPU %v is missing cpufreq", cpu) - } + cpufreq, err = parseCpufreqCpuinfo(cpuCpufreqPath) if err != nil { return []SystemCPUCpufreqStats{}, err } @@ -92,22 +87,28 @@ func (fs FS) NewSystemCpufreq() ([]SystemCPUCpufreqStats, error) { return systemCpufreq, nil } -func parseCpufreqCpuinfo(prefix string, cpuPath string) (*SystemCPUCpufreqStats, error) { +func parseCpufreqCpuinfo(cpuPath string) (*SystemCPUCpufreqStats, error) { uintFiles := []string{ - prefix + "_cur_freq", - prefix + "_max_freq", - prefix + "_min_freq", + "cpuinfo_cur_freq", + "cpuinfo_max_freq", + "cpuinfo_min_freq", "cpuinfo_transition_latency", + "scaling_cur_freq", + "scaling_max_freq", + "scaling_min_freq", } - uintOut := make([]uint64, len(uintFiles)) + uintOut := make([]*uint64, len(uintFiles)) for i, f := range uintFiles { v, err := util.ReadUintFromFile(filepath.Join(cpuPath, f)) if err != nil { + if os.IsNotExist(err) || os.IsPermission(err) { + continue + } return &SystemCPUCpufreqStats{}, err } - uintOut[i] = v + uintOut[i] = &v } stringFiles := []string{ @@ -128,14 +129,17 @@ func parseCpufreqCpuinfo(prefix string, cpuPath string) (*SystemCPUCpufreqStats, } return &SystemCPUCpufreqStats{ - CurrentFrequency: uintOut[0], - MaximumFrequency: uintOut[1], - MinimumFrequency: uintOut[2], - TransitionLatency: uintOut[3], - AvailableGovernors: stringOut[0], - Driver: stringOut[1], - Govenor: stringOut[2], - RelatedCpus: stringOut[3], - SetSpeed: stringOut[4], + CpuinfoCurrentFrequency: uintOut[0], + CpuinfoMaximumFrequency: uintOut[1], + CpuinfoMinimumFrequency: uintOut[2], + CpuinfoTransitionLatency: uintOut[3], + ScalingCurrentFrequency: uintOut[4], + ScalingMaximumFrequency: uintOut[5], + ScalingMinimumFrequency: uintOut[6], + AvailableGovernors: stringOut[0], + Driver: stringOut[1], + Govenor: stringOut[2], + RelatedCpus: stringOut[3], + SetSpeed: stringOut[4], }, nil } diff --git a/sysfs/system_cpu_test.go b/sysfs/system_cpu_test.go index 11d447b39..1295ca71a 100644 --- a/sysfs/system_cpu_test.go +++ b/sysfs/system_cpu_test.go @@ -20,6 +20,10 @@ import ( "testing" ) +func makeUint64(v uint64) *uint64 { + return &v +} + func TestNewSystemCpufreq(t *testing.T) { fs, err := NewFS("fixtures") if err != nil { @@ -32,31 +36,37 @@ func TestNewSystemCpufreq(t *testing.T) { } systemCpufreq := []SystemCPUCpufreqStats{ - // Ubuntu 16.04 (4.15.0-20-generic), has `scaling_cur_freq` file. + // Has missing `cpuinfo_cur_freq` file. { - Name: "0", - CurrentFrequency: 1219917, - MinimumFrequency: 800000, - MaximumFrequency: 2400000, - TransitionLatency: 0, - AvailableGovernors: "performance powersave", - Driver: "intel_pstate", - Govenor: "powersave", - RelatedCpus: "0", - SetSpeed: "", + Name: "0", + CpuinfoCurrentFrequency: nil, + CpuinfoMinimumFrequency: makeUint64(800000), + CpuinfoMaximumFrequency: makeUint64(2400000), + CpuinfoTransitionLatency: makeUint64(0), + ScalingCurrentFrequency: makeUint64(1219917), + ScalingMinimumFrequency: makeUint64(800000), + ScalingMaximumFrequency: makeUint64(2400000), + AvailableGovernors: "performance powersave", + Driver: "intel_pstate", + Govenor: "powersave", + RelatedCpus: "0", + SetSpeed: "", }, - // RHEL 7.3 (3.10.0-514.26.2.el7), missing `scaling_cur_freq` file. + // Has missing `scaling_cur_freq` file. { - Name: "1", - CurrentFrequency: 1200195, - MinimumFrequency: 1200000, - MaximumFrequency: 3300000, - TransitionLatency: 4294967295, - AvailableGovernors: "performance powersave", - Driver: "intel_pstate", - Govenor: "powersave", - RelatedCpus: "1", - SetSpeed: "", + Name: "1", + CpuinfoCurrentFrequency: makeUint64(1200195), + CpuinfoMinimumFrequency: makeUint64(1200000), + CpuinfoMaximumFrequency: makeUint64(3300000), + CpuinfoTransitionLatency: makeUint64(4294967295), + ScalingCurrentFrequency: nil, + ScalingMinimumFrequency: makeUint64(1200000), + ScalingMaximumFrequency: makeUint64(3300000), + AvailableGovernors: "performance powersave", + Driver: "intel_pstate", + Govenor: "powersave", + RelatedCpus: "1", + SetSpeed: "", }, }