parseStat parses the metrics from /proc/[pid]/stat.
(r io.Reader, fileName string)
| 180 | |
| 181 | // parseStat parses the metrics from /proc/[pid]/stat. |
| 182 | func parseStat(r io.Reader, fileName string) (Stat, error) { |
| 183 | var ( |
| 184 | scanner = bufio.NewScanner(r) |
| 185 | stat = Stat{ |
| 186 | CPU: make(map[int64]CPUStat), |
| 187 | } |
| 188 | err error |
| 189 | ) |
| 190 | |
| 191 | // Increase default scanner buffer to handle very long `intr` lines. |
| 192 | buf := make([]byte, 0, 8*1024) |
| 193 | scanner.Buffer(buf, 1024*1024) |
| 194 | |
| 195 | for scanner.Scan() { |
| 196 | line := scanner.Text() |
| 197 | parts := strings.Fields(scanner.Text()) |
| 198 | // require at least <key> <value> |
| 199 | if len(parts) < 2 { |
| 200 | continue |
| 201 | } |
| 202 | switch { |
| 203 | case parts[0] == "btime": |
| 204 | if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil { |
| 205 | return Stat{}, fmt.Errorf("%w: couldn't parse %q (btime): %w", ErrFileParse, parts[1], err) |
| 206 | } |
| 207 | case parts[0] == "intr": |
| 208 | if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil { |
| 209 | return Stat{}, fmt.Errorf("%w: couldn't parse %q (intr): %w", ErrFileParse, parts[1], err) |
| 210 | } |
| 211 | numberedIRQs := parts[2:] |
| 212 | stat.IRQ = make([]uint64, len(numberedIRQs)) |
| 213 | for i, count := range numberedIRQs { |
| 214 | if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil { |
| 215 | return Stat{}, fmt.Errorf("%w: couldn't parse %q (intr%d): %w", ErrFileParse, count, i, err) |
| 216 | } |
| 217 | } |
| 218 | case parts[0] == "ctxt": |
| 219 | if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil { |
| 220 | return Stat{}, fmt.Errorf("%w: couldn't parse %q (ctxt): %w", ErrFileParse, parts[1], err) |
| 221 | } |
| 222 | case parts[0] == "processes": |
| 223 | if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil { |
| 224 | return Stat{}, fmt.Errorf("%w: couldn't parse %q (processes): %w", ErrFileParse, parts[1], err) |
| 225 | } |
| 226 | case parts[0] == "procs_running": |
| 227 | if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil { |
| 228 | return Stat{}, fmt.Errorf("%w: couldn't parse %q (procs_running): %w", ErrFileParse, parts[1], err) |
| 229 | } |
| 230 | case parts[0] == "procs_blocked": |
| 231 | if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil { |
| 232 | return Stat{}, fmt.Errorf("%w: couldn't parse %q (procs_blocked): %w", ErrFileParse, parts[1], err) |
| 233 | } |
| 234 | case parts[0] == "softirq": |
| 235 | softIRQStats, total, err := parseSoftIRQStat(line) |
| 236 | if err != nil { |
| 237 | return Stat{}, err |
| 238 | } |
| 239 | stat.SoftIRQTotal = total |
no test coverage detected
searching dependent graphs…