mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-22 14:56:56 +00:00
Update detail node logic to deal with connection directionality; also correctly merge edge metadata for pseudo nodes.
This commit is contained in:
@@ -48,6 +48,23 @@ type Row struct {
|
||||
ValueMinor string `json:"value_minor,omitempty"` // e.g. KB/s
|
||||
}
|
||||
|
||||
type rows []Row
|
||||
|
||||
func (r rows) Len() int { return len(r) }
|
||||
func (r rows) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
||||
func (r rows) Less(i, j int) bool {
|
||||
switch {
|
||||
case r[i].Key != r[j].Key:
|
||||
return r[i].Key < r[j].Key
|
||||
|
||||
case r[i].ValueMajor != r[j].ValueMajor:
|
||||
return r[i].ValueMajor < r[j].ValueMajor
|
||||
|
||||
default:
|
||||
return r[i].ValueMinor < r[j].ValueMinor
|
||||
}
|
||||
}
|
||||
|
||||
type tables []Table
|
||||
|
||||
func (t tables) Len() int { return len(t) }
|
||||
@@ -118,6 +135,7 @@ func MakeDetailedNode(r report.Report, n RenderableNode) DetailedNode {
|
||||
}
|
||||
}
|
||||
if len(connections) > 0 {
|
||||
sort.Sort(rows(connections))
|
||||
tables = append(tables, connectionDetailsTable(connections))
|
||||
}
|
||||
|
||||
@@ -166,16 +184,26 @@ func connectionDetailsRows(topology report.Topology, originID string) []Row {
|
||||
if !ok {
|
||||
return rows
|
||||
}
|
||||
adjacencies := topology.Adjacency[report.MakeAdjacencyID(originID)]
|
||||
sort.Strings(adjacencies)
|
||||
for _, nodeID := range adjacencies {
|
||||
if remote, ok := labeler(nodeID); ok {
|
||||
for _, serverNodeID := range topology.Adjacency[report.MakeAdjacencyID(originID)] {
|
||||
if remote, ok := labeler(serverNodeID); ok {
|
||||
rows = append(rows, Row{
|
||||
Key: local,
|
||||
ValueMajor: remote,
|
||||
})
|
||||
}
|
||||
}
|
||||
for clientAdjID, serverNodeIDs := range topology.Adjacency {
|
||||
if serverNodeIDs.Contains(originID) {
|
||||
if clientNodeID, ok := report.ParseAdjacencyID(clientAdjID); ok {
|
||||
if remote, ok := labeler(clientNodeID); ok {
|
||||
rows = append(rows, Row{
|
||||
Key: remote,
|
||||
ValueMajor: local,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
@@ -183,7 +211,7 @@ func connectionDetailsTable(connectionRows []Row) Table {
|
||||
return Table{
|
||||
Title: "Connection Details",
|
||||
Numeric: false,
|
||||
Rows: append([]Row{{Key: "Local", ValueMajor: "Remote"}}, connectionRows...),
|
||||
Rows: append([]Row{{Key: "Client", ValueMajor: "Server"}}, connectionRows...),
|
||||
Rank: endpointRank,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package render_test
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -121,15 +121,15 @@ func TestMakeDetailedContainerNode(t *testing.T) {
|
||||
LabelMinor: test.ServerHostName,
|
||||
Pseudo: false,
|
||||
Tables: []render.Table{
|
||||
// {
|
||||
// Title: "Connections",
|
||||
// Numeric: true,
|
||||
// Rank: 100,
|
||||
// Rows: []render.Row{
|
||||
// {"Egress packet rate", "75", "packets/sec"},
|
||||
// {"Egress byte rate", "750", "Bps"},
|
||||
// },
|
||||
// },
|
||||
{
|
||||
Title: "Connections",
|
||||
Numeric: true,
|
||||
Rank: 100,
|
||||
Rows: []render.Row{
|
||||
{"Egress packet rate", "105", "packets/sec"},
|
||||
{"Egress byte rate", "1.0", "KBps"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Title: "Origin Container",
|
||||
Numeric: false,
|
||||
@@ -159,43 +159,43 @@ func TestMakeDetailedContainerNode(t *testing.T) {
|
||||
{"Operating system", "Linux", ""},
|
||||
},
|
||||
},
|
||||
// {
|
||||
// Title: "Connection Details",
|
||||
// Numeric: false,
|
||||
// Rows: []render.Row{
|
||||
// {"Local", "Remote", ""},
|
||||
// {
|
||||
// fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
// fmt.Sprintf("%s:%s", test.UnknownClient1IP, test.ClientPort54010),
|
||||
// "",
|
||||
// },
|
||||
// {
|
||||
// fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
// fmt.Sprintf("%s:%s", test.UnknownClient1IP, test.ClientPort54020),
|
||||
// "",
|
||||
// },
|
||||
// {
|
||||
// fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
// fmt.Sprintf("%s:%s", test.UnknownClient3IP, test.ClientPort54020),
|
||||
// "",
|
||||
// },
|
||||
// {
|
||||
// fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
// fmt.Sprintf("%s:%s", test.ClientIP, test.ClientPort54001),
|
||||
// "",
|
||||
// },
|
||||
// {
|
||||
// fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
// fmt.Sprintf("%s:%s", test.ClientIP, test.ClientPort54002),
|
||||
// "",
|
||||
// },
|
||||
// {
|
||||
// fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
// fmt.Sprintf("%s:%s", test.RandomClientIP, test.ClientPort12345),
|
||||
// "",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
{
|
||||
Title: "Connection Details",
|
||||
Numeric: false,
|
||||
Rows: []render.Row{
|
||||
{"Client", "Server", ""},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.UnknownClient1IP, test.ClientPort54010),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.UnknownClient1IP, test.ClientPort54020),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.UnknownClient3IP, test.ClientPort54020),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.ClientIP, test.ClientPort54001),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.ClientIP, test.ClientPort54002),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.RandomClientIP, test.ClientPort12345),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(want, have) {
|
||||
|
||||
@@ -20,8 +20,8 @@ var (
|
||||
Pseudo: true,
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(40),
|
||||
EgressByteCount: newu64(400),
|
||||
EgressPacketCount: newu64(70),
|
||||
EgressByteCount: newu64(700),
|
||||
},
|
||||
Adjacency: adjacency,
|
||||
}
|
||||
@@ -107,7 +107,10 @@ var (
|
||||
test.ServerHostNodeID,
|
||||
),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(210),
|
||||
EgressByteCount: newu64(2100),
|
||||
},
|
||||
},
|
||||
nonContainerProcessID: {
|
||||
ID: nonContainerProcessID,
|
||||
@@ -162,7 +165,10 @@ var (
|
||||
test.ServerHostNodeID,
|
||||
),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(210),
|
||||
EgressByteCount: newu64(2100),
|
||||
},
|
||||
},
|
||||
"bash": {
|
||||
ID: "bash",
|
||||
@@ -218,7 +224,10 @@ var (
|
||||
test.ServerHostNodeID,
|
||||
),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(210),
|
||||
EgressByteCount: newu64(2100),
|
||||
},
|
||||
},
|
||||
uncontainedServerID: {
|
||||
ID: uncontainedServerID,
|
||||
@@ -273,7 +282,10 @@ var (
|
||||
test.ServerProcessNodeID,
|
||||
test.ServerHostNodeID),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(210),
|
||||
EgressByteCount: newu64(2100),
|
||||
},
|
||||
},
|
||||
uncontainedServerID: {
|
||||
ID: uncontainedServerID,
|
||||
@@ -309,7 +321,9 @@ var (
|
||||
test.ServerAddressNodeID,
|
||||
),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
MaxConnCountTCP: newu64(3),
|
||||
},
|
||||
},
|
||||
ClientHostRenderedID: {
|
||||
ID: ClientHostRenderedID,
|
||||
|
||||
@@ -177,6 +177,24 @@ func (m LeafMap) Render(rpt report.Report) RenderableNodes {
|
||||
source2mapped[nodeID] = mapped.ID
|
||||
}
|
||||
|
||||
mkPseudoNode := func(srcID, dstId string, srcIsClient bool) (string, bool) {
|
||||
pseudoNode, ok := m.Pseudo(srcID, dstId, srcIsClient, localNetworks)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
// TODO(tomwilkie): we should propagate origin nodes for pseudo nodes.
|
||||
// Not worth doing until they are selectable in the UI
|
||||
// pseudoNode.Origins = pseudoNode.Origins.Add(srcID)
|
||||
existing, ok := nodes[pseudoNode.ID]
|
||||
if ok {
|
||||
pseudoNode.Merge(existing)
|
||||
}
|
||||
|
||||
nodes[pseudoNode.ID] = pseudoNode
|
||||
source2mapped[pseudoNode.ID] = srcID
|
||||
return pseudoNode.ID, true
|
||||
}
|
||||
|
||||
// Walk the graph and make connections.
|
||||
for src, dsts := range t.Adjacency {
|
||||
srcNodeID, ok := report.ParseAdjacencyID(src)
|
||||
@@ -185,11 +203,8 @@ func (m LeafMap) Render(rpt report.Report) RenderableNodes {
|
||||
continue
|
||||
}
|
||||
|
||||
var (
|
||||
srcRenderableID, ok1 = source2mapped[srcNodeID]
|
||||
srcRenderableNode = nodes[srcRenderableID]
|
||||
)
|
||||
if !ok1 {
|
||||
srcRenderableID, ok := source2mapped[srcNodeID]
|
||||
if !ok {
|
||||
// One of the entries in dsts must be a non-pseudo node
|
||||
var existingDstNodeID string
|
||||
for _, dstNodeID := range dsts {
|
||||
@@ -199,33 +214,31 @@ func (m LeafMap) Render(rpt report.Report) RenderableNodes {
|
||||
}
|
||||
}
|
||||
|
||||
pseudoNode, ok := m.Pseudo(srcNodeID, existingDstNodeID, true, localNetworks)
|
||||
srcRenderableID, ok = mkPseudoNode(srcNodeID, existingDstNodeID, true)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
srcRenderableID = pseudoNode.ID
|
||||
srcRenderableNode = pseudoNode
|
||||
nodes[srcRenderableID] = srcRenderableNode
|
||||
source2mapped[srcNodeID] = srcRenderableID
|
||||
}
|
||||
srcRenderableNode := nodes[srcRenderableID]
|
||||
|
||||
for _, dstNodeID := range dsts {
|
||||
dstRenderableID, ok := source2mapped[dstNodeID]
|
||||
if !ok {
|
||||
pseudoNode, ok := m.Pseudo(dstNodeID, srcNodeID, false, localNetworks)
|
||||
dstRenderableID, ok = mkPseudoNode(dstNodeID, srcNodeID, false)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
dstRenderableID = pseudoNode.ID
|
||||
nodes[dstRenderableID] = pseudoNode
|
||||
source2mapped[dstNodeID] = dstRenderableID
|
||||
}
|
||||
dstRenderableNode := nodes[dstRenderableID]
|
||||
|
||||
srcRenderableNode.Adjacency = srcRenderableNode.Adjacency.Add(dstRenderableID)
|
||||
edgeID := report.MakeEdgeID(srcNodeID, dstNodeID)
|
||||
if md, ok := t.EdgeMetadatas[edgeID]; ok {
|
||||
|
||||
// We propagate edge metadata to nodes on both ends of the edges.
|
||||
// TODO we should 'reverse' one end of the edge meta data - ingress -> egress etc.
|
||||
if md, ok := t.EdgeMetadatas[report.MakeEdgeID(srcNodeID, dstNodeID)]; ok {
|
||||
srcRenderableNode.EdgeMetadata.Merge(md)
|
||||
dstRenderableNode.EdgeMetadata.Merge(md)
|
||||
nodes[dstRenderableID] = dstRenderableNode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user