refactor detailed key label rendering into a single dictionary

This commit is contained in:
Paul Bellamy
2016-01-20 15:33:16 +00:00
parent 77949db711
commit e31520dddd
6 changed files with 125 additions and 77 deletions

58
render/detailed/labels.go Normal file
View File

@@ -0,0 +1,58 @@
package detailed
import (
"fmt"
"strings"
"github.com/weaveworks/scope/probe/docker"
"github.com/weaveworks/scope/probe/host"
"github.com/weaveworks/scope/probe/kubernetes"
"github.com/weaveworks/scope/probe/overlay"
"github.com/weaveworks/scope/probe/process"
)
var labels = map[string]string{
docker.CPUTotalUsage: "CPU",
docker.ContainerCommand: "Command",
docker.ContainerCreated: "Created",
docker.ContainerHostname: "Hostname",
docker.ContainerID: "ID",
docker.ContainerIPs: "IPs",
docker.ContainerPorts: "Ports",
docker.ContainerState: "State",
docker.ImageID: "Image ID",
docker.MemoryUsage: "Memory",
host.CPUUsage: "CPU",
host.HostName: "Hostname",
host.KernelVersion: "Kernel version",
host.Load15: "Load (15m)",
host.Load1: "Load (1m)",
host.Load5: "Load (5m)",
host.LocalNetworks: "Local Networks",
host.MemUsage: "Memory",
host.OS: "Operating system",
host.Uptime: "Uptime",
kubernetes.Namespace: "Namespace",
kubernetes.PodCreated: "Created",
kubernetes.PodID: "ID",
overlay.WeaveDNSHostname: "Weave DNS Hostname",
overlay.WeaveMACAddress: "Weave MAC",
// process.CPUUsage: "CPU", // Duplicate key!
process.Cmdline: "Command",
process.MemoryUsage: "Memory",
process.PID: "PID",
process.PPID: "Parent PID",
process.Threads: "# Threads",
}
// Label maps from the internal keys to the human-readable label for a piece
// of metadata/set/etc. If none is found the raw key will be returned.
func Label(key string) string {
if label, ok := labels[key]; ok {
return label
}
if strings.HasPrefix(key, "label_") {
return fmt.Sprintf("Label %q", strings.TrimPrefix(key, "label_"))
}
return key
}

View File

