in metric/system/process/process_linux_common.go [189:236]
func parseProcStat(data []byte) (ProcState, error) {
const minFields = 36
state := ProcState{}
// Extract the comm value with is surrounded by parentheses.
lIdx := bytes.Index(data, []byte("("))
rIdx := bytes.LastIndex(data, []byte(")"))
if lIdx < 0 || rIdx < 0 || lIdx >= rIdx || rIdx+2 >= len(data) {
return state, fmt.Errorf("failed to extract 'comm' field from '%v'",
string(data))
}
state.Name = string(data[lIdx+1 : rIdx])
// Extract the rest of the fields that we are interested in.
fields := bytes.Fields(data[rIdx+2:])
if len(fields) <= minFields {
return state, fmt.Errorf("expected at least %d stat fields from '%v'",
minFields, string(data))
}
// See https://man7.org/linux/man-pages/man5/proc.5.html for all fields.
interests := bytes.Join([][]byte{
fields[0], // state
fields[1], // ppid
fields[2], // pgrp
fields[17], // num_threads
}, []byte(" "))
var procState string
var ppid, pgid, numThreads int
_, err := fmt.Fscan(bytes.NewBuffer(interests),
&procState,
&ppid,
&pgid,
&numThreads,
)
if err != nil {
return state, fmt.Errorf("failed to parse stat fields from '%s': %w",
string(data), err)
}
state.State = getProcState(procState[0])
state.Ppid = opt.IntWith(ppid)
state.Pgid = opt.IntWith(pgid)
state.NumThreads = opt.IntWith(numThreads)
return state, nil
}