Skip to content

Commit 18ac0a2

Browse files
committed
parse cpu with ID in /proc/stat
Signed-off-by: Jia Xin <[email protected]>
1 parent 5f46783 commit 18ac0a2

File tree

1 file changed

+21
-18
lines changed

1 file changed

+21
-18
lines changed

stat.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ type Stat struct {
6262
// Summed up cpu statistics.
6363
CPUTotal CPUStat
6464
// Per-CPU statistics.
65-
CPU []CPUStat
65+
CPU map[int64]*CPUStat
6666
// Number of times interrupts were handled, which contains numbered and unnumbered IRQs.
6767
IRQTotal uint64
6868
// Number of times a numbered IRQ was triggered.
@@ -142,14 +142,20 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) {
142142
return softIRQStat, total, nil
143143
}
144144

145+
func newStat() Stat {
146+
return Stat{
147+
CPU: make(map[int64]*CPUStat),
148+
}
149+
}
150+
145151
// NewStat returns information about current cpu/process statistics.
146152
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
147153
//
148154
// Deprecated: Use fs.Stat() instead.
149155
func NewStat() (Stat, error) {
150156
fs, err := NewFS(fs.DefaultProcMountPoint)
151157
if err != nil {
152-
return Stat{}, err
158+
return newStat(), err
153159
}
154160
return fs.Stat()
155161
}
@@ -168,10 +174,10 @@ func (fs FS) Stat() (Stat, error) {
168174
fileName := fs.proc.Path("stat")
169175
data, err := util.ReadFileNoStat(fileName)
170176
if err != nil {
171-
return Stat{}, err
177+
return newStat(), err
172178
}
173179

174-
stat := Stat{}
180+
stat := newStat()
175181

176182
scanner := bufio.NewScanner(bytes.NewReader(data))
177183
for scanner.Scan() {
@@ -184,60 +190,57 @@ func (fs FS) Stat() (Stat, error) {
184190
switch {
185191
case parts[0] == "btime":
186192
if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
187-
return Stat{}, fmt.Errorf("couldn't parse %q (btime): %w", parts[1], err)
193+
return newStat(), fmt.Errorf("couldn't parse %q (btime): %w", parts[1], err)
188194
}
189195
case parts[0] == "intr":
190196
if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
191-
return Stat{}, fmt.Errorf("couldn't parse %q (intr): %w", parts[1], err)
197+
return newStat(), fmt.Errorf("couldn't parse %q (intr): %w", parts[1], err)
192198
}
193199
numberedIRQs := parts[2:]
194200
stat.IRQ = make([]uint64, len(numberedIRQs))
195201
for i, count := range numberedIRQs {
196202
if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil {
197-
return Stat{}, fmt.Errorf("couldn't parse %q (intr%d): %w", count, i, err)
203+
return newStat(), fmt.Errorf("couldn't parse %q (intr%d): %w", count, i, err)
198204
}
199205
}
200206
case parts[0] == "ctxt":
201207
if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
202-
return Stat{}, fmt.Errorf("couldn't parse %q (ctxt): %w", parts[1], err)
208+
return newStat(), fmt.Errorf("couldn't parse %q (ctxt): %w", parts[1], err)
203209
}
204210
case parts[0] == "processes":
205211
if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
206-
return Stat{}, fmt.Errorf("couldn't parse %q (processes): %w", parts[1], err)
212+
return newStat(), fmt.Errorf("couldn't parse %q (processes): %w", parts[1], err)
207213
}
208214
case parts[0] == "procs_running":
209215
if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
210-
return Stat{}, fmt.Errorf("couldn't parse %q (procs_running): %w", parts[1], err)
216+
return newStat(), fmt.Errorf("couldn't parse %q (procs_running): %w", parts[1], err)
211217
}
212218
case parts[0] == "procs_blocked":
213219
if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
214-
return Stat{}, fmt.Errorf("couldn't parse %q (procs_blocked): %w", parts[1], err)
220+
return newStat(), fmt.Errorf("couldn't parse %q (procs_blocked): %w", parts[1], err)
215221
}
216222
case parts[0] == "softirq":
217223
softIRQStats, total, err := parseSoftIRQStat(line)
218224
if err != nil {
219-
return Stat{}, err
225+
return newStat(), err
220226
}
221227
stat.SoftIRQTotal = total
222228
stat.SoftIRQ = softIRQStats
223229
case strings.HasPrefix(parts[0], "cpu"):
224230
cpuStat, cpuID, err := parseCPUStat(line)
225231
if err != nil {
226-
return Stat{}, err
232+
return newStat(), err
227233
}
228234
if cpuID == -1 {
229235
stat.CPUTotal = cpuStat
230236
} else {
231-
for int64(len(stat.CPU)) <= cpuID {
232-
stat.CPU = append(stat.CPU, CPUStat{})
233-
}
234-
stat.CPU[cpuID] = cpuStat
237+
stat.CPU[cpuID] = &cpuStat
235238
}
236239
}
237240
}
238241

239242
if err := scanner.Err(); err != nil {
240-
return Stat{}, fmt.Errorf("couldn't parse %q: %w", fileName, err)
243+
return newStat(), fmt.Errorf("couldn't parse %q: %w", fileName, err)
241244
}
242245

243246
return stat, nil

0 commit comments

Comments
 (0)