Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Put real information in the detail struct #27

Merged
merged 1 commit into from
May 12, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions scope/app/api_origin.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,33 @@ func makeOriginHandler(rep Reporter) func(http.ResponseWriter, *http.Request) {
var (
vars = mux.Vars(r)
nodeID = vars["id"]
rpt = rep.Report()
)

host, ok := rpt.HostMetadatas[nodeID]
origin, ok := getOrigin(rep, nodeID)
if !ok {
http.NotFound(w, r)
return
}
respondWith(w, http.StatusOK, origin)
}
}

var addrs []string
for _, l := range host.LocalNets {
addrs = append(addrs, l.String())
}
func getOrigin(rep Reporter, nodeID string) (Origin, bool) {
host, ok := rep.Report().HostMetadatas[nodeID]
if !ok {
return Origin{}, false
}

respondWith(w, http.StatusOK, Origin{
Hostname: host.Hostname,
OS: host.OS,
Addresses: addrs,
LoadOne: host.LoadOne,
LoadFive: host.LoadFive,
LoadFifteen: host.LoadFifteen,
})
var addrs []string
for _, l := range host.LocalNets {
addrs = append(addrs, l.String())
}

return Origin{
Hostname: host.Hostname,
OS: host.OS,
Addresses: addrs,
LoadOne: host.LoadOne,
LoadFive: host.LoadFive,
LoadFifteen: host.LoadFifteen,
}, true
}
71 changes: 48 additions & 23 deletions scope/app/api_topology.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package main

import (
"fmt"
"net/http"
"strconv"
"time"

"github.com/gorilla/mux"
"github.com/gorilla/websocket"

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

Expand Down Expand Up @@ -85,7 +88,8 @@ func makeTopologyHandlers(
http.NotFound(w, r)
return
}
respondWith(w, http.StatusOK, APINode{Node: makeDetailed(node)})
of := func(nodeID string) (Origin, bool) { return getOrigin(rep, nodeID) }
respondWith(w, http.StatusOK, APINode{Node: makeDetailed(node, of)})
})

// Individual edges.
Expand All @@ -95,39 +99,51 @@ func makeTopologyHandlers(
localID = vars["local"]
remoteID = vars["remote"]
rpt = rep.Report()
metadata = topo(rpt).EdgeMetadata(mapping, grouped, localID, remoteID).Render()
metadata = topo(rpt).EdgeMetadata(mapping, grouped, localID, remoteID).Transform()
)
respondWith(w, http.StatusOK, APIEdge{Metadata: metadata})
})
}

// TODO(pb): temporary hack
func makeDetailed(n report.RenderableNode) report.DetailedNode {
func makeDetailed(n report.RenderableNode, of func(string) (Origin, bool)) report.DetailedNode {
// A RenderableNode may be the result of merge operation(s), and so may
// have multiple origins.
origins := []report.Table{}
for _, originID := range n.Origin {
origin, ok := of(originID)
if !ok {
origin = unknownOrigin
}
origins = append(origins, report.Table{
Title: "Origin",
Numeric: false,
Rows: []report.Row{
{"Hostname", origin.Hostname, ""},
{"Load", fmt.Sprintf("%.2f %.2f %.2f", origin.LoadOne, origin.LoadFive, origin.LoadFifteen), ""},
{"OS", origin.OS, ""},
//{"Addresses", strings.Join(origin.Addresses, ", "), ""},
{"ID", originID, ""},
},
})
}

tables := []report.Table{}
tables = append(tables, report.Table{
Title: "Connections",
Numeric: true,
Rows: []report.Row{
{"TCP (max)", strconv.FormatInt(int64(n.Metadata[report.KeyMaxConnCountTCP]), 10), ""},
},
})
tables = append(tables, origins...)

return report.DetailedNode{
ID: n.ID,
LabelMajor: n.LabelMajor,
LabelMinor: n.LabelMinor,
Pseudo: n.Pseudo,
Tables: []report.Table{
{"Bandwidth", true, []report.Row{
{"Ingress", "25", "KB/s"},
{"Egress", "44", "KB/s"},
}},
{"Ingress", true, []report.Row{
{"10.11.12.13", "20", "KB/s"},
{"172.16.121.199", "3", "KB/s"},
{"99.85.101.122", "1", "KB/s"},
}},
{"Egress", true, []report.Row{
{"10.11.12.13", "43", "KB/s"},
{"172.16.121.199", "1", "KB/s"},
}},
{"Origin", false, []report.Row{
{"Hostname", "foo.bar.com", ""},
{"Load", "3.30 2.11 0.92", ""},
{"OS", "Linux", ""},
}},
},
Tables: tables,
}
}

Expand Down Expand Up @@ -180,3 +196,12 @@ func handleWebsocket(
}
}
}

var unknownOrigin = Origin{
Hostname: "unknown",
OS: "unknown",
Addresses: []string{},
LoadOne: 0.0,
LoadFive: 0.0,
LoadFifteen: 0.0,
}
29 changes: 16 additions & 13 deletions scope/report/metadata.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
package report

