mirror of
https://github.com/weaveworks/scope.git
synced 2026-05-06 01:08:03 +00:00
@@ -556,9 +556,9 @@ func captureReporter(rep Reporter, metricsGraphURL string, f reporterHandler) Ct
|
||||
}
|
||||
}
|
||||
|
||||
type rendererHandler func(context.Context, render.Renderer, render.Decorator, report.Report, string, http.ResponseWriter, *http.Request)
|
||||
type rendererHandler func(context.Context, render.Renderer, render.Decorator, report.RenderContext, http.ResponseWriter, *http.Request)
|
||||
|
||||
func (r *Registry) captureRenderer(rep Reporter, metricGraphsURL string, f rendererHandler) CtxHandlerFunc {
|
||||
func (r *Registry) captureRenderer(rep Reporter, metricsGraphURL string, f rendererHandler) CtxHandlerFunc {
|
||||
return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
var (
|
||||
topologyID = mux.Vars(req)["topology"]
|
||||
@@ -579,6 +579,6 @@ func (r *Registry) captureRenderer(rep Reporter, metricGraphsURL string, f rende
|
||||
respondWith(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
f(ctx, renderer, decorator, rpt, metricGraphsURL, w, req)
|
||||
f(ctx, renderer, decorator, report.RenderContext{Report: rpt, MetricsGraphURL: metricsGraphURL}, w, req)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,27 +29,27 @@ type APINode struct {
|
||||
}
|
||||
|
||||
// Full topology.
|
||||
func handleTopology(ctx context.Context, renderer render.Renderer, decorator render.Decorator, report report.Report, metricsGraphURL string, w http.ResponseWriter, r *http.Request) {
|
||||
func handleTopology(ctx context.Context, renderer render.Renderer, decorator render.Decorator, rc report.RenderContext, w http.ResponseWriter, r *http.Request) {
|
||||
respondWith(w, http.StatusOK, APITopology{
|
||||
Nodes: detailed.Summaries(report, renderer.Render(report, decorator), metricsGraphURL),
|
||||
Nodes: detailed.Summaries(rc, renderer.Render(rc.Report, decorator)),
|
||||
})
|
||||
}
|
||||
|
||||
// Individual nodes.
|
||||
func handleNode(ctx context.Context, renderer render.Renderer, decorator render.Decorator, report report.Report, metricsGraphURL string, w http.ResponseWriter, r *http.Request) {
|
||||
func handleNode(ctx context.Context, renderer render.Renderer, decorator render.Decorator, rc report.RenderContext, w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
topologyID = vars["topology"]
|
||||
nodeID = vars["id"]
|
||||
preciousRenderer = render.PreciousNodeRenderer{PreciousNodeID: nodeID, Renderer: renderer}
|
||||
rendered = preciousRenderer.Render(report, decorator)
|
||||
rendered = preciousRenderer.Render(rc.Report, decorator)
|
||||
node, ok = rendered[nodeID]
|
||||
)
|
||||
if !ok {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
respondWith(w, http.StatusOK, APINode{Node: detailed.MakeNode(topologyID, report, rendered, node, metricsGraphURL)})
|
||||
respondWith(w, http.StatusOK, APINode{Node: detailed.MakeNode(topologyID, rc, rendered, node)})
|
||||
}
|
||||
|
||||
// Websocket for the full topology.
|
||||
@@ -114,17 +114,20 @@ func handleWebsocket(
|
||||
// might be interested in implementing in the future.
|
||||
timestampDelta := time.Since(channelOpenedAt)
|
||||
reportTimestamp := startReportingAt.Add(timestampDelta)
|
||||
report, err := rep.Report(ctx, reportTimestamp)
|
||||
re, err := rep.Report(ctx, reportTimestamp)
|
||||
if err != nil {
|
||||
log.Errorf("Error generating report: %v", err)
|
||||
return
|
||||
}
|
||||
renderer, decorator, err := topologyRegistry.RendererForTopology(topologyID, r.Form, report)
|
||||
renderer, decorator, err := topologyRegistry.RendererForTopology(topologyID, r.Form, re)
|
||||
if err != nil {
|
||||
log.Errorf("Error generating report: %v", err)
|
||||
return
|
||||
}
|
||||
newTopo := detailed.Summaries(report, renderer.Render(report, decorator), metricsGraphURL)
|
||||
newTopo := detailed.Summaries(
|
||||
report.RenderContext{Report: re, MetricsGraphURL: metricsGraphURL},
|
||||
renderer.Render(re, decorator),
|
||||
)
|
||||
diff := detailed.TopoDiff(previousTopo, newTopo)
|
||||
previousTopo = newTopo
|
||||
|
||||
|
||||
@@ -121,13 +121,13 @@ func internetAddr(node report.Node, ep report.Node) (string, bool) {
|
||||
return addr, true
|
||||
}
|
||||
|
||||
func (c *connectionCounters) rows(r report.Report, ns report.Nodes, includeLocal bool, metricsGraphURL string) []Connection {
|
||||
func (c *connectionCounters) rows(r report.Report, ns report.Nodes, includeLocal bool) []Connection {
|
||||
output := []Connection{}
|
||||
for row, count := range c.counts {
|
||||
// Use MakeNodeSummary to render the id and label of this node
|
||||
// TODO(paulbellamy): Would be cleaner if we hade just a
|
||||
// MakeNodeID(ns[row.remoteNodeID]). As we don't need the whole summary.
|
||||
summary, _ := MakeNodeSummary(r, ns[row.remoteNodeID], metricsGraphURL)
|
||||
summary, _ := MakeNodeSummary(report.RenderContext{Report: r}, ns[row.remoteNodeID])
|
||||
connection := Connection{
|
||||
ID: fmt.Sprintf("%s-%s-%s-%s", row.remoteNodeID, row.remoteAddr, row.localAddr, row.port),
|
||||
NodeID: summary.ID,
|
||||
@@ -162,7 +162,7 @@ func (c *connectionCounters) rows(r report.Report, ns report.Nodes, includeLocal
|
||||
return output
|
||||
}
|
||||
|
||||
func incomingConnectionsSummary(topologyID string, r report.Report, n report.Node, ns report.Nodes, metricsGraphURL string) ConnectionsSummary {
|
||||
func incomingConnectionsSummary(topologyID string, r report.Report, n report.Node, ns report.Nodes) ConnectionsSummary {
|
||||
localEndpointIDs, localEndpointIDCopies := endpointChildIDsAndCopyMapOf(n)
|
||||
counts := newConnectionCounters()
|
||||
|
||||
@@ -188,11 +188,11 @@ func incomingConnectionsSummary(topologyID string, r report.Report, n report.Nod
|
||||
TopologyID: topologyID,
|
||||
Label: "Inbound",
|
||||
Columns: columnHeaders,
|
||||
Connections: counts.rows(r, ns, isInternetNode(n), metricsGraphURL),
|
||||
Connections: counts.rows(r, ns, isInternetNode(n)),
|
||||
}
|
||||
}
|
||||
|
||||
func outgoingConnectionsSummary(topologyID string, r report.Report, n report.Node, ns report.Nodes, metricsGraphURL string) ConnectionsSummary {
|
||||
func outgoingConnectionsSummary(topologyID string, r report.Report, n report.Node, ns report.Nodes) ConnectionsSummary {
|
||||
localEndpoints := endpointChildrenOf(n)
|
||||
counts := newConnectionCounters()
|
||||
|
||||
@@ -220,7 +220,7 @@ func outgoingConnectionsSummary(topologyID string, r report.Report, n report.Nod
|
||||
TopologyID: topologyID,
|
||||
Label: "Outbound",
|
||||
Columns: columnHeaders,
|
||||
Connections: counts.rows(r, ns, isInternetNode(n), metricsGraphURL),
|
||||
Connections: counts.rows(r, ns, isInternetNode(n)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,8 +99,6 @@ func formatMetricQueries(filter string, ids []string) map[string]string {
|
||||
return queries
|
||||
}
|
||||
|
||||
var metricsGraphURL = ""
|
||||
|
||||
// RenderMetricURLs sets respective URLs for metrics in a node summary. Missing metrics
|
||||
// where we have a query for will be appended as an empty metric (no values or samples).
|
||||
func RenderMetricURLs(summary NodeSummary, n report.Node, metricsGraphURL string) NodeSummary {
|
||||
@@ -119,10 +117,10 @@ func RenderMetricURLs(summary NodeSummary, n report.Node, metricsGraphURL string
|
||||
}
|
||||
|
||||
query := metricQuery(summary, n, metric.ID)
|
||||
|
||||
ms = append(ms, metric)
|
||||
|
||||
if query != "" {
|
||||
ms[len(ms)-1].URL = metricURL(query)
|
||||
ms[len(ms)-1].URL = metricURL(query, metricsGraphURL)
|
||||
}
|
||||
|
||||
found[metric.ID] = struct{}{}
|
||||
@@ -143,7 +141,7 @@ func RenderMetricURLs(summary NodeSummary, n report.Node, metricsGraphURL string
|
||||
ms = append(ms, report.MetricRow{
|
||||
ID: metadata.ID,
|
||||
Label: metadata.Label,
|
||||
URL: metricURL(query),
|
||||
URL: metricURL(query, metricsGraphURL),
|
||||
Metric: &report.Metric{},
|
||||
Priority: maxprio,
|
||||
ValueEmpty: true,
|
||||
@@ -170,7 +168,7 @@ func metricQuery(summary NodeSummary, n report.Node, metricID string) string {
|
||||
}
|
||||
|
||||
// metricURL builds the URL by embedding it into the configured `metricsGraphURL`.
|
||||
func metricURL(query string) string {
|
||||
func metricURL(query, metricsGraphURL string) string {
|
||||
if strings.Contains(metricsGraphURL, urlQueryVarName) {
|
||||
return strings.Replace(metricsGraphURL, urlQueryVarName, url.QueryEscape(query), -1)
|
||||
}
|
||||
|
||||
@@ -80,15 +80,15 @@ func (c *ControlInstance) CodecDecodeSelf(decoder *codec.Decoder) {
|
||||
|
||||
// MakeNode transforms a renderable node to a detailed node. It uses
|
||||
// aggregate metadata, plus the set of origin node IDs, to produce tables.
|
||||
func MakeNode(topologyID string, r report.Report, ns report.Nodes, n report.Node, metricsGraphURL string) Node {
|
||||
summary, _ := MakeNodeSummary(r, n, metricsGraphURL)
|
||||
func MakeNode(topologyID string, rc report.RenderContext, ns report.Nodes, n report.Node) Node {
|
||||
summary, _ := MakeNodeSummary(rc, n)
|
||||
return Node{
|
||||
NodeSummary: summary,
|
||||
Controls: controls(r, n),
|
||||
Children: children(r, n, metricsGraphURL),
|
||||
Controls: controls(rc.Report, n),
|
||||
Children: children(rc, n),
|
||||
Connections: []ConnectionsSummary{
|
||||
incomingConnectionsSummary(topologyID, r, n, ns, metricsGraphURL),
|
||||
outgoingConnectionsSummary(topologyID, r, n, ns, metricsGraphURL),
|
||||
incomingConnectionsSummary(topologyID, rc.Report, n, ns),
|
||||
outgoingConnectionsSummary(topologyID, rc.Report, n, ns),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -181,13 +181,13 @@ var nodeSummaryGroupSpecs = []struct {
|
||||
},
|
||||
}
|
||||
|
||||
func children(r report.Report, n report.Node, metricsGraphURL string) []NodeSummaryGroup {
|
||||
func children(rc report.RenderContext, n report.Node) []NodeSummaryGroup {
|
||||
summaries := map[string][]NodeSummary{}
|
||||
n.Children.ForEach(func(child report.Node) {
|
||||
if child.ID == n.ID {
|
||||
return
|
||||
}
|
||||
summary, ok := MakeNodeSummary(r, child, metricsGraphURL)
|
||||
summary, ok := MakeNodeSummary(rc, child)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -216,7 +216,7 @@ func children(r report.Report, n report.Node, metricsGraphURL string) []NodeSumm
|
||||
if len(nodeSummaries) == 0 {
|
||||
continue
|
||||
}
|
||||
topology, ok := r.Topology(topologyID)
|
||||
topology, ok := rc.Topology(topologyID)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -102,21 +102,22 @@ var primaryAPITopology = map[string]string{
|
||||
}
|
||||
|
||||
// MakeNodeSummary summarizes a node, if possible.
|
||||
func MakeNodeSummary(r report.Report, n report.Node, metricsGraphURL string) (NodeSummary, bool) {
|
||||
func MakeNodeSummary(rc report.RenderContext, n report.Node) (NodeSummary, bool) {
|
||||
r := rc.Report
|
||||
if renderer, ok := renderers[n.Topology]; ok {
|
||||
// Skip (and don't fall through to fallback) if renderer maps to nil
|
||||
if renderer != nil {
|
||||
summary, b := renderer(baseNodeSummary(r, n), n)
|
||||
return RenderMetricURLs(summary, n, metricsGraphURL), b
|
||||
return RenderMetricURLs(summary, n, rc.MetricsGraphURL), b
|
||||
}
|
||||
} else if _, ok := r.Topology(n.Topology); ok {
|
||||
} else if _, ok := rc.Topology(n.Topology); ok {
|
||||
summary := baseNodeSummary(r, n)
|
||||
summary.Label = n.ID // This is unlikely to look very good, but is a reasonable fallback
|
||||
return summary, true
|
||||
}
|
||||
if strings.HasPrefix(n.Topology, "group:") {
|
||||
summary, b := groupNodeSummary(baseNodeSummary(r, n), r, n)
|
||||
return RenderMetricURLs(summary, n, metricsGraphURL), b
|
||||
return RenderMetricURLs(summary, n, rc.MetricsGraphURL), b
|
||||
}
|
||||
return NodeSummary{}, false
|
||||
}
|
||||
@@ -374,11 +375,11 @@ func (s nodeSummariesByID) Less(i, j int) bool { return s[i].ID < s[j].ID }
|
||||
type NodeSummaries map[string]NodeSummary
|
||||
|
||||
// Summaries converts RenderableNodes into a set of NodeSummaries
|
||||
func Summaries(r report.Report, rns report.Nodes, metricsGraphURL string) NodeSummaries {
|
||||
func Summaries(rc report.RenderContext, rns report.Nodes) NodeSummaries {
|
||||
|
||||
result := NodeSummaries{}
|
||||
for id, node := range rns {
|
||||
if summary, ok := MakeNodeSummary(r, node, metricsGraphURL); ok {
|
||||
if summary, ok := MakeNodeSummary(rc, node); ok {
|
||||
for i, m := range summary.Metrics {
|
||||
summary.Metrics[i] = m.Summary()
|
||||
}
|
||||
|
||||
@@ -148,6 +148,12 @@ type Report struct {
|
||||
ID string `deepequal:"skip"`
|
||||
}
|
||||
|
||||
// RenderContext carries contextual data that is needed when rendering parts of the report.
|
||||
type RenderContext struct {
|
||||
Report
|
||||
MetricsGraphURL string
|
||||
}
|
||||
|
||||
// MakeReport makes a clean report, ready to Merge() other reports into.
|
||||
func MakeReport() Report {
|
||||
return Report{
|
||||
|
||||
Reference in New Issue
Block a user