func parseProcStat()

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
}