// AggregateMetadata is the per-second version of a EdgeMetadata. Rates,
// rather than counts. Only keys which are known are set, but they may be 0.
// AggregateMetadata is a composable version of an EdgeMetadata. It's used
// when we want to merge nodes/edges for any reason, or
//
// Even though we base it on EdgeMetadata, we can apply it to nodes, by
// summing up (merging) all of the {ingress, egress} metadatas of the
// {incoming, outgoing} edges to the node.
type AggregateMetadata map[string]int

const (
keyBytesIngress = "ingress_bytes"
keyBytesEgress = "egress_bytes"
keyMaxConnCountTCP = "max_conn_count_tcp"
// KeyBytesIngress is the aggregate metadata key for the total count of
// ingress bytes.
KeyBytesIngress = "ingress_bytes"
// KeyBytesEgress is the aggregate metadata key for the total count of
// egress bytes.
KeyBytesEgress = "egress_bytes"
// KeyMaxConnCountTCP is the aggregate metadata key for the maximum number
// of simultaneous observed TCP connections in the window.
KeyMaxConnCountTCP = "max_conn_count_tcp"
)

// Render calculates a AggregateMetadata from an EdgeMetadata.
func (md EdgeMetadata) Render() AggregateMetadata {
// Transform calculates a AggregateMetadata from an EdgeMetadata.
func (md EdgeMetadata) Transform() AggregateMetadata {
m := AggregateMetadata{}

if md.WithBytes {
m[keyBytesIngress] = int(md.BytesIngress)
m[keyBytesEgress] = int(md.BytesEgress)
m[KeyBytesIngress] = int(md.BytesIngress)
m[KeyBytesEgress] = int(md.BytesEgress)
}

if md.WithConnCountTCP {
// The maximum is the maximum. No need to calculate anything.
m[keyMaxConnCountTCP] = int(md.MaxConnCountTCP)
m[KeyMaxConnCountTCP] = int(md.MaxConnCountTCP)
}

return m
}

Expand Down
16 changes: 8 additions & 8 deletions scope/report/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ func TestAggregateMetadata(t *testing.T) {
WithConnCountTCP: true,
MaxConnCountTCP: 400,
}: {
keyMaxConnCountTCP: 400,
KeyMaxConnCountTCP: 400,
},

// Connection count rounding
EdgeMetadata{
WithConnCountTCP: true,
MaxConnCountTCP: 4,
}: {
keyMaxConnCountTCP: 4,
KeyMaxConnCountTCP: 4,
},

// 0 connections.
EdgeMetadata{
WithConnCountTCP: true,
MaxConnCountTCP: 0,
}: {
keyMaxConnCountTCP: 0,
KeyMaxConnCountTCP: 0,
},

// Egress
Expand All @@ -38,8 +38,8 @@ func TestAggregateMetadata(t *testing.T) {
BytesEgress: 24,
BytesIngress: 0,
}: {
keyBytesEgress: 24,
keyBytesIngress: 0,
KeyBytesEgress: 24,
KeyBytesIngress: 0,
},

// Ingress
Expand All @@ -48,14 +48,14 @@ func TestAggregateMetadata(t *testing.T) {
BytesEgress: 0,
BytesIngress: 1200,
}: {
keyBytesEgress: 0,
keyBytesIngress: 1200,
KeyBytesEgress: 0,
KeyBytesIngress: 1200,
},

// Nothing there.
EdgeMetadata{}: {},
} {
if have := from.Render(); !reflect.DeepEqual(have, want) {
if have := from.Transform(); !reflect.DeepEqual(have, want) {
t.Errorf("have: %#v, want %#v", have, want)
}

Expand Down
12 changes: 6 additions & 6 deletions scope/report/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ type NodeMetadatas map[string]NodeMetadata
// conceivably (and usefully) collect about an edge between two nodes in any
// topology.
type EdgeMetadata struct {
WithBytes bool
BytesIngress uint // dst -> src
BytesEgress uint // src -> dst
WithBytes bool `json:"with_bytes,omitempty"`
BytesIngress uint `json:"bytes_ingress,omitempty"` // dst -> src
BytesEgress uint `json:"bytes_egress,omitempty"` // src -> dst

WithConnCountTCP bool
MaxConnCountTCP uint
WithConnCountTCP bool `json:"with_conn_count_tcp,omitempty"`
MaxConnCountTCP uint `json:"max_conn_count_tcp,omitempty"`
}

// NodeMetadata describes a superset of the metadata that probes can collect
Expand Down Expand Up @@ -137,7 +137,7 @@ func (t Topology) RenderBy(f MapFunc, grouped bool) map[string]RenderableNode {
srcRenderableNode.Adjacency = srcRenderableNode.Adjacency.Add(dstRenderableID)
edgeID := srcNodeAddress + IDDelim + dstNodeAddress
if md, ok := t.EdgeMetadatas[edgeID]; ok {
srcRenderableNode.Metadata.Merge(md.Render())
srcRenderableNode.Metadata.Merge(md.Transform())
}
}

Expand Down
2 changes: 1 addition & 1 deletion scope/xfer/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func reportCollector(ip string, col chan<- report.Report, quit <-chan struct{})
log.Printf("decode error: %v", err)
break
}
log.Printf("collector: got a report from %v", ip)
//log.Printf("collector: got a report from %v", ip)

select {
case col <- report:
Expand Down