1// Copyright 2019 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package procfs 15 16import ( 17 "bufio" 18 "bytes" 19 "io/ioutil" 20 "strconv" 21 "strings" 22) 23 24// CPUInfo contains general information about a system CPU found in /proc/cpuinfo 25type CPUInfo struct { 26 Processor uint 27 VendorID string 28 CPUFamily string 29 Model string 30 ModelName string 31 Stepping string 32 Microcode string 33 CPUMHz float64 34 CacheSize string 35 PhysicalID string 36 Siblings uint 37 CoreID string 38 CPUCores uint 39 APICID string 40 InitialAPICID string 41 FPU string 42 FPUException string 43 CPUIDLevel uint 44 WP string 45 Flags []string 46 Bugs []string 47 BogoMips float64 48 CLFlushSize uint 49 CacheAlignment uint 50 AddressSizes string 51 PowerManagement string 52} 53 54// CPUInfo returns information about current system CPUs. 55// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt 56func (fs FS) CPUInfo() ([]CPUInfo, error) { 57 data, err := ioutil.ReadFile(fs.proc.Path("cpuinfo")) 58 if err != nil { 59 return nil, err 60 } 61 return parseCPUInfo(data) 62} 63 64// parseCPUInfo parses data from /proc/cpuinfo 65func parseCPUInfo(info []byte) ([]CPUInfo, error) { 66 cpuinfo := []CPUInfo{} 67 i := -1 68 scanner := bufio.NewScanner(bytes.NewReader(info)) 69 for scanner.Scan() { 70 line := scanner.Text() 71 if strings.TrimSpace(line) == "" { 72 continue 73 } 74 field := strings.SplitN(line, ": ", 2) 75 switch strings.TrimSpace(field[0]) { 76 case "processor": 77 cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor 78 i++ 79 v, err := strconv.ParseUint(field[1], 0, 32) 80 if err != nil { 81 return nil, err 82 } 83 cpuinfo[i].Processor = uint(v) 84 case "vendor_id": 85 cpuinfo[i].VendorID = field[1] 86 case "cpu family": 87 cpuinfo[i].CPUFamily = field[1] 88 case "model": 89 cpuinfo[i].Model = field[1] 90 case "model name": 91 cpuinfo[i].ModelName = field[1] 92 case "stepping": 93 cpuinfo[i].Stepping = field[1] 94 case "microcode": 95 cpuinfo[i].Microcode = field[1] 96 case "cpu MHz": 97 v, err := strconv.ParseFloat(field[1], 64) 98 if err != nil { 99 return nil, err 100 } 101 cpuinfo[i].CPUMHz = v 102 case "cache size": 103 cpuinfo[i].CacheSize = field[1] 104 case "physical id": 105 cpuinfo[i].PhysicalID = field[1] 106 case "siblings": 107 v, err := strconv.ParseUint(field[1], 0, 32) 108 if err != nil { 109 return nil, err 110 } 111 cpuinfo[i].Siblings = uint(v) 112 case "core id": 113 cpuinfo[i].CoreID = field[1] 114 case "cpu cores": 115 v, err := strconv.ParseUint(field[1], 0, 32) 116 if err != nil { 117 return nil, err 118 } 119 cpuinfo[i].CPUCores = uint(v) 120 case "apicid": 121 cpuinfo[i].APICID = field[1] 122 case "initial apicid": 123 cpuinfo[i].InitialAPICID = field[1] 124 case "fpu": 125 cpuinfo[i].FPU = field[1] 126 case "fpu_exception": 127 cpuinfo[i].FPUException = field[1] 128 case "cpuid level": 129 v, err := strconv.ParseUint(field[1], 0, 32) 130 if err != nil { 131 return nil, err 132 } 133 cpuinfo[i].CPUIDLevel = uint(v) 134 case "wp": 135 cpuinfo[i].WP = field[1] 136 case "flags": 137 cpuinfo[i].Flags = strings.Fields(field[1]) 138 case "bugs": 139 cpuinfo[i].Bugs = strings.Fields(field[1]) 140 case "bogomips": 141 v, err := strconv.ParseFloat(field[1], 64) 142 if err != nil { 143 return nil, err 144 } 145 cpuinfo[i].BogoMips = v 146 case "clflush size": 147 v, err := strconv.ParseUint(field[1], 0, 32) 148 if err != nil { 149 return nil, err 150 } 151 cpuinfo[i].CLFlushSize = uint(v) 152 case "cache_alignment": 153 v, err := strconv.ParseUint(field[1], 0, 32) 154 if err != nil { 155 return nil, err 156 } 157 cpuinfo[i].CacheAlignment = uint(v) 158 case "address sizes": 159 cpuinfo[i].AddressSizes = field[1] 160 case "power management": 161 cpuinfo[i].PowerManagement = field[1] 162 } 163 } 164 return cpuinfo, nil 165 166} 167