diff --git a/render/detailed/summary.go b/render/detailed/summary.go index 0892d014f..7779cc1e2 100644 --- a/render/detailed/summary.go +++ b/render/detailed/summary.go @@ -124,9 +124,10 @@ func (n NodeSummary) Copy() NodeSummary { } func baseNodeSummary(r report.Report, n report.Node) NodeSummary { + t, _ := r.Topology(n.Topology) return NodeSummary{ ID: n.ID, - Shape: topologyShape(r, n.Topology), + Shape: t.GetShape(), Linkable: true, Metadata: NodeMetadata(r, n), Metrics: NodeMetrics(r, n), @@ -298,18 +299,18 @@ func groupNodeSummary(base NodeSummary, r report.Report, n report.Node) (NodeSum } base.Label, base.Rank = label, label - if count, ok := n.Counters.Lookup(parts[1]); ok { - base.LabelMinor = fmt.Sprintf("%d %s", count, parts[1]) - if count != 1 { - if strings.HasSuffix(parts[1], "s") { - base.LabelMinor += "es" + t, ok := r.Topology(parts[1]) + if ok && t.Label != "" { + if count, ok := n.Counters.Lookup(parts[1]); ok { + if count == 1 { + base.LabelMinor = fmt.Sprintf("%d %s", count, t.Label) } else { - base.LabelMinor += "s" + base.LabelMinor = fmt.Sprintf("%d %s", count, t.LabelPlural) } } } - base.Shape = topologyShape(r, parts[1]) + base.Shape = t.GetShape() base.Stack = true return base, true } @@ -373,10 +374,3 @@ func getRenderableContainerName(nmd report.Node) string { } return "" } - -func topologyShape(r report.Report, topology string) string { - if t, ok := r.Topology(topology); ok && t.Shape != "" { - return t.Shape - } - return report.Circle -} diff --git a/report/metadata_template.go b/report/metadata_template.go index 3091ba730..16d99af31 100644 --- a/report/metadata_template.go +++ b/report/metadata_template.go @@ -30,13 +30,7 @@ type MetadataTemplate struct { // Copy returns a value-copy of the template func (t MetadataTemplate) Copy() MetadataTemplate { - return MetadataTemplate{ - ID: t.ID, - Label: t.Label, - Truncate: t.Truncate, - Priority: t.Priority, - From: t.From, - } + return t } // MetadataRows returns the rows for a node diff --git a/report/report.go b/report/report.go index 3475efa0f..7488f6087 100644 --- a/report/report.go +++ b/report/report.go @@ -103,19 +103,39 @@ type Report struct { // MakeReport makes a clean report, ready to Merge() other reports into. func MakeReport() Report { return Report{ - Endpoint: MakeTopology(), - Process: MakeTopology().WithShape(Square), - Container: MakeTopology().WithShape(Hexagon), - ContainerImage: MakeTopology().WithShape(Hexagon), - Host: MakeTopology().WithShape(Circle), - Pod: MakeTopology().WithShape(Heptagon), - Service: MakeTopology().WithShape(Heptagon), - Overlay: MakeTopology(), - Sampling: Sampling{}, - Window: 0, - Plugins: xfer.MakePluginSpecs(), - ID: fmt.Sprintf("%d", rand.Int63()), - Probes: Probes{}, + Endpoint: MakeTopology(), + + Process: MakeTopology(). + WithShape(Square). + WithLabel("process", "processes"), + + Container: MakeTopology(). + WithShape(Hexagon). + WithLabel("container", "containers"), + + ContainerImage: MakeTopology(). + WithShape(Hexagon). + WithLabel("image", "images"), + + Host: MakeTopology(). + WithShape(Circle). + WithLabel("host", "hosts"), + + Pod: MakeTopology(). + WithShape(Heptagon). + WithLabel("pod", "pods"), + + Service: MakeTopology(). + WithShape(Heptagon). + WithLabel("service", "services"), + + Overlay: MakeTopology(), + + Sampling: Sampling{}, + Window: 0, + Plugins: xfer.MakePluginSpecs(), + ID: fmt.Sprintf("%d", rand.Int63()), + Probes: Probes{}, } } diff --git a/report/table.go b/report/table.go index 806a1b23c..25052640b 100644 --- a/report/table.go +++ b/report/table.go @@ -60,13 +60,9 @@ type TableTemplate struct { Prefix string `json:"prefix"` } -// Copy returns a copy of the TableTemplate +// Copy returns a value-copy of the TableTemplate func (t TableTemplate) Copy() TableTemplate { - return TableTemplate{ - ID: t.ID, - Label: t.Label, - Prefix: t.Prefix, - } + return t } // Merge other into t, returning a fresh copy. Does fieldwise max - diff --git a/report/topology.go b/report/topology.go index f648d9351..989cdfbd2 100644 --- a/report/topology.go +++ b/report/topology.go @@ -11,6 +11,8 @@ import ( // in the Node struct. type Topology struct { Shape string `json:"shape,omitempty"` + Label string `json:"label,omitempty"` + LabelPlural string `json:"label_plural,omitempty"` Nodes `json:"nodes"` Controls `json:"controls,omitempty"` MetadataTemplates `json:"metadata_templates,omitempty"` @@ -21,7 +23,6 @@ type Topology struct { // MakeTopology gives you a Topology. func MakeTopology() Topology { return Topology{ - Shape: Circle, Nodes: map[string]Node{}, Controls: Controls{}, } @@ -32,6 +33,8 @@ func MakeTopology() Topology { func (t Topology) WithMetadataTemplates(other MetadataTemplates) Topology { return Topology{ Shape: t.Shape, + Label: t.Label, + LabelPlural: t.LabelPlural, Nodes: t.Nodes.Copy(), Controls: t.Controls.Copy(), MetadataTemplates: t.MetadataTemplates.Merge(other), @@ -45,6 +48,8 @@ func (t Topology) WithMetadataTemplates(other MetadataTemplates) Topology { func (t Topology) WithMetricTemplates(other MetricTemplates) Topology { return Topology{ Shape: t.Shape, + Label: t.Label, + LabelPlural: t.LabelPlural, Nodes: t.Nodes.Copy(), Controls: t.Controls.Copy(), MetadataTemplates: t.MetadataTemplates.Copy(), @@ -58,6 +63,8 @@ func (t Topology) WithMetricTemplates(other MetricTemplates) Topology { func (t Topology) WithTableTemplates(other TableTemplates) Topology { return Topology{ Shape: t.Shape, + Label: t.Label, + LabelPlural: t.LabelPlural, Nodes: t.Nodes.Copy(), Controls: t.Controls.Copy(), MetadataTemplates: t.MetadataTemplates.Copy(), @@ -66,10 +73,26 @@ func (t Topology) WithTableTemplates(other TableTemplates) Topology { } } -// WithShape sets the shape nodes of this topology, returning a new topology. +// WithShape sets the shape of nodes from this topology, returning a new topology. func (t Topology) WithShape(shape string) Topology { return Topology{ Shape: shape, + Label: t.Label, + LabelPlural: t.LabelPlural, + Nodes: t.Nodes.Copy(), + Controls: t.Controls.Copy(), + MetadataTemplates: t.MetadataTemplates.Copy(), + MetricTemplates: t.MetricTemplates.Copy(), + TableTemplates: t.TableTemplates.Copy(), + } +} + +// WithLabel sets the label terminology of this topology, returning a new topology. +func (t Topology) WithLabel(label, labelPlural string) Topology { + return Topology{ + Shape: t.Shape, + Label: label, + LabelPlural: labelPlural, Nodes: t.Nodes.Copy(), Controls: t.Controls.Copy(), MetadataTemplates: t.MetadataTemplates.Copy(), @@ -91,10 +114,20 @@ func (t Topology) AddNode(node Node) Topology { return t } +// GetShape returns the current topology shape, or the default if there isn't one. +func (t Topology) GetShape() string { + if t.Shape == "" { + return Circle + } + return t.Shape +} + // Copy returns a value copy of the Topology. func (t Topology) Copy() Topology { return Topology{ Shape: t.Shape, + Label: t.Label, + LabelPlural: t.LabelPlural, Nodes: t.Nodes.Copy(), Controls: t.Controls.Copy(), MetadataTemplates: t.MetadataTemplates.Copy(), @@ -107,12 +140,17 @@ func (t Topology) Copy() Topology { // The original is not modified. func (t Topology) Merge(other Topology) Topology { shape := t.Shape - // A circle is the lowliest shape. - if shape == Circle { + if shape == "" { shape = other.Shape } + label, labelPlural := t.Label, t.LabelPlural + if label == "" { + label, labelPlural = other.Label, other.LabelPlural + } return Topology{ - Shape: t.Shape, + Shape: shape, + Label: label, + LabelPlural: labelPlural, Nodes: t.Nodes.Merge(other.Nodes), Controls: t.Controls.Merge(other.Controls), MetadataTemplates: t.MetadataTemplates.Merge(other.MetadataTemplates), diff --git a/test/fixture/report_fixture.go b/test/fixture/report_fixture.go index 5a9a9e33f..eff141875 100644 --- a/test/fixture/report_fixture.go +++ b/test/fixture/report_fixture.go @@ -248,7 +248,7 @@ var ( }, MetadataTemplates: process.MetadataTemplates, MetricTemplates: process.MetricTemplates, - }, + }.WithShape(report.Square).WithLabel("process", "processes"), Container: report.Topology{ Nodes: report.Nodes{ ClientContainerNodeID: report.MakeNodeWith( @@ -299,7 +299,7 @@ var ( }, MetadataTemplates: docker.ContainerMetadataTemplates, MetricTemplates: docker.ContainerMetricTemplates, - }, + }.WithShape(report.Hexagon).WithLabel("container", "containers"), ContainerImage: report.Topology{ Nodes: report.Nodes{ ClientContainerImageNodeID: report.MakeNodeWith(ClientContainerImageNodeID, map[string]string{ @@ -322,7 +322,7 @@ var ( ).WithTopology(report.ContainerImage), }, MetadataTemplates: docker.ContainerImageMetadataTemplates, - }, + }.WithShape(report.Hexagon).WithLabel("image", "images"), Host: report.Topology{ Nodes: report.Nodes{ ClientHostNodeID: report.MakeNodeWith( @@ -356,7 +356,7 @@ var ( }, MetadataTemplates: host.MetadataTemplates, MetricTemplates: host.MetricTemplates, - }, + }.WithShape(report.Circle).WithLabel("host", "hosts"), Pod: report.Topology{ Nodes: report.Nodes{ ClientPodNodeID: report.MakeNodeWith( @@ -388,7 +388,7 @@ var ( ), }, MetadataTemplates: kubernetes.PodMetadataTemplates, - }, + }.WithShape(report.Heptagon).WithLabel("pod", "pods"), Service: report.Topology{ Nodes: report.Nodes{ ServiceNodeID: report.MakeNodeWith( @@ -400,7 +400,7 @@ var ( }). WithTopology(report.Service), }, - }, + }.WithShape(report.Heptagon).WithLabel("service", "services"), Sampling: report.Sampling{ Count: 1024, Total: 4096,