mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-04 02:30:45 +00:00
Decouple PIDTree from DockerTagger
PIDTree is created in each spy tick, regardless if Docker Tagger is used.
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user