in metric/system/process/process_linux_common.go [110:165]
func FillPidMetrics(hostfs resolve.Resolver, pid int, state ProcState, filter func(string) bool) (ProcState, error) {
// Memory Data
var err error
state.Memory, err = getMemData(hostfs, pid)
if err != nil {
return state, fmt.Errorf("error getting memory data for pid %d: %w", pid, err)
}
// CPU Data
state.CPU, err = getCPUTime(hostfs, pid)
if err != nil {
return state, fmt.Errorf("error getting CPU data for pid %d: %w", pid, err)
}
// CLI args
if len(state.Args) == 0 {
state.Args, err = getArgs(hostfs, pid)
if err != nil {
return state, fmt.Errorf("error getting CLI args for pid %d: %w", pid, err)
}
}
// FD metrics
state.FD, err = getFDStats(hostfs, pid)
if err != nil {
return state, fmt.Errorf("error getting FD metrics for pid %d: %w", pid, err)
}
if state.Env == nil {
// env vars
state.Env, _ = getEnvData(hostfs, pid, filter)
}
state.Exe, state.Cwd, err = getProcStringData(hostfs, pid)
// skip permission errors and file not found errors
// see https://github.com/elastic/elastic-agent-system-metrics/issues/135 for a bit more context,
// depending on the permissions/caps that this is running with, the /exe symlink may have different levels of permission restrictions.
// A kernel proc will also return file not found.
if err != nil && !errors.Is(err, os.ErrPermission) && !errors.Is(err, os.ErrNotExist) { // ignore permission errors
return state, fmt.Errorf("error getting metadata for pid %d: %w", pid, err)
}
state.Username, err = getUser(hostfs, pid)
if err != nil {
return state, fmt.Errorf("error creating username for pid %d: %w", pid, err)
}
// the /proc/[pid]/io metrics require SYS_PTRACE when run from inside docker
state.IO, err = getIOData(hostfs, pid)
if err != nil {
return state, NonFatalErr{Err: fmt.Errorf("/io unavailable; if running inside a container, use SYS_PTRACE: %w", err)}
}
return state, nil
}