func getCPUTime()

in metric/system/process/process_linux_common.go [380:421]


func getCPUTime(hostfs resolve.Resolver, pid int) (ProcCPUInfo, error) {
	state := ProcCPUInfo{}

	pathCPU := hostfs.Join("proc", strconv.Itoa(pid), "stat")
	data, err := os.ReadFile(pathCPU)
	if err != nil {
		return state, fmt.Errorf("error opening file %s: %w", pathCPU, err)
	}
	fields := strings.Fields(string(data))

	user, err := strconv.ParseUint(fields[13], 10, 64)
	if err != nil {
		return state, fmt.Errorf("error parsing user CPU times for pid %d: %w", pid, err)
	}
	sys, err := strconv.ParseUint(fields[14], 10, 64)
	if err != nil {
		return state, fmt.Errorf("error parsing system CPU times for pid %d: %w", pid, err)
	}

	btime, err := getLinuxBootTime(hostfs)
	if err != nil {
		return state, fmt.Errorf("error feting boot time for pid %d: %w", pid, err)
	}

	// convert to milliseconds from USER_HZ
	// This effectively means our definition of "ticks" throughout the process code is a millisecond
	state.User.Ticks = opt.UintWith(user * (1000 / ticks))
	state.System.Ticks = opt.UintWith(sys * (1000 / ticks))
	state.Total.Ticks = opt.UintWith(opt.SumOptUint(state.User.Ticks, state.System.Ticks))

	startTime, err := strconv.ParseUint(fields[21], 10, 64)
	if err != nil {
		return state, fmt.Errorf("error parsing start time value %s for pid %d: %w", fields[21], pid, err)
	}

	startTime /= ticks
	startTime += btime
	startTime *= 1000

	state.StartTime = unixTimeMsToTime(startTime)
	return state, nil
}