mirror of
https://github.com/weaveworks/scope.git
synced 2026-08-18 03:46:45 +00:00
feature(app): Add a debugging summary function, exposed via http
URL is /admin/summary
This commit is contained in:
@@ -31,6 +31,7 @@ type Reporter interface {
|
||||
Report(context.Context, time.Time) (report.Report, error)
|
||||
HasReports(context.Context, time.Time) (bool, error)
|
||||
HasHistoricReports() bool
|
||||
AdminSummary(context.Context, time.Time) (string, error)
|
||||
WaitOn(context.Context, chan struct{})
|
||||
UnWait(context.Context, chan struct{})
|
||||
}
|
||||
@@ -172,6 +173,20 @@ func (c *collector) HasHistoricReports() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// AdminSummary returns a string with some internal information about
|
||||
// the report, which may be useful to troubleshoot.
|
||||
func (c *collector) AdminSummary(ctx context.Context, timestamp time.Time) (string, error) {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
var b strings.Builder
|
||||
for i := range c.reports {
|
||||
fmt.Fprintf(&b, "%v: ", c.timestamps[i].Format(time.StampMilli))
|
||||
b.WriteString(c.reports[i].Summary())
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
return b.String(), nil
|
||||
}
|
||||
|
||||
// remove reports older than the app.window
|
||||
func (c *collector) clean() {
|
||||
var (
|
||||
@@ -240,6 +255,10 @@ func (c StaticCollector) HasHistoricReports() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c StaticCollector) AdminSummary(ctx context.Context, timestamp time.Time) (string, error) {
|
||||
return "not implemented", nil
|
||||
}
|
||||
|
||||
// Add adds a report to the collector's internal state. It implements Adder.
|
||||
func (c StaticCollector) Add(context.Context, report.Report, []byte) error { return nil }
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -444,6 +445,34 @@ func (c *awsCollector) HasHistoricReports() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// AdminSummary returns a string with some internal information about
|
||||
// the report, which may be useful to troubleshoot.
|
||||
func (c *awsCollector) AdminSummary(ctx context.Context, timestamp time.Time) (string, error) {
|
||||
span, ctx := opentracing.StartSpanFromContext(ctx, "awsCollector.Report")
|
||||
defer span.Finish()
|
||||
userid, err := c.cfg.UserIDer(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
end := timestamp
|
||||
start := end.Add(-c.cfg.Window)
|
||||
reportKeys, err := c.getReportKeys(ctx, userid, start, end)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
reports, err := c.reportsForKeysInRange(ctx, reportKeys, start.UnixNano(), end.UnixNano())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var b strings.Builder
|
||||
for i := range reports {
|
||||
// TODO: print the key - note reports may be in a different order from reportKeys
|
||||
b.WriteString(reports[i].Summary())
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
return b.String(), nil
|
||||
}
|
||||
|
||||
// calculateDynamoKeys generates the row & column keys for Dynamo.
|
||||
func calculateDynamoKeys(userid string, now time.Time) (string, string) {
|
||||
rowKey := fmt.Sprintf("%s-%s", userid, strconv.FormatInt(now.UnixNano()/time.Hour.Nanoseconds(), 10))
|
||||
|
||||
@@ -159,6 +159,18 @@ func RegisterReportPostHandler(a Adder, router *mux.Router) {
|
||||
}))
|
||||
}
|
||||
|
||||
// RegisterAdminRoutes registers routes for admin calls with a http mux.
|
||||
func RegisterAdminRoutes(router *mux.Router, reporter Reporter) {
|
||||
get := router.Methods("GET").Subrouter()
|
||||
get.Handle("/admin/summary", requestContextDecorator(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
summary, err := reporter.AdminSummary(ctx, time.Now())
|
||||
if err != nil {
|
||||
respondWith(w, http.StatusBadRequest, err)
|
||||
}
|
||||
fmt.Fprintln(w, summary)
|
||||
}))
|
||||
}
|
||||
|
||||
var newVersion = struct {
|
||||
sync.Mutex
|
||||
*xfer.NewVersionInfo
|
||||
|
||||
@@ -67,6 +67,7 @@ func router(collector app.Collector, controlRouter app.ControlRouter, pipeRouter
|
||||
app.RegisterControlRoutes(router, controlRouter)
|
||||
app.RegisterPipeRoutes(router, pipeRouter)
|
||||
app.RegisterTopologyRoutes(router, app.WebReporter{Reporter: collector, MetricsGraphURL: metricsGraphURL}, capabilities)
|
||||
app.RegisterAdminRoutes(router, collector)
|
||||
|
||||
uiHandler := http.FileServer(GetFS(externalUI))
|
||||
router.PathPrefix("/ui").Name("static").Handler(
|
||||
|
||||
@@ -559,6 +559,26 @@ func (r Report) upgradeDNSRecords() Report {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r Report) Summary() string {
|
||||
ret := ""
|
||||
if len(r.Host.Nodes) == 1 {
|
||||
for k, _ := range r.Host.Nodes {
|
||||
ret = k + ":"
|
||||
}
|
||||
}
|
||||
count := 0
|
||||
r.WalkNamedTopologies(func(n string, t *Topology) {
|
||||
if len(t.Nodes) > 0 {
|
||||
count++
|
||||
if count > 1 {
|
||||
ret = ret + ", "
|
||||
}
|
||||
ret = ret + fmt.Sprintf("%s:%d", n, len(t.Nodes))
|
||||
}
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
// Sampling describes how the packet data sources for this report were
|
||||
// sampled. It can be used to calculate effective sample rates. We can't
|
||||
// just put the rate here, because that can't be accurately merged. Counts
|
||||
|
||||
Reference in New Issue
Block a user