Skip to content

Commit

Permalink
Extend process metadata; add command line.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Wilkie committed Jun 22, 2015
1 parent ee14eb3 commit be6c4d7
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 72 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ $(SCOPE_EXPORT): $(APP_EXE) $(PROBE_EXE) docker/*

$(APP_EXE): app/*.go render/*.go report/*.go xfer/*.go

$(PROBE_EXE): probe/*.go probe/tag/*.go probe/docker/*.go report/*.go xfer/*.go
$(PROBE_EXE): probe/*.go probe/tag/*.go probe/docker/*.go probe/process/*.go report/*.go xfer/*.go

$(APP_EXE) $(PROBE_EXE):
go get -tags netgo ./$(@D)
Expand Down
12 changes: 7 additions & 5 deletions probe/process/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (

// We use these keys in node metadata
const (
PID = "pid"
Comm = "comm"
PPID = "ppid"
PID = "pid"
Comm = "comm"
PPID = "ppid"
Cmdline = "cmdline"
)

// Reporter generate Reports containing the Process topology
Expand Down Expand Up @@ -44,8 +45,9 @@ func (r *Reporter) processTopology() (report.Topology, error) {
pidstr := strconv.Itoa(p.PID)
nodeID := report.MakeProcessNodeID(r.scope, pidstr)
t.NodeMetadatas[nodeID] = report.NodeMetadata{
PID: pidstr,
Comm: p.Comm,
PID: pidstr,
Comm: p.Comm,
Cmdline: p.Cmdline,
}
if p.PPID > 0 {
t.NodeMetadatas[nodeID][PPID] = strconv.Itoa(p.PPID)
Expand Down
28 changes: 16 additions & 12 deletions probe/process/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestReporter(t *testing.T) {
{PID: 1, PPID: 0, Comm: "init"},
{PID: 2, PPID: 1, Comm: "bash"},
{PID: 3, PPID: 1, Comm: "apache"},
{PID: 4, PPID: 2, Comm: "ping"},
{PID: 4, PPID: 2, Comm: "ping", Cmdline: "ping foo.bar.local"},
} {
f(p)
}
Expand All @@ -32,23 +32,27 @@ func TestReporter(t *testing.T) {
EdgeMetadatas: report.EdgeMetadatas{},
NodeMetadatas: report.NodeMetadatas{
report.MakeProcessNodeID("", "1"): report.NodeMetadata{
process.PID: "1",
process.Comm: "init",
process.PID: "1",
process.Comm: "init",
process.Cmdline: "",
},
report.MakeProcessNodeID("", "2"): report.NodeMetadata{
process.PID: "2",
process.Comm: "bash",
process.PPID: "1",
process.PID: "2",
process.Comm: "bash",
process.PPID: "1",
process.Cmdline: "",
},
report.MakeProcessNodeID("", "3"): report.NodeMetadata{
process.PID: "3",
process.Comm: "apache",
process.PPID: "1",
process.PID: "3",
process.Comm: "apache",
process.PPID: "1",
process.Cmdline: "",
},
report.MakeProcessNodeID("", "4"): report.NodeMetadata{
process.PID: "4",
process.Comm: "ping",
process.PPID: "2",
process.PID: "4",
process.Comm: "ping",
process.PPID: "2",
process.Cmdline: "ping foo.bar.local",
},
},
}
Expand Down
16 changes: 1 addition & 15 deletions probe/process/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,7 @@ func NewTree(procRoot string) (Tree, error) {
pt.processes[p.PID] = p
})

if err != nil {
return nil, err
}

for _, child := range pt.processes {
parent, ok := pt.processes[child.PPID]
if !ok {
// This can happen as listing proc is not a consistent snapshot
continue
}
child.parent = parent
parent.children = append(parent.children, child)
}

return &pt, nil
return &pt, err
}

// GetParent returns the pid of the parent process for a given pid
Expand Down
18 changes: 13 additions & 5 deletions probe/process/walker.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package process

import (
"bytes"
"io/ioutil"
"log"
"path"
"strconv"
"strings"
Expand All @@ -11,8 +13,7 @@ import (
type Process struct {
PID, PPID int
Comm string
parent *Process
children []*Process
Cmdline string
}

// Hooks exposed for mocking
Expand Down Expand Up @@ -45,15 +46,22 @@ var Walk = func(procRoot string, f func(*Process)) error {
return err
}

cmdline := ""
if cmdlineBuf, err := ReadFile(path.Join(procRoot, filename, "cmdline")); err == nil {
cmdlineBuf = bytes.Replace(cmdlineBuf, []byte{'\000'}, []byte{' '}, -1)
cmdline = string(cmdlineBuf)
}

comm := "(unknown)"
if commBuf, err := ReadFile(path.Join(procRoot, filename, "comm")); err == nil {
comm = string(commBuf)
}

f(&Process{
PID: pid,
PPID: ppid,
Comm: comm,
PID: pid,
PPID: ppid,
Comm: comm,
Cmdline: cmdline,
})
}

Expand Down
71 changes: 45 additions & 26 deletions probe/process/walker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@ import (
"github.com/weaveworks/scope/test"
)

type fileinfo struct {
name string
type mockProcess struct {
name string
cmdline string
}

func (f fileinfo) Name() string { return f.name }
func (f fileinfo) Size() int64 { return 0 }
func (f fileinfo) Mode() os.FileMode { return 0 }
func (f fileinfo) ModTime() time.Time { return time.Now() }
func (f fileinfo) IsDir() bool { return true }
func (f fileinfo) Sys() interface{} { return nil }
func (p mockProcess) Name() string { return p.name }
func (p mockProcess) Size() int64 { return 0 }
func (p mockProcess) Mode() os.FileMode { return 0 }
func (p mockProcess) ModTime() time.Time { return time.Now() }
func (p mockProcess) IsDir() bool { return true }
func (p mockProcess) Sys() interface{} { return nil }

func TestWalker(t *testing.T) {
oldReadDir, oldReadFile := process.ReadDir, process.ReadFile
Expand All @@ -31,36 +32,54 @@ func TestWalker(t *testing.T) {
process.ReadFile = oldReadFile
}()

processes := map[string]mockProcess{
"3": {name: "3", cmdline: "curl"},
"2": {name: "2"},
"4": {name: "4"},
"notapid": {name: "notapid"},
"1": {name: "1"},
}

process.ReadDir = func(path string) ([]os.FileInfo, error) {
return []os.FileInfo{
fileinfo{"3"}, fileinfo{"2"}, fileinfo{"4"},
fileinfo{"notapid"}, fileinfo{"1"},
}, nil
result := []os.FileInfo{}
for _, p := range processes {
result = append(result, p)
}
return result, nil
}

process.ReadFile = func(path string) ([]byte, error) {
splits := strings.Split(path, "/")
if splits[len(splits)-1] != "stat" {
return nil, fmt.Errorf("not stat")

pid := splits[len(splits)-2]
process, ok := processes[pid]
if !ok {
return nil, fmt.Errorf("not found")
}
pid, err := strconv.Atoi(splits[len(splits)-2])
if err != nil {
return nil, err

file := splits[len(splits)-1]
switch file {
case "stat":
pid, _ := strconv.Atoi(splits[len(splits)-2])
parent := pid - 1
return []byte(fmt.Sprintf("%d na R %d", pid, parent)), nil
case "cmdline":
return []byte(process.cmdline), nil
}
parent := pid - 1
return []byte(fmt.Sprintf("%d na R %d", pid, parent)), nil

return nil, fmt.Errorf("not found")
}

want := []*process.Process{
{PID: 3, PPID: 2, Comm: "(unknown)"},
{PID: 2, PPID: 1, Comm: "(unknown)"},
{PID: 4, PPID: 3, Comm: "(unknown)"},
{PID: 1, PPID: 0, Comm: "(unknown)"},
want := map[int]*process.Process{
3: {PID: 3, PPID: 2, Comm: "(unknown)", Cmdline: "curl"},
2: {PID: 2, PPID: 1, Comm: "(unknown)", Cmdline: ""},
4: {PID: 4, PPID: 3, Comm: "(unknown)", Cmdline: ""},
1: {PID: 1, PPID: 0, Comm: "(unknown)", Cmdline: ""},
}

have := []*process.Process{}
have := map[int]*process.Process{}
err := process.Walk("unused", func(p *process.Process) {
have = append(have, p)
have[p.PID] = p
})

if err != nil || !reflect.DeepEqual(want, have) {
Expand Down
19 changes: 11 additions & 8 deletions render/detailed_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strconv"

"github.com/weaveworks/scope/probe/docker"
"github.com/weaveworks/scope/probe/process"
"github.com/weaveworks/scope/report"
)

Expand Down Expand Up @@ -139,15 +140,17 @@ func addressOriginTable(nmd report.NodeMetadata) (Table, bool) {

func processOriginTable(nmd report.NodeMetadata) (Table, bool) {
rows := []Row{}
if val, ok := nmd["comm"]; ok {
rows = append(rows, Row{"Name (comm)", val, ""})
}
if val, ok := nmd["pid"]; ok {
rows = append(rows, Row{"PID", val, ""})
}
if val, ok := nmd["ppid"]; ok {
rows = append(rows, Row{"Parent PID", val, ""})
for _, tuple := range []struct{ key, human string }{
{process.Comm, "Name (comm)"},
{process.PID, "PID"},
{process.PPID, "Parent PID"},
{process.Cmdline, "Command"},
} {
if val, ok := nmd[tuple.key]; ok {
rows = append(rows, Row{Key: tuple.human, ValueMajor: val, ValueMinor: ""})
}
}

return Table{
Title: "Origin Process",
Numeric: false,
Expand Down

0 comments on commit be6c4d7

Please sign in to comment.