From 7df63d1bc43310a5499b7f875f853fc5338d864c Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Wed, 10 Jun 2015 17:49:50 +0200 Subject: [PATCH] Decouple PIDTree from DockerTagger PIDTree is created in each spy tick, regardless if Docker Tagger is used. --- probe/main.go | 6 ++-- probe/tag/docker_tagger.go | 9 ++---- probe/tag/docker_tagger_test.go | 12 ++++---- probe/tag/pidtree.go | 52 ++++++++++++++++++--------------- 4 files changed, 40 insertions(+), 39 deletions(-) diff --git a/probe/main.go b/probe/main.go index 34272fe3a..29bf52546 100644 --- a/probe/main.go +++ b/probe/main.go @@ -99,8 +99,10 @@ func main() { case <-spyTick: r.Merge(spy(hostID, hostName, *spyProcs)) - if dockerTagger != nil { - r.Process.Merge(dockerTagger.ProcessTopology(hostID)) + if pidTree, err := tag.NewPIDTree(*procRoot); err == nil { + r.Process.Merge(pidTree.ProcessTopology(hostID)) + } else { + log.Print(err) } r = tag.Apply(r, taggers) diff --git a/probe/tag/docker_tagger.go b/probe/tag/docker_tagger.go index 7980e0276..2729f3bd3 100644 --- a/probe/tag/docker_tagger.go +++ b/probe/tag/docker_tagger.go @@ -18,7 +18,7 @@ const ( var ( newDockerClientStub = newDockerClient - newPIDTreeStub = newPIDTree + newPIDTreeStub = NewPIDTree ) // DockerTagger is a tagger that tags Docker container information to process @@ -33,7 +33,7 @@ type DockerTagger struct { images map[string]*docker.APIImages procRoot string - pidTree *pidTree + pidTree *PIDTree } // NewDockerTagger returns a usable DockerTagger. Don't forget to Stop it. @@ -64,11 +64,6 @@ func (t *DockerTagger) Stop() { close(t.quit) } -// ProcessTopology returns a process topology from the pidtree. -func (t *DockerTagger) ProcessTopology(hostID string) report.Topology { - return t.pidTree.processTopology(hostID) -} - func (t *DockerTagger) loop() { if !t.update() { return diff --git a/probe/tag/docker_tagger_test.go b/probe/tag/docker_tagger_test.go index a3f073fb5..ef02b15fe 100644 --- a/probe/tag/docker_tagger_test.go +++ b/probe/tag/docker_tagger_test.go @@ -40,12 +40,12 @@ func TestDockerTagger(t *testing.T) { oldPIDTree, oldDockerClient := newPIDTreeStub, newDockerClientStub defer func() { newPIDTreeStub, newDockerClientStub = oldPIDTree, oldDockerClient }() - newPIDTreeStub = func(procRoot string) (*pidTree, error) { - pid1 := &process{pid: 1} - pid2 := &process{pid: 2, ppid: 1, parent: pid1} - pid1.children = []*process{pid2} - return &pidTree{ - processes: map[int]*process{ + newPIDTreeStub = func(procRoot string) (*PIDTree, error) { + pid1 := &Process{PID: 1} + pid2 := &Process{PID: 2, PPID: 1, parent: pid1} + pid1.children = []*Process{pid2} + return &PIDTree{ + processes: map[int]*Process{ 1: pid1, 2: pid2, }, }, nil diff --git a/probe/tag/pidtree.go b/probe/tag/pidtree.go index 88b010ce5..2ca59bbe8 100644 --- a/probe/tag/pidtree.go +++ b/probe/tag/pidtree.go @@ -10,15 +10,17 @@ import ( "github.com/weaveworks/scope/report" ) -type pidTree struct { - processes map[int]*process +// PIDTree represents all processes on the machine. +type PIDTree struct { + processes map[int]*Process } -type process struct { - pid, ppid int - parent *process - children []*process - comm string +// Process represents a single process. +type Process struct { + PID, PPID int + Comm string + parent *Process + children []*Process } // Hooks for mocking @@ -27,13 +29,14 @@ var ( readFile = ioutil.ReadFile ) -func newPIDTree(procRoot string) (*pidTree, error) { +// NewPIDTree returns a new PIDTree that can be polled. +func NewPIDTree(procRoot string) (*PIDTree, error) { dirEntries, err := readDir(procRoot) if err != nil { return nil, err } - pt := pidTree{processes: map[int]*process{}} + pt := PIDTree{processes: map[int]*Process{}} for _, dirEntry := range dirEntries { filename := dirEntry.Name() pid, err := strconv.Atoi(filename) @@ -56,15 +59,15 @@ func newPIDTree(procRoot string) (*pidTree, error) { comm = string(commBuf) } - pt.processes[pid] = &process{ - pid: pid, - ppid: ppid, - comm: comm, + pt.processes[pid] = &Process{ + PID: pid, + PPID: ppid, + Comm: comm, } } for _, child := range pt.processes { - parent, ok := pt.processes[child.ppid] + parent, ok := pt.processes[child.PPID] if !ok { // This can happen as listing proc is not a consistent snapshot continue @@ -76,17 +79,17 @@ func newPIDTree(procRoot string) (*pidTree, error) { return &pt, nil } -func (pt *pidTree) getParent(pid int) (int, error) { +func (pt *PIDTree) getParent(pid int) (int, error) { proc, ok := pt.processes[pid] if !ok { return -1, fmt.Errorf("PID %d not found", pid) } - return proc.ppid, nil + return proc.PPID, nil } // allChildren returns a flattened list of child pids including the given pid -func (pt *pidTree) allChildren(pid int) ([]int, error) { +func (pt *PIDTree) allChildren(pid int) ([]int, error) { proc, ok := pt.processes[pid] if !ok { return []int{}, fmt.Errorf("PID %d not found", pid) @@ -94,9 +97,9 @@ func (pt *pidTree) allChildren(pid int) ([]int, error) { var result []int - var f func(*process) - f = func(p *process) { - result = append(result, p.pid) + var f func(*Process) + f = func(p *Process) { + result = append(result, p.PID) for _, child := range p.children { f(child) } @@ -106,17 +109,18 @@ func (pt *pidTree) allChildren(pid int) ([]int, error) { return result, nil } -func (pt *pidTree) processTopology(hostID string) report.Topology { +// ProcessTopology returns a process topology based on the current state of the PIDTree. +func (pt *PIDTree) ProcessTopology(hostID string) report.Topology { t := report.NewTopology() for pid, proc := range pt.processes { pidstr := strconv.Itoa(pid) nodeID := report.MakeProcessNodeID(hostID, pidstr) t.NodeMetadatas[nodeID] = report.NodeMetadata{ "pid": pidstr, - "comm": proc.comm, + "comm": proc.Comm, } - if proc.ppid > 0 { - t.NodeMetadatas[nodeID]["ppid"] = strconv.Itoa(proc.ppid) + if proc.PPID > 0 { + t.NodeMetadatas[nodeID]["ppid"] = strconv.Itoa(proc.PPID) } } return t