mirror of
https://github.com/weaveworks/scope.git
synced 2026-02-22 05:50:11 +00:00
This fixes the regression where process names weren't appearing for Darwin probes. Makes testing easier. Also, changes the process walker to operate on value types. There's no performance advantage to using reference types for something of this size, and there appeared to be a data race in the Darwin port that caused nodes to gain and lose process names over time. Also, restructures how to enable docker scraping. Default false when run manually, and enabled via --probe.docker true in the scope script.
80 lines
1.6 KiB
Go
80 lines
1.6 KiB
Go
package process
|
|
|
|
import (
|
|
"bytes"
|
|
"io/ioutil"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Hooks exposed for mocking
|
|
var (
|
|
ReadDir = ioutil.ReadDir
|
|
ReadFile = ioutil.ReadFile
|
|
)
|
|
|
|
type walker struct {
|
|
procRoot string
|
|
}
|
|
|
|
// NewWalker creates a new process Walker.
|
|
func NewWalker(procRoot string) Walker {
|
|
return &walker{procRoot: procRoot}
|
|
}
|
|
|
|
// Walk walks the supplied directory (expecting it to look like /proc)
|
|
// and marshalls the files into instances of Process, which it then
|
|
// passes one-by-one to the supplied function. Walk is only made public
|
|
// so that is can be tested.
|
|
func (w *walker) Walk(f func(Process)) error {
|
|
dirEntries, err := ReadDir(w.procRoot)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, dirEntry := range dirEntries {
|
|
filename := dirEntry.Name()
|
|
pid, err := strconv.Atoi(filename)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
stat, err := ReadFile(path.Join(w.procRoot, filename, "stat"))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
splits := strings.Fields(string(stat))
|
|
ppid, err := strconv.Atoi(splits[3])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
threads, err := strconv.Atoi(splits[19])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cmdline := ""
|
|
if cmdlineBuf, err := ReadFile(path.Join(w.procRoot, filename, "cmdline")); err == nil {
|
|
cmdlineBuf = bytes.Replace(cmdlineBuf, []byte{'\000'}, []byte{' '}, -1)
|
|
cmdline = string(cmdlineBuf)
|
|
}
|
|
|
|
comm := "(unknown)"
|
|
if commBuf, err := ReadFile(path.Join(w.procRoot, filename, "comm")); err == nil {
|
|
comm = strings.TrimSpace(string(commBuf))
|
|
}
|
|
|
|
f(Process{
|
|
PID: pid,
|
|
PPID: ppid,
|
|
Comm: comm,
|
|
Cmdline: cmdline,
|
|
Threads: threads,
|
|
})
|
|
}
|
|
|
|
return nil
|
|
}
|