mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 02:00:43 +00:00
208 lines
6.2 KiB
Go
208 lines
6.2 KiB
Go
package detailed
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/weaveworks/scope/probe/docker"
|
|
"github.com/weaveworks/scope/probe/host"
|
|
"github.com/weaveworks/scope/probe/kubernetes"
|
|
"github.com/weaveworks/scope/probe/process"
|
|
"github.com/weaveworks/scope/render"
|
|
"github.com/weaveworks/scope/report"
|
|
)
|
|
|
|
// Node is the data type that's yielded to the JavaScript layer when
|
|
// we want deep information about an individual node.
|
|
type Node struct {
|
|
NodeSummary
|
|
Rank string `json:"rank,omitempty"`
|
|
Pseudo bool `json:"pseudo,omitempty"`
|
|
Controls []ControlInstance `json:"controls"`
|
|
Children []NodeSummaryGroup `json:"children,omitempty"`
|
|
Parents []Parent `json:"parents,omitempty"`
|
|
}
|
|
|
|
// Parent is the information needed to build a link to the parent of a Node.
|
|
type Parent struct {
|
|
ID string `json:"id"`
|
|
Label string `json:"label"`
|
|
TopologyID string `json:"topologyId"`
|
|
}
|
|
|
|
// ControlInstance contains a control description, and all the info
|
|
// needed to execute it.
|
|
type ControlInstance struct {
|
|
ProbeID string `json:"probeId"`
|
|
NodeID string `json:"nodeId"`
|
|
report.Control
|
|
}
|
|
|
|
// MakeNode transforms a renderable node to a detailed node. It uses
|
|
// aggregate metadata, plus the set of origin node IDs, to produce tables.
|
|
func MakeNode(r report.Report, n render.RenderableNode) Node {
|
|
summary, _ := MakeNodeSummary(n.Node)
|
|
summary.ID = n.ID
|
|
summary.Label = n.LabelMajor
|
|
return Node{
|
|
NodeSummary: summary,
|
|
Rank: n.Rank,
|
|
Pseudo: n.Pseudo,
|
|
Controls: controls(r, n),
|
|
Children: children(n),
|
|
Parents: parents(r, n),
|
|
}
|
|
}
|
|
|
|
func controlsFor(topology report.Topology, nodeID string) []ControlInstance {
|
|
result := []ControlInstance{}
|
|
node, ok := topology.Nodes[nodeID]
|
|
if !ok {
|
|
return result
|
|
}
|
|
|
|
for _, id := range node.Controls.Controls {
|
|
if control, ok := topology.Controls[id]; ok {
|
|
probeID, _ := node.Latest.Lookup(report.ProbeID)
|
|
result = append(result, ControlInstance{
|
|
ProbeID: probeID,
|
|
NodeID: nodeID,
|
|
Control: control,
|
|
})
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func controls(r report.Report, n render.RenderableNode) []ControlInstance {
|
|
if _, ok := r.Process.Nodes[n.ControlNode]; ok {
|
|
return controlsFor(r.Process, n.ControlNode)
|
|
} else if _, ok := r.Container.Nodes[n.ControlNode]; ok {
|
|
return controlsFor(r.Container, n.ControlNode)
|
|
} else if _, ok := r.ContainerImage.Nodes[n.ControlNode]; ok {
|
|
return controlsFor(r.ContainerImage, n.ControlNode)
|
|
} else if _, ok := r.Host.Nodes[n.ControlNode]; ok {
|
|
return controlsFor(r.Host, n.ControlNode)
|
|
}
|
|
return []ControlInstance{}
|
|
}
|
|
|
|
var (
|
|
nodeSummaryGroupSpecs = []struct {
|
|
topologyID string
|
|
NodeSummaryGroup
|
|
}{
|
|
{report.Host, NodeSummaryGroup{TopologyID: "hosts", Label: "Hosts", Columns: []string{host.CPUUsage, host.MemoryUsage}}},
|
|
{report.Pod, NodeSummaryGroup{TopologyID: "pods", Label: "Pods", Columns: []string{}}},
|
|
{report.ContainerImage, NodeSummaryGroup{TopologyID: "containers-by-image", Label: "Container Images", Columns: []string{}}},
|
|
{report.Container, NodeSummaryGroup{TopologyID: "containers", Label: "Containers", Columns: []string{docker.CPUTotalUsage, docker.MemoryUsage}}},
|
|
{report.Process, NodeSummaryGroup{TopologyID: "applications", Label: "Applications", Columns: []string{process.PID, process.CPUUsage, process.MemoryUsage}}},
|
|
}
|
|
)
|
|
|
|
func children(n render.RenderableNode) []NodeSummaryGroup {
|
|
summaries := map[string][]NodeSummary{}
|
|
n.Children.ForEach(func(child report.Node) {
|
|
if child.ID != n.ID {
|
|
if summary, ok := MakeNodeSummary(child); ok {
|
|
summaries[child.Topology] = append(summaries[child.Topology], summary)
|
|
}
|
|
}
|
|
})
|
|
|
|
nodeSummaryGroups := []NodeSummaryGroup{}
|
|
for _, spec := range nodeSummaryGroupSpecs {
|
|
if len(summaries[spec.topologyID]) > 0 {
|
|
sort.Sort(nodeSummariesByID(summaries[spec.TopologyID]))
|
|
group := spec.NodeSummaryGroup.Copy()
|
|
group.Nodes = summaries[spec.topologyID]
|
|
nodeSummaryGroups = append(nodeSummaryGroups, group)
|
|
}
|
|
}
|
|
return nodeSummaryGroups
|
|
}
|
|
|
|
// parents renders the parents of this report.Node, which have been aggregated
|
|
// from the probe reports.
|
|
func parents(r report.Report, n render.RenderableNode) (result []Parent) {
|
|
topologies := map[string]struct {
|
|
report.Topology
|
|
render func(report.Node) Parent
|
|
}{
|
|
report.Container: {r.Container, containerParent},
|
|
report.Pod: {r.Pod, podParent},
|
|
report.Service: {r.Service, serviceParent},
|
|
report.ContainerImage: {r.ContainerImage, containerImageParent},
|
|
report.Host: {r.Host, hostParent},
|
|
}
|
|
topologyIDs := []string{}
|
|
for topologyID := range topologies {
|
|
topologyIDs = append(topologyIDs, topologyID)
|
|
}
|
|
sort.Strings(topologyIDs)
|
|
for _, topologyID := range topologyIDs {
|
|
t := topologies[topologyID]
|
|
parents, _ := n.Node.Parents.Lookup(topologyID)
|
|
for _, id := range parents {
|
|
if topologyID == n.Node.Topology && id == n.ID {
|
|
continue
|
|
}
|
|
|
|
parent, ok := t.Nodes[id]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
result = append(result, t.render(parent))
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func containerParent(n report.Node) Parent {
|
|
label, _ := render.GetRenderableContainerName(n)
|
|
containerID, _ := n.Latest.Lookup(docker.ContainerID)
|
|
return Parent{
|
|
ID: render.MakeContainerID(containerID),
|
|
Label: label,
|
|
TopologyID: "containers",
|
|
}
|
|
}
|
|
|
|
func podParent(n report.Node) Parent {
|
|
podID, _ := n.Latest.Lookup(kubernetes.PodID)
|
|
podName, _ := n.Latest.Lookup(kubernetes.PodName)
|
|
return Parent{
|
|
ID: render.MakePodID(podID),
|
|
Label: podName,
|
|
TopologyID: "pods",
|
|
}
|
|
}
|
|
|
|
func serviceParent(n report.Node) Parent {
|
|
serviceID, _ := n.Latest.Lookup(kubernetes.ServiceID)
|
|
serviceName, _ := n.Latest.Lookup(kubernetes.ServiceName)
|
|
return Parent{
|
|
ID: render.MakeServiceID(serviceID),
|
|
Label: serviceName,
|
|
TopologyID: "pods-by-service",
|
|
}
|
|
}
|
|
|
|
func containerImageParent(n report.Node) Parent {
|
|
imageName, _ := n.Latest.Lookup(docker.ImageName)
|
|
return Parent{
|
|
ID: render.MakeContainerImageID(render.ImageNameWithoutVersion(imageName)),
|
|
Label: imageName,
|
|
TopologyID: "containers-by-image",
|
|
}
|
|
}
|
|
|
|
func hostParent(n report.Node) Parent {
|
|
hostName, _ := n.Latest.Lookup(host.HostName)
|
|
return Parent{
|
|
ID: render.MakeHostID(hostName),
|
|
Label: hostName,
|
|
TopologyID: "hosts",
|
|
}
|
|
}
|