mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 18:20:27 +00:00
Add host context in the details pane
In situations when the details can refer to entities from multiple hosts (e.g. container image) make explicit to what host we are referring to.
This commit is contained in:
@@ -68,7 +68,7 @@ func handleNode(rep xfer.Reporter, t topologyView, w http.ResponseWriter, r *htt
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
respondWith(w, http.StatusOK, APINode{Node: render.MakeDetailedNode(rpt, node)})
|
||||
respondWith(w, http.StatusOK, APINode{Node: render.MakeDetailedNode(rpt, node, t.isMultiHost)})
|
||||
}
|
||||
|
||||
// Individual edges.
|
||||
|
||||
@@ -107,9 +107,10 @@ var topologyRegistry = map[string]topologyView{
|
||||
renderer: render.FilterUnconnected{Renderer: render.ProcessWithContainerNameRenderer{}},
|
||||
},
|
||||
"applications-by-name": {
|
||||
human: "by name",
|
||||
parent: "applications",
|
||||
renderer: render.FilterUnconnected{Renderer: render.ProcessNameRenderer},
|
||||
human: "by name",
|
||||
parent: "applications",
|
||||
renderer: render.FilterUnconnected{Renderer: render.ProcessNameRenderer},
|
||||
isMultiHost: true,
|
||||
},
|
||||
"containers": {
|
||||
human: "Containers",
|
||||
@@ -117,9 +118,10 @@ var topologyRegistry = map[string]topologyView{
|
||||
renderer: render.ContainerRenderer,
|
||||
},
|
||||
"containers-by-image": {
|
||||
human: "by image",
|
||||
parent: "containers",
|
||||
renderer: render.ContainerImageRenderer,
|
||||
human: "by image",
|
||||
parent: "containers",
|
||||
renderer: render.ContainerImageRenderer,
|
||||
isMultiHost: true,
|
||||
},
|
||||
"hosts": {
|
||||
human: "Hosts",
|
||||
@@ -129,7 +131,8 @@ var topologyRegistry = map[string]topologyView{
|
||||
}
|
||||
|
||||
type topologyView struct {
|
||||
human string
|
||||
parent string
|
||||
renderer render.Renderer
|
||||
human string
|
||||
parent string
|
||||
renderer render.Renderer
|
||||
isMultiHost bool // does the view involve information from multiple hosts?
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func (t tables) Less(i, j int) bool { return t[i].Rank > t[j].Rank }
|
||||
|
||||
// MakeDetailedNode transforms a renderable node to a detailed node. It uses
|
||||
// aggregate metadata, plus the set of origin node IDs, to produce tables.
|
||||
func MakeDetailedNode(r report.Report, n RenderableNode) DetailedNode {
|
||||
func MakeDetailedNode(r report.Report, n RenderableNode, addHostTags bool) DetailedNode {
|
||||
tables := tables{}
|
||||
// RenderableNode may be the result of merge operation(s), and so may have
|
||||
// multiple origins. The ultimate goal here is to generate tables to view
|
||||
@@ -80,7 +80,7 @@ func MakeDetailedNode(r report.Report, n RenderableNode) DetailedNode {
|
||||
// add them later.
|
||||
connections := []Row{}
|
||||
for _, id := range n.Origins {
|
||||
if table, ok := OriginTable(r, id); ok {
|
||||
if table, ok := OriginTable(r, id, addHostTags); ok {
|
||||
tables = append(tables, table)
|
||||
} else if _, ok := r.Endpoint.NodeMetadatas[id]; ok {
|
||||
connections = append(connections, connectionDetailsRows(r.Endpoint, id)...)
|
||||
@@ -155,12 +155,12 @@ func addConnectionsTable(tables *tables, connections []Row, r report.Report, n R
|
||||
|
||||
// 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) {
|
||||
func OriginTable(r report.Report, originID string, addHostTags bool) (Table, bool) {
|
||||
if nmd, ok := r.Process.NodeMetadatas[originID]; ok {
|
||||
return processOriginTable(nmd)
|
||||
return processOriginTable(nmd, addHostTags)
|
||||
}
|
||||
if nmd, ok := r.Container.NodeMetadatas[originID]; ok {
|
||||
return containerOriginTable(nmd)
|
||||
return containerOriginTable(nmd, addHostTags)
|
||||
}
|
||||
if nmd, ok := r.ContainerImage.NodeMetadatas[originID]; ok {
|
||||
return containerImageOriginTable(nmd)
|
||||
@@ -224,7 +224,7 @@ func connectionDetailsRows(topology report.Topology, originID string) []Row {
|
||||
return rows
|
||||
}
|
||||
|
||||
func processOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
func processOriginTable(nmd report.NodeMetadata, addHostTag bool) (Table, bool) {
|
||||
rows := []Row{}
|
||||
for _, tuple := range []struct{ key, human string }{
|
||||
{process.Comm, "Name"},
|
||||
@@ -237,7 +237,9 @@ func processOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
rows = append(rows, Row{Key: tuple.human, ValueMajor: val, ValueMinor: ""})
|
||||
}
|
||||
}
|
||||
|
||||
if addHostTag {
|
||||
rows = append([]Row{{Key: "Host", ValueMajor: report.ExtractHostID(nmd)}}, rows...)
|
||||
}
|
||||
return Table{
|
||||
Title: "Origin Process",
|
||||
Numeric: false,
|
||||
@@ -246,7 +248,7 @@ func processOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
}, len(rows) > 0
|
||||
}
|
||||
|
||||
func containerOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
func containerOriginTable(nmd report.NodeMetadata, addHostTag bool) (Table, bool) {
|
||||
rows := []Row{}
|
||||
for _, tuple := range []struct{ key, human string }{
|
||||
{docker.ContainerID, "ID"},
|
||||
@@ -268,7 +270,9 @@ func containerOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
rows = append(rows, Row{Key: "Memory Usage (MB):", ValueMajor: memoryStr, ValueMinor: ""})
|
||||
}
|
||||
}
|
||||
|
||||
if addHostTag {
|
||||
rows = append([]Row{{Key: "Host", ValueMajor: report.ExtractHostID(nmd)}}, rows...)
|
||||
}
|
||||
return Table{
|
||||
Title: "Origin Container",
|
||||
Numeric: false,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func TestOriginTable(t *testing.T) {
|
||||
if _, ok := render.OriginTable(test.Report, "not-found"); ok {
|
||||
if _, ok := render.OriginTable(test.Report, "not-found", false); ok {
|
||||
t.Errorf("unknown origin ID gave unexpected success")
|
||||
}
|
||||
for originID, want := range map[string]render.Table{
|
||||
@@ -34,7 +34,7 @@ func TestOriginTable(t *testing.T) {
|
||||
},
|
||||
},
|
||||
} {
|
||||
have, ok := render.OriginTable(test.Report, originID)
|
||||
have, ok := render.OriginTable(test.Report, originID, false)
|
||||
if !ok {
|
||||
t.Errorf("%q: not OK", originID)
|
||||
continue
|
||||
@@ -43,11 +43,46 @@ func TestOriginTable(t *testing.T) {
|
||||
t.Errorf("%q: %s", originID, test.Diff(want, have))
|
||||
}
|
||||
}
|
||||
|
||||
// Test host tags
|
||||
for originID, want := range map[string]render.Table{
|
||||
test.ServerProcessNodeID: {
|
||||
Title: "Origin Process",
|
||||
Numeric: false,
|
||||
Rank: 2,
|
||||
Rows: []render.Row{
|
||||
{"Host", test.ServerHostID, "", false},
|
||||
{"Name", "apache", "", false},
|
||||
{"PID", test.ServerPID, "", false},
|
||||
},
|
||||
},
|
||||
test.ServerContainerNodeID: {
|
||||
Title: "Origin Container",
|
||||
Numeric: false,
|
||||
Rank: 3,
|
||||
Rows: []render.Row{
|
||||
{"Host", test.ServerHostID, "", false},
|
||||
{"ID", test.ServerContainerID, "", false},
|
||||
{"Name", "server", "", false},
|
||||
{"Image ID", test.ServerContainerImageID, "", false},
|
||||
},
|
||||
},
|
||||
} {
|
||||
have, ok := render.OriginTable(test.Report, originID, true)
|
||||
if !ok {
|
||||
t.Errorf("%q: not OK", originID)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(want, have) {
|
||||
t.Errorf("%q: %s", originID, test.Diff(want, have))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMakeDetailedHostNode(t *testing.T) {
|
||||
renderableNode := render.HostRenderer.Render(test.Report)[render.MakeHostID(test.ClientHostID)]
|
||||
have := render.MakeDetailedNode(test.Report, renderableNode)
|
||||
have := render.MakeDetailedNode(test.Report, renderableNode, false)
|
||||
want := render.DetailedNode{
|
||||
ID: render.MakeHostID(test.ClientHostID),
|
||||
LabelMajor: "client",
|
||||
@@ -109,7 +144,7 @@ func TestMakeDetailedHostNode(t *testing.T) {
|
||||
|
||||
func TestMakeDetailedContainerNode(t *testing.T) {
|
||||
renderableNode := render.ContainerRenderer.Render(test.Report)[test.ServerContainerID]
|
||||
have := render.MakeDetailedNode(test.Report, renderableNode)
|
||||
have := render.MakeDetailedNode(test.Report, renderableNode, false)
|
||||
want := render.DetailedNode{
|
||||
ID: test.ServerContainerID,
|
||||
LabelMajor: "server",
|
||||
|
||||
Reference in New Issue
Block a user