Skip to content

Commit

Permalink
Merge pull request #298 from paulbellamy/154-inspect-connections
Browse files Browse the repository at this point in the history
Replace "Origin Endpoint" tables with "Connection Details" table
  • Loading branch information
paulbellamy committed Jul 3, 2015
2 parents 37c99b7 + 95f941f commit 94a0ace
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 95 deletions.
17 changes: 9 additions & 8 deletions experimental/demoprobe/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strconv"
"time"

"github.com/weaveworks/scope/probe/docker"
"github.com/weaveworks/scope/report"
)

Expand Down Expand Up @@ -70,17 +71,17 @@ func DemoReport(nodeCount int) report.Report {
// Endpoint topology
if _, ok := r.Endpoint.NodeMetadatas[srcPortID]; !ok {
r.Endpoint.NodeMetadatas[srcPortID] = report.NodeMetadata{
"pid": "4000",
"name": c.srcProc,
"domain": "node-" + src,
docker.PID: "4000",
docker.Name: c.srcProc,
docker.Domain: "node-" + src,
}
}
r.Endpoint.Adjacency[srcID] = r.Endpoint.Adjacency[srcID].Add(dstPortID)
if _, ok := r.Endpoint.NodeMetadatas[dstPortID]; !ok {
r.Endpoint.NodeMetadatas[dstPortID] = report.NodeMetadata{
"pid": "4000",
"name": c.dstProc,
"domain": "node-" + dst,
docker.PID: "4000",
docker.Name: c.dstProc,
docker.Domain: "node-" + dst,
}
}
r.Endpoint.Adjacency[dstID] = r.Endpoint.Adjacency[dstID].Add(srcPortID)
Expand All @@ -100,13 +101,13 @@ func DemoReport(nodeCount int) report.Report {
// Address topology
if _, ok := r.Address.NodeMetadatas[srcAddressID]; !ok {
r.Address.NodeMetadatas[srcAddressID] = report.NodeMetadata{
"name": src,
docker.Name: src,
}
}
r.Address.Adjacency[nodeSrcAddressID] = r.Address.Adjacency[nodeSrcAddressID].Add(dstAddressID)
if _, ok := r.Address.NodeMetadatas[dstAddressID]; !ok {
r.Address.NodeMetadatas[dstAddressID] = report.NodeMetadata{
"name": dst,
docker.Name: dst,
}
}
r.Address.Adjacency[nodeDstAddressID] = r.Address.Adjacency[nodeDstAddressID].Add(srcAddressID)
Expand Down
5 changes: 5 additions & 0 deletions probe/docker/tagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import (
// These constants are keys used in node metadata
// TODO: use these constants in report/{mapping.go, detailed_node.go} - pending some circular references
const (
Addr = "addr"
ContainerID = "docker_container_id"
Domain = "domain"
Name = "name"
PID = "pid"
Port = "port"
)

// These vars are exported for testing.
Expand Down
25 changes: 13 additions & 12 deletions probe/endpoint/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/prometheus/client_golang/prometheus"

"github.com/weaveworks/procspy"
"github.com/weaveworks/scope/probe/docker"
"github.com/weaveworks/scope/report"
)

Expand Down Expand Up @@ -80,16 +81,12 @@ func (r *Reporter) addConnection(rpt *report.Report, c *procspy.Connection) {

if _, ok := rpt.Address.NodeMetadatas[scopedLocal]; !ok {
rpt.Address.NodeMetadatas[scopedLocal] = report.NodeMetadata{
"name": r.hostName,
"addr": c.LocalAddress.String(),
docker.Name: r.hostName,
docker.Addr: c.LocalAddress.String(),
}
}

// Count the TCP connection.
edgeMeta := rpt.Address.EdgeMetadatas[edgeKey]
edgeMeta.WithConnCountTCP = true
edgeMeta.MaxConnCountTCP++
rpt.Address.EdgeMetadatas[edgeKey] = edgeMeta
countTCPConnection(rpt.Address.EdgeMetadatas, edgeKey)

if c.Proc.PID > 0 {
var (
Expand All @@ -111,10 +108,14 @@ func (r *Reporter) addConnection(rpt *report.Report, c *procspy.Connection) {

rpt.Endpoint.NodeMetadatas[scopedLocal] = md
}
// Count the TCP connection.
edgeMeta := rpt.Endpoint.EdgeMetadatas[edgeKey]
edgeMeta.WithConnCountTCP = true
edgeMeta.MaxConnCountTCP++
rpt.Endpoint.EdgeMetadatas[edgeKey] = edgeMeta

countTCPConnection(rpt.Endpoint.EdgeMetadatas, edgeKey)
}
}

func countTCPConnection(m report.EdgeMetadatas, edgeKey string) {
edgeMeta := m[edgeKey]
edgeMeta.WithConnCountTCP = true
edgeMeta.MaxConnCountTCP++
m[edgeKey] = edgeMeta
}
3 changes: 2 additions & 1 deletion probe/endpoint/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/weaveworks/procspy"
"github.com/weaveworks/scope/probe/docker"
"github.com/weaveworks/scope/probe/endpoint"
"github.com/weaveworks/scope/report"
)
Expand Down Expand Up @@ -95,7 +96,7 @@ func TestSpyNoProcesses(t *testing.T) {
t.Fatalf("want %q, have %q", want, have)
}

if want, have := nodeName, r.Address.NodeMetadatas[scopedLocal]["name"]; want != have {
if want, have := nodeName, r.Address.NodeMetadatas[scopedLocal][docker.Name]; want != have {
t.Fatalf("want %q, have %q", want, have)
}
}
Expand Down
44 changes: 23 additions & 21 deletions render/detailed_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package render

import (
"fmt"
"reflect"
"sort"
"strconv"

Expand Down Expand Up @@ -79,18 +78,17 @@ func MakeDetailedNode(r report.Report, n RenderableNode) DetailedNode {
// multiple origins. The ultimate goal here is to generate tables to view
// in the UI, so we skip the intermediate representations, but we could
// add them later.
outer:
connections := []Row{}
for _, id := range n.Origins {
if table, ok := OriginTable(r, id); ok {
// TODO there's a bug that yields duplicate tables. Quick fix.
for _, existing := range tables {
if reflect.DeepEqual(existing, table) {
continue outer
}
}
tables = append(tables, table)
} else if nmd, ok := r.Endpoint.NodeMetadatas[id]; ok {
connections = append(connections, connectionDetailsRows(r.Endpoint, id, nmd)...)
}
}
if len(connections) > 0 {
tables = append(tables, connectionDetailsTable(connections))
}

// Sort tables by rank
sort.Sort(tables)
Expand All @@ -107,9 +105,6 @@ outer:
// OriginTable produces a table (to be consumed directly by the UI) based on
// an origin ID, which is (optimistically) a node ID in one of our topologies.
func OriginTable(r report.Report, originID string) (Table, bool) {
if nmd, ok := r.Endpoint.NodeMetadatas[originID]; ok {
return endpointOriginTable(nmd)
}
if nmd, ok := r.Address.NodeMetadatas[originID]; ok {
return addressOriginTable(nmd)
}
Expand All @@ -128,22 +123,29 @@ func OriginTable(r report.Report, originID string) (Table, bool) {
return Table{}, false
}

func endpointOriginTable(nmd report.NodeMetadata) (Table, bool) {
func connectionDetailsRows(endpointTopology report.Topology, originID string, nmd report.NodeMetadata) []Row {
rows := []Row{}
for _, tuple := range []struct{ key, human string }{
{"addr", "Endpoint"},
{"port", "Port"},
} {
if val, ok := nmd[tuple.key]; ok {
rows = append(rows, Row{Key: tuple.human, ValueMajor: val, ValueMinor: ""})
local := fmt.Sprintf("%s:%s", nmd[docker.Addr], nmd[docker.Port])
adjacencies := endpointTopology.Adjacency[report.MakeAdjacencyID(originID)]
sort.Strings(adjacencies)
for _, adj := range adjacencies {
if _, address, port, ok := report.ParseEndpointNodeID(adj); ok {
rows = append(rows, Row{
Key: local,
ValueMajor: fmt.Sprintf("%s:%s", address, port),
})
}
}
return rows
}

func connectionDetailsTable(connectionRows []Row) Table {
return Table{
Title: "Origin Endpoint",
Title: "Connection Details",
Numeric: false,
Rows: rows,
Rows: append([]Row{{Key: "Local", ValueMajor: "Remote"}}, connectionRows...),
Rank: endpointRank,
}, len(rows) > 0
}
}

func addressOriginTable(nmd report.NodeMetadata) (Table, bool) {
Expand Down
44 changes: 33 additions & 11 deletions render/detailed_node_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package render_test

import (
"fmt"
"reflect"
"testing"

Expand All @@ -13,14 +14,6 @@ func TestOriginTable(t *testing.T) {
t.Errorf("unknown origin ID gave unexpected success")
}
for originID, want := range map[string]render.Table{
test.Client54001NodeID: {
Title: "Origin Endpoint",
Numeric: false,
Rows: []render.Row{
{"Endpoint", test.ClientIP, ""},
{"Port", test.ClientPort54001, ""},
},
},
test.ClientAddressNodeID: {
Title: "Origin Address",
Numeric: false,
Expand Down Expand Up @@ -107,11 +100,40 @@ func TestMakeDetailedNode(t *testing.T) {
},
},
{
Title: "Origin Endpoint",
Title: "Connection Details",
Numeric: false,
Rows: []render.Row{
{"Endpoint", test.ServerIP, ""},
{"Port", test.ServerPort, ""},
{"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),
"",
},
},
},
},
Expand Down
11 changes: 11 additions & 0 deletions report/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,17 @@ func ParseNodeID(nodeID string) (hostID string, remainder string, ok bool) {
return fields[0], fields[1], true
}

// ParseEndpointNodeID produces the host ID, address, and port and remainder
// (typically an address) from an endpoint node ID. Note that hostID may be
// blank.
func ParseEndpointNodeID(endpointNodeID string) (hostID, address, port string, ok bool) {
fields := strings.SplitN(endpointNodeID, ScopeDelim, 3)
if len(fields) != 3 {
return "", "", "", false
}
return fields[0], fields[1], fields[2], true
}

// ExtractHostID extracts the host id from NodeMetadata
func ExtractHostID(m NodeMetadata) string {
hostid, _, _ := ParseNodeID(m[HostNodeID])
Expand Down
36 changes: 36 additions & 0 deletions report/id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,42 @@ func TestAdjacencyID(t *testing.T) {
}
}

func TestEndpointNodeID(t *testing.T) {
for _, bad := range []string{
clientAddressNodeID,
serverAddressNodeID,
unknownAddressNodeID,
clientHostNodeID,
serverHostNodeID,
"host.com;1.2.3.4",
"a;b",
"a;",
";b",
";",
"",
} {
if haveName, haveAddress, havePort, ok := report.ParseEndpointNodeID(bad); ok {
t.Errorf("%q: expected failure, but got {%q, %q, %q}", bad, haveName, haveAddress, havePort)
}
}

for input, want := range map[string]struct{ name, address, port string }{
report.MakeEndpointNodeID("host.com", "1.2.3.4", "c"): {"", "1.2.3.4", "c"},
"a;b;c": {"a", "b", "c"},
} {
haveName, haveAddress, havePort, ok := report.ParseEndpointNodeID(input)
if !ok {
t.Errorf("%q: not OK", input)
continue
}
if want.name != haveName ||
want.address != haveAddress ||
want.port != havePort {
t.Errorf("%q: want %q, have {%q, %q, %q}", input, want, haveName, haveAddress, havePort)
}
}
}

func TestEdgeID(t *testing.T) {
for _, bad := range []string{
client54001EndpointNodeID,
Expand Down
Loading

0 comments on commit 94a0ace

Please sign in to comment.