in metric/system/process/process.go [93:148]
func (procStats *Stats) Get() ([]mapstr.M, []mapstr.M, error) {
// If the user hasn't configured any kind of process glob, return
if len(procStats.Procs) == 0 {
return nil, nil, nil
}
// actually fetch the PIDs from the OS-specific code
pidMap, plist, wrappedErr := procStats.FetchPids()
if wrappedErr != nil && !isNonFatal(wrappedErr) {
return nil, nil, fmt.Errorf("error gathering PIDs: %w", wrappedErr)
}
failedPIDs := extractFailedPIDs(pidMap)
// We use this to track processes over time.
procStats.ProcsMap.SetMap(pidMap)
// filter the process list that will be passed down to users
plist = procStats.includeTopProcesses(plist)
// This is a holdover until we migrate this library to metricbeat/internal
// At which point we'll use the memory code there.
var totalPhyMem uint64
if procStats.host != nil {
memStats, err := procStats.host.Memory()
if err != nil {
procStats.logger.Warnf("Getting memory details: %v", err)
} else {
totalPhyMem = memStats.Total
}
}
// Format the list to the MapStr type used by the outputs
procs := make([]mapstr.M, 0, len(plist))
rootEvents := make([]mapstr.M, 0, len(plist))
for _, process := range plist {
process := process
// Add the RSS pct memory first
process.Memory.Rss.Pct = GetProcMemPercentage(process, totalPhyMem)
// Create the root event
rootMap := processRootEvent(&process)
proc, err := procStats.getProcessEvent(&process)
if err != nil {
return nil, nil, fmt.Errorf("error converting process for pid %d: %w", process.Pid.ValueOr(0), err)
}
procs = append(procs, proc)
rootEvents = append(rootEvents, rootMap)
}
if wrappedErr != nil && len(failedPIDs) > 0 {
procStats.logger.Debugf("error fetching process metrics: %v", wrappedErr)
return procs, rootEvents, NonFatalErr{Err: fmt.Errorf(errFetchingPIDs, len(failedPIDs))}
}
return procs, rootEvents, toNonFatal(wrappedErr)
}