mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 10:11:03 +00:00
the information is constant and already present in the id, so we can extract it from there. That reduces the report size and improves report encoding/decoding performance. It should reduce memory usage too and improve report merging performance too. NB: Probes with this change are incompatible with old apps.
147 lines
4.6 KiB
Go
147 lines
4.6 KiB
Go
package render
|
|
|
|
import (
|
|
"github.com/weaveworks/scope/probe/docker"
|
|
"github.com/weaveworks/scope/probe/process"
|
|
"github.com/weaveworks/scope/report"
|
|
)
|
|
|
|
// Constants are used in the tests.
|
|
const (
|
|
InboundMajor = "The Internet"
|
|
OutboundMajor = "The Internet"
|
|
InboundMinor = "Inbound connections"
|
|
OutboundMinor = "Outbound connections"
|
|
|
|
// Topology for pseudo-nodes and IPs so we can differentiate them at the end
|
|
Pseudo = "pseudo"
|
|
)
|
|
|
|
func renderProcesses(rpt report.Report) bool {
|
|
return len(rpt.Process.Nodes) >= 1
|
|
}
|
|
|
|
// EndpointRenderer is a Renderer which produces a renderable endpoint graph.
|
|
var EndpointRenderer = FilterProcspiedOrEBPF(SelectEndpoint)
|
|
|
|
// ProcessRenderer is a Renderer which produces a renderable process
|
|
// graph by merging the endpoint graph and the process topology.
|
|
var ProcessRenderer = ConditionalRenderer(renderProcesses,
|
|
ColorConnected(MakeReduce(
|
|
MakeMap(
|
|
MapEndpoint2Process,
|
|
EndpointRenderer,
|
|
),
|
|
SelectProcess,
|
|
)),
|
|
)
|
|
|
|
// processWithContainerNameRenderer is a Renderer which produces a process
|
|
// graph enriched with container names where appropriate
|
|
type processWithContainerNameRenderer struct {
|
|
Renderer
|
|
}
|
|
|
|
func (r processWithContainerNameRenderer) Render(rpt report.Report, dct Decorator) report.Nodes {
|
|
processes := r.Renderer.Render(rpt, dct)
|
|
containers := SelectContainer.Render(rpt, dct)
|
|
|
|
outputs := report.Nodes{}
|
|
for id, p := range processes {
|
|
outputs[id] = p
|
|
containerID, timestamp, ok := p.Latest.LookupEntry(docker.ContainerID)
|
|
if !ok {
|
|
continue
|
|
}
|
|
container, ok := containers[report.MakeContainerNodeID(containerID)]
|
|
if !ok {
|
|
continue
|
|
}
|
|
p.Latest = p.Latest.Set(docker.ContainerID, timestamp, containerID)
|
|
if containerName, timestamp, ok := container.Latest.LookupEntry(docker.ContainerName); ok {
|
|
p.Latest = p.Latest.Set(docker.ContainerName, timestamp, containerName)
|
|
}
|
|
outputs[id] = p
|
|
}
|
|
return outputs
|
|
}
|
|
|
|
// ProcessWithContainerNameRenderer is a Renderer which produces a process
|
|
// graph enriched with container names where appropriate
|
|
var ProcessWithContainerNameRenderer = processWithContainerNameRenderer{ProcessRenderer}
|
|
|
|
// ProcessNameRenderer is a Renderer which produces a renderable process
|
|
// name graph by munging the progess graph.
|
|
var ProcessNameRenderer = ConditionalRenderer(renderProcesses,
|
|
MakeMap(
|
|
MapProcess2Name,
|
|
ProcessRenderer,
|
|
),
|
|
)
|
|
|
|
// MapEndpoint2Pseudo makes internet of host pesudo nodes from a endpoint node.
|
|
func MapEndpoint2Pseudo(n report.Node, local report.Networks) report.Nodes {
|
|
_, addr, _, ok := report.ParseEndpointNodeID(n.ID)
|
|
if !ok {
|
|
return report.Nodes{}
|
|
}
|
|
|
|
if externalNode, ok := NewDerivedExternalNode(n, addr, local); ok {
|
|
return report.Nodes{externalNode.ID: externalNode}
|
|
}
|
|
|
|
// due to https://github.com/weaveworks/scope/issues/1323 we are dropping
|
|
// all non-external pseudo nodes for now.
|
|
return report.Nodes{}
|
|
}
|
|
|
|
// MapEndpoint2Process maps endpoint Nodes to process
|
|
// Nodes.
|
|
//
|
|
// If this function is given a pseudo node, then it will just return it;
|
|
// Pseudo nodes will never have pids in them, and therefore will never
|
|
// be able to be turned into a Process node.
|
|
//
|
|
// Otherwise, this function will produce a node with the correct ID
|
|
// format for a process, but without any Major or Minor labels.
|
|
// It does not have enough info to do that, and the resulting graph
|
|
// must be merged with a process graph to get that info.
|
|
func MapEndpoint2Process(n report.Node, local report.Networks) report.Nodes {
|
|
// Nodes without a hostid are treated as pseudo nodes
|
|
if _, ok := n.Latest.Lookup(report.HostNodeID); !ok {
|
|
return MapEndpoint2Pseudo(n, local)
|
|
}
|
|
|
|
pid, timestamp, ok := n.Latest.LookupEntry(process.PID)
|
|
if !ok {
|
|
return report.Nodes{}
|
|
}
|
|
|
|
id := report.MakeProcessNodeID(report.ExtractHostID(n), pid)
|
|
node := NewDerivedNode(id, n).WithTopology(report.Process)
|
|
node.Latest = node.Latest.Set(process.PID, timestamp, pid)
|
|
node.Counters = node.Counters.Add(n.Topology, 1)
|
|
return report.Nodes{id: node}
|
|
}
|
|
|
|
// MapProcess2Name maps process Nodes to Nodes
|
|
// for each process name.
|
|
//
|
|
// This mapper is unlike the other foo2bar mappers as the intention
|
|
// is not to join the information with another topology.
|
|
func MapProcess2Name(n report.Node, _ report.Networks) report.Nodes {
|
|
if n.Topology == Pseudo {
|
|
return report.Nodes{n.ID: n}
|
|
}
|
|
|
|
name, timestamp, ok := n.Latest.LookupEntry(process.Name)
|
|
if !ok {
|
|
return report.Nodes{}
|
|
}
|
|
|
|
node := NewDerivedNode(name, n).WithTopology(MakeGroupNodeTopology(n.Topology, process.Name))
|
|
node.Latest = node.Latest.Set(process.Name, timestamp, name)
|
|
node.Counters = node.Counters.Add(n.Topology, 1)
|
|
return report.Nodes{name: node}
|
|
}
|