| 114 | } |
| 115 | |
| 116 | func (c *processCollector) getAllocatedThreads() (int, map[string]int32, int, map[string]int32, error) { |
| 117 | p, err := c.fs.AllProcs() |
| 118 | if err != nil { |
| 119 | return 0, nil, 0, nil, fmt.Errorf("unable to list all processes: %w", err) |
| 120 | } |
| 121 | pids := 0 |
| 122 | thread := 0 |
| 123 | procStates := make(map[string]int32) |
| 124 | threadStates := make(map[string]int32) |
| 125 | |
| 126 | for _, pid := range p { |
| 127 | stat, err := pid.Stat() |
| 128 | if err != nil { |
| 129 | // PIDs can vanish between getting the list and getting stats. |
| 130 | if c.isIgnoredError(err) { |
| 131 | c.logger.Debug("file not found when retrieving stats for pid", "pid", pid.PID, "err", err) |
| 132 | continue |
| 133 | } |
| 134 | c.logger.Debug("error reading stat for pid", "pid", pid.PID, "err", err) |
| 135 | return 0, nil, 0, nil, fmt.Errorf("error reading stat for pid %d: %w", pid.PID, err) |
| 136 | } |
| 137 | pids++ |
| 138 | procStates[stat.State]++ |
| 139 | thread += stat.NumThreads |
| 140 | err = c.getThreadStates(pid.PID, stat, threadStates) |
| 141 | if err != nil { |
| 142 | return 0, nil, 0, nil, err |
| 143 | } |
| 144 | } |
| 145 | return pids, procStates, thread, threadStates, nil |
| 146 | } |
| 147 | |
| 148 | func (c *processCollector) getThreadStates(pid int, pidStat procfs.ProcStat, threadStates map[string]int32) error { |
| 149 | fs, err := procfs.NewFS(procFilePath(path.Join(strconv.Itoa(pid), "task"))) |