@@ -1,7 +1,7 @@
package detailed
import (
"fmt"
"encoding/json"
"sort"
"strings"
@@ -15,57 +15,69 @@ import (
var (
processNodeMetadata = renderMetadata(
meta(process.PID, "PID"),
meta(process.PPID, "Parent PID"),
meta(process.Cmdline, "Command"),
meta(process.Threads, "# Threads"),
meta(process.PID),
meta(process.PPID),
meta(process.Cmdline),
meta(process.Threads),
)
containerNodeMetadata = renderMetadata(
meta(docker.ContainerID, "ID"),
meta(docker.ImageID, "Image ID"),
ltst(docker.ContainerState, "State"),
sets(docker.ContainerIPs, "IPs"),
sets(docker.ContainerPorts, "Ports"),
meta(docker.ContainerCreated, "Created"),
meta(docker.ContainerCommand, "Command"),
meta(overlay.WeaveMACAddress, "Weave MAC"),
meta(overlay.WeaveDNSHostname, "Weave DNS Hostname"),
meta(docker.ContainerID),
meta(docker.ImageID),
ltst(docker.ContainerState),
sets(docker.ContainerIPs),
sets(docker.ContainerPorts),
meta(docker.ContainerCreated),
meta(docker.ContainerCommand),
meta(overlay.WeaveMACAddress),
meta(overlay.WeaveDNSHostname),
getDockerLabelRows,
)
containerImageNodeMetadata = renderMetadata(
meta(docker.ImageID, "Image ID"),
meta(docker.ImageID),
getDockerLabelRows,
)
podNodeMetadata = renderMetadata(
meta(kubernetes.PodID, "ID"),
meta(kubernetes.Namespace, "Namespace"),
meta(kubernetes.PodCreated, "Created"),
meta(kubernetes.PodID),
meta(kubernetes.Namespace),
meta(kubernetes.PodCreated),
)
hostNodeMetadata = renderMetadata(
meta(host.HostName, "Hostname"),
meta(host.OS, "Operating system"),
meta(host.KernelVersion, "Kernel version"),
meta(host.Uptime, "Uptime"),
sets(host.LocalNetworks, "Local Networks"),
meta(host.HostName),
meta(host.OS),
meta(host.KernelVersion),
meta(host.Uptime),
sets(host.LocalNetworks),
)
)
// MetadataRow is a row for the metadata table.
type MetadataRow struct {
ID string `json:"id"`
Label string `json:"label"`
Value string `json:"value"`
ID string
Value string
}
// Copy returns a value copy of a metadata row.
func (m MetadataRow) Copy() MetadataRow {
return MetadataRow{
ID: m.ID,
Label: m.Label,
Value: m.Value,
}
}
// MarshalJSON marshals this MetadataRow to json. It adds a label before
// rendering.
func (m MetadataRow) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
ID string `json:"id"`
Label string `json:"label"`
Value string `json:"value"`
}{
ID: m.ID,
Label: Label(m.ID),
Value: m.Value,
})
}
// NodeMetadata 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 NodeMetadata(n report.Node) []MetadataRow {
@@ -92,28 +104,28 @@ func renderMetadata(templates ...func(report.Node) []MetadataRow) func(report.No
}
}
func meta(id, label string) func(report.Node) []MetadataRow {
func meta(id string) func(report.Node) []MetadataRow {
return func(n report.Node) []MetadataRow {
if val, ok := n.Metadata[id]; ok {
return []MetadataRow{{ID: id, Label: label, Value: val}}
return []MetadataRow{{ID: id, Value: val}}
}
return nil
}
}
func sets(id, label string) func(report.Node) []MetadataRow {
func sets(id string) func(report.Node) []MetadataRow {
return func(n report.Node) []MetadataRow {
if val, ok := n.Sets[id]; ok && len(val) > 0 {
return []MetadataRow{{ID: id, Label: label, Value: strings.Join(val, ", ")}}
return []MetadataRow{{ID: id, Value: strings.Join(val, ", ")}}
}
return nil
}
}
func ltst(id, label string) func(report.Node) []MetadataRow {
func ltst(id string) func(report.Node) []MetadataRow {
return func(n report.Node) []MetadataRow {
if val, ok := n.Latest.Lookup(id); ok {
return []MetadataRow{{ID: id, Label: label, Value: val}}
return []MetadataRow{{ID: id, Value: val}}
}
return nil
}
@@ -129,7 +141,7 @@ func getDockerLabelRows(nmd report.Node) []MetadataRow {
}
sort.Strings(labelKeys)
for _, labelKey := range labelKeys {
rows = append(rows, MetadataRow{ID: "label_" + labelKey, Label: fmt.Sprintf("Label %q", labelKey), Value: labels[labelKey]})
rows = append(rows, MetadataRow{ID: "label_" + labelKey, Value: labels[labelKey]})
}
return rows
}

View File

@@ -26,12 +26,11 @@ func TestNodeMetadata(t *testing.T) {
docker.ContainerIPs: report.MakeStringSet("10.10.10.0/24", "10.10.10.1/24"),
}).WithLatest(docker.ContainerState, fixture.Now, docker.StateRunning),
want: []detailed.MetadataRow{
{ID: docker.ContainerID, Label: "ID", Value: fixture.ClientContainerID},
{ID: docker.ContainerState, Label: "State", Value: "running"},
{ID: docker.ContainerIPs, Label: "IPs", Value: "10.10.10.0/24, 10.10.10.1/24"},
{ID: docker.ContainerID, Value: fixture.ClientContainerID},
{ID: docker.ContainerState, Value: "running"},
{ID: docker.ContainerIPs, Value: "10.10.10.0/24, 10.10.10.1/24"},
{
ID: "label_label1",
Label: "Label \"label1\"",
Value: "label1value",
},
},

View File

@@ -18,19 +18,19 @@ const (
var (
processNodeMetrics = renderMetrics(
MetricRow{ID: process.CPUUsage, Label: "CPU", Format: percentFormat},
MetricRow{ID: process.MemoryUsage, Label: "Memory", Format: filesizeFormat},
MetricRow{ID: process.CPUUsage, Format: percentFormat},
MetricRow{ID: process.MemoryUsage, Format: filesizeFormat},
)
containerNodeMetrics = renderMetrics(
MetricRow{ID: docker.CPUTotalUsage, Label: "CPU", Format: percentFormat},
MetricRow{ID: docker.MemoryUsage, Label: "Memory", Format: filesizeFormat},
MetricRow{ID: docker.CPUTotalUsage, Format: percentFormat},
MetricRow{ID: docker.MemoryUsage, Format: filesizeFormat},
)
hostNodeMetrics = renderMetrics(
MetricRow{ID: host.CPUUsage, Label: "CPU", Format: percentFormat},
MetricRow{ID: host.MemUsage, Label: "Memory", Format: filesizeFormat},
MetricRow{ID: host.Load1, Label: "Load (1m)", Format: defaultFormat, Group: "load"},
MetricRow{ID: host.Load5, Label: "Load (5m)", Format: defaultFormat, Group: "load"},
MetricRow{ID: host.Load15, Label: "Load (15m)", Format: defaultFormat, Group: "load"},
MetricRow{ID: host.CPUUsage, Format: percentFormat},
MetricRow{ID: host.MemUsage, Format: filesizeFormat},
MetricRow{ID: host.Load1, Format: defaultFormat, Group: "load"},
MetricRow{ID: host.Load5, Format: defaultFormat, Group: "load"},
MetricRow{ID: host.Load15, Format: defaultFormat, Group: "load"},
)
)
@@ -38,7 +38,6 @@ var (
// accoutrements.
type MetricRow struct {
ID string
Label string
Format string
Group string
Value float64
@@ -49,7 +48,6 @@ type MetricRow struct {
func (m MetricRow) Copy() MetricRow {
row := MetricRow{
ID: m.ID,
Label: m.Label,
Format: m.Format,
Group: m.Group,
Value: m.Value,
@@ -73,7 +71,7 @@ func (m MetricRow) MarshalJSON() ([]byte, error) {
report.WireMetrics
}{
ID: m.ID,
Label: m.Label,
Label: Label(m.ID),
Format: m.Format,
Group: m.Group,
Value: m.Value,

View File

@@ -25,7 +25,6 @@ func TestNodeMetrics(t *testing.T) {
want: []detailed.MetricRow{
{
ID: process.CPUUsage,
Label: "CPU",
Format: "percent",
Group: "",
Value: 0.01,
@@ -33,7 +32,6 @@ func TestNodeMetrics(t *testing.T) {
},
{
ID: process.MemoryUsage,
Label: "Memory",
Format: "filesize",
Group: "",
Value: 0.01,
@@ -47,7 +45,6 @@ func TestNodeMetrics(t *testing.T) {
want: []detailed.MetricRow{
{
ID: docker.CPUTotalUsage,
Label: "CPU",
Format: "percent",
Group: "",
Value: 0.01,
@@ -55,7 +52,6 @@ func TestNodeMetrics(t *testing.T) {
},
{
ID: docker.MemoryUsage,
Label: "Memory",
Format: "filesize",
Group: "",
Value: 0.01,
@@ -69,7 +65,6 @@ func TestNodeMetrics(t *testing.T) {
want: []detailed.MetricRow{
{
ID: host.CPUUsage,
Label: "CPU",
Format: "percent",
Group: "",
Value: 0.01,
@@ -77,7 +72,6 @@ func TestNodeMetrics(t *testing.T) {
},
{
ID: host.MemUsage,
Label: "Memory",
Format: "filesize",
Group: "",
Value: 0.01,
@@ -85,21 +79,18 @@ func TestNodeMetrics(t *testing.T) {
},
{
ID: host.Load1,
Label: "Load (1m)",
Group: "load",
Value: 0.01,
Metric: &fixture.LoadMetric,
},
{
ID: host.Load5,
Label: "Load (5m)",
Group: "load",
Value: 0.01,
Metric: &fixture.LoadMetric,
},
{
ID: host.Load15,
Label: "Load (15m)",
Group: "load",
Value: 0.01,
Metric: &fixture.LoadMetric,

View File

@@ -32,17 +32,14 @@ func TestMakeDetailedHostNode(t *testing.T) {
Metadata: []detailed.MetadataRow{
{
ID: "host_name",
Label: "Hostname",
Value: "client.hostname.com",
},
{
ID: "os",
Label: "Operating system",
Value: "Linux",
},
{
ID: "local_networks",
Label: "Local Networks",
Value: "10.10.10.0/24",
},
},
@@ -50,34 +47,29 @@ func TestMakeDetailedHostNode(t *testing.T) {
{
ID: host.CPUUsage,
Format: "percent",
Label: "CPU",
Value: 0.01,
Metric: &fixture.CPUMetric,
},
{
ID: host.MemUsage,
Format: "filesize",
Label: "Memory",
Value: 0.01,
Metric: &fixture.MemoryMetric,
},
{
ID: host.Load1,
Group: "load",
Label: "Load (1m)",
Value: 0.01,
Metric: &fixture.LoadMetric,
},
{
ID: host.Load5,
Group: "load",
Label: "Load (5m)",
Value: 0.01,
Metric: &fixture.LoadMetric,
},
{
ID: host.Load15,
Label: "Load (15m)",
Group: "load",
Value: 0.01,
Metric: &fixture.LoadMetric,
@@ -126,26 +118,24 @@ func TestMakeDetailedContainerNode(t *testing.T) {
Label: "server",
Linkable: true,
Metadata: []detailed.MetadataRow{
{ID: "docker_container_id", Label: "ID", Value: fixture.ServerContainerID},
{ID: "docker_image_id", Label: "Image ID", Value: fixture.ServerContainerImageID},
{ID: "docker_container_state", Label: "State", Value: "running"},
{ID: "label_" + render.AmazonECSContainerNameLabel, Label: fmt.Sprintf(`Label %q`, render.AmazonECSContainerNameLabel), Value: `server`},
{ID: "label_foo1", Label: `Label "foo1"`, Value: `bar1`},
{ID: "label_foo2", Label: `Label "foo2"`, Value: `bar2`},
{ID: "label_io.kubernetes.pod.name", Label: `Label "io.kubernetes.pod.name"`, Value: "ping/pong-b"},
{ID: "docker_container_id", Value: fixture.ServerContainerID},
{ID: "docker_image_id", Value: fixture.ServerContainerImageID},
{ID: "docker_container_state", Value: "running"},
{ID: "label_" + render.AmazonECSContainerNameLabel, Value: `server`},
{ID: "label_foo1", Value: `bar1`},
{ID: "label_foo2", Value: `bar2`},
{ID: "label_io.kubernetes.pod.name", Value: "ping/pong-b"},
},
Metrics: []detailed.MetricRow{
{
ID: docker.CPUTotalUsage,
Format: "percent",
Label: "CPU",
Value: 0.01,
Metric: &fixture.CPUMetric,
},
{
ID: docker.MemoryUsage,
Format: "filesize",
Label: "Memory",
Value: 0.01,
Metric: &fixture.MemoryMetric,
},
@@ -165,7 +155,7 @@ func TestMakeDetailedContainerNode(t *testing.T) {
Label: "apache",
Linkable: true,
Metadata: []detailed.MetadataRow{
{ID: process.PID, Label: "PID", Value: fixture.ServerPID},
{ID: process.PID, Value: fixture.ServerPID},
},
Metrics: []detailed.MetricRow{},
},