mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-05 11:11:13 +00:00
refactor detailed key label rendering into a single dictionary
This commit is contained in:
58
render/detailed/labels.go
Normal file
58
render/detailed/labels.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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{},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user