diff --git a/info/machine.go b/info/machine.go index 7c76494b58..54f4dd7a2a 100644 --- a/info/machine.go +++ b/info/machine.go @@ -40,6 +40,9 @@ type MachineInfo struct { // The number of cores in this machine. NumCores int `json:"num_cores"` + // Maximum clock speed for the cores, in KHz. + CpuFrequency uint64 `json:"cpu_frequency_khz"` + // The amount of memory (in bytes) in this machine MemoryCapacity int64 `json:"memory_capacity"` diff --git a/manager/machine.go b/manager/machine.go index 3386dd660a..9e92d12592 100644 --- a/manager/machine.go +++ b/manager/machine.go @@ -27,12 +27,42 @@ import ( "github.com/google/cadvisor/container/docker" "github.com/google/cadvisor/fs" "github.com/google/cadvisor/info" + "github.com/google/cadvisor/utils" "github.com/google/cadvisor/utils/sysfs" ) var numCpuRegexp = regexp.MustCompile("processor\\t*: +[0-9]+") +var CpuClockSpeedMHz = regexp.MustCompile("cpu MHz\\t*: +([0-9]+.[0-9]+)") var memoryCapacityRegexp = regexp.MustCompile("MemTotal: *([0-9]+) kB") +func getClockSpeed(procInfo []byte) (uint64, error) { + // First look through sys to find a max supported cpu frequency. + const maxFreqFile = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" + if utils.FileExists(maxFreqFile) { + val, err := ioutil.ReadFile(maxFreqFile) + if err != nil { + return 0, err + } + var maxFreq uint64 + n, err := fmt.Sscanf(string(val), "%d", &maxFreq) + if err != nil || n != 1 { + return 0, fmt.Errorf("could not parse frequency %q", val) + } + return maxFreq, nil + } + // Fall back to /proc/cpuinfo + matches := CpuClockSpeedMHz.FindSubmatch(procInfo) + if len(matches) != 2 { + return 0, fmt.Errorf("could not detect clock speed from output: %q", string(procInfo)) + } + speed, err := strconv.ParseFloat(string(matches[1]), 64) + if err != nil { + return 0, err + } + // Convert to kHz + return uint64(speed * 1000), nil +} + func getMachineInfo(sysFs sysfs.SysFs) (*info.MachineInfo, error) { // Get the number of CPUs from /proc/cpuinfo. out, err := ioutil.ReadFile("/proc/cpuinfo") @@ -43,6 +73,10 @@ func getMachineInfo(sysFs sysfs.SysFs) (*info.MachineInfo, error) { if numCores == 0 { return nil, fmt.Errorf("failed to count cores in output: %s", string(out)) } + clockSpeed, err := getClockSpeed(out) + if err != nil { + return nil, err + } // Get the amount of usable memory from /proc/meminfo. out, err = ioutil.ReadFile("/proc/meminfo") @@ -77,6 +111,7 @@ func getMachineInfo(sysFs sysfs.SysFs) (*info.MachineInfo, error) { machineInfo := &info.MachineInfo{ NumCores: numCores, + CpuFrequency: clockSpeed, MemoryCapacity: memoryCapacity, DiskMap: diskMap, }