mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 02:00:43 +00:00
Add /api/probes endpoint
This commit is contained in:
@@ -4,6 +4,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
|
||||
// Raw report handler
|
||||
@@ -17,3 +19,19 @@ func makeRawReportHandler(rep Reporter) CtxHandlerFunc {
|
||||
respondWith(w, http.StatusOK, report)
|
||||
}
|
||||
}
|
||||
|
||||
// Probe handler
|
||||
func makeProbeHandler(rep Reporter) CtxHandlerFunc {
|
||||
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
rpt, err := rep.Report(ctx)
|
||||
if err != nil {
|
||||
respondWith(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
result := []report.Probe{}
|
||||
for _, p := range rpt.Probes {
|
||||
result = append(result, p)
|
||||
}
|
||||
respondWith(w, http.StatusOK, result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ func RegisterTopologyRoutes(router *mux.Router, r Reporter) {
|
||||
gzipHandler(requestContextDecorator(topologyRegistry.captureRendererWithoutFilters(r, handleNode))))
|
||||
get.HandleFunc("/api/report",
|
||||
gzipHandler(requestContextDecorator(makeRawReportHandler(r))))
|
||||
get.HandleFunc("/api/probes",
|
||||
gzipHandler(requestContextDecorator(makeProbeHandler(r))))
|
||||
}
|
||||
|
||||
// RegisterReportPostHandler registers the handler for report submission
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/armon/go-metrics"
|
||||
|
||||
"github.com/weaveworks/scope/common/mtime"
|
||||
"github.com/weaveworks/scope/probe/appclient"
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
@@ -17,6 +18,7 @@ const (
|
||||
|
||||
// Probe sits there, generating and publishing reports.
|
||||
type Probe struct {
|
||||
id string
|
||||
spyInterval, publishInterval time.Duration
|
||||
publisher *appclient.ReportPublisher
|
||||
|
||||
@@ -52,8 +54,9 @@ type Ticker interface {
|
||||
}
|
||||
|
||||
// New makes a new Probe.
|
||||
func New(spyInterval, publishInterval time.Duration, publisher appclient.Publisher) *Probe {
|
||||
func New(id string, spyInterval, publishInterval time.Duration, publisher appclient.Publisher) *Probe {
|
||||
result := &Probe{
|
||||
id: id,
|
||||
spyInterval: spyInterval,
|
||||
publishInterval: publishInterval,
|
||||
publisher: appclient.NewReportPublisher(publisher),
|
||||
@@ -150,6 +153,10 @@ func (p *Probe) report() report.Report {
|
||||
for i := 0; i < cap(reports); i++ {
|
||||
result = result.Merge(<-reports)
|
||||
}
|
||||
result.Probes[p.id] = report.Probe{
|
||||
ID: p.id,
|
||||
LastSeen: mtime.Now(),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ugorji/go/codec"
|
||||
"github.com/weaveworks/scope/common/mtime"
|
||||
"github.com/weaveworks/scope/report"
|
||||
"github.com/weaveworks/scope/test"
|
||||
"github.com/weaveworks/scope/test/reflect"
|
||||
@@ -18,7 +19,7 @@ func TestApply(t *testing.T) {
|
||||
endpointNode = report.MakeNodeWith(map[string]string{"5": "6"})
|
||||
)
|
||||
|
||||
p := New(0, 0, nil)
|
||||
p := New("", 0, 0, nil)
|
||||
p.AddTagger(NewTopologyTagger())
|
||||
|
||||
r := report.MakeReport()
|
||||
@@ -71,11 +72,20 @@ func TestProbe(t *testing.T) {
|
||||
// marshalling->unmarshaling is not idempotent due to `json:"omitempty"`
|
||||
// tags, transforming empty slices into nils. So, we make DeepEqual
|
||||
// happy by setting empty `json:"omitempty"` entries to nil
|
||||
const probeID = "probeid"
|
||||
now := time.Now()
|
||||
mtime.NowForce(now)
|
||||
defer mtime.NowReset()
|
||||
|
||||
want := report.MakeReport()
|
||||
node := report.MakeNodeWith(map[string]string{"b": "c"})
|
||||
node.Metrics = nil // omitempty
|
||||
want.Endpoint.AddNode("a", node)
|
||||
want.Probes[probeID] = report.Probe{
|
||||
ID: probeID,
|
||||
LastSeen: now,
|
||||
}
|
||||
|
||||
pub := mockPublisher{make(chan report.Report)}
|
||||
|
||||
// omitempty
|
||||
@@ -88,7 +98,7 @@ func TestProbe(t *testing.T) {
|
||||
want.Host.Controls = nil
|
||||
want.Overlay.Controls = nil
|
||||
|
||||
p := New(10*time.Millisecond, 100*time.Millisecond, pub)
|
||||
p := New(probeID, 10*time.Millisecond, 100*time.Millisecond, pub)
|
||||
p.AddReporter(mockReporter{want})
|
||||
p.Start()
|
||||
defer p.Stop()
|
||||
|
||||
@@ -138,7 +138,7 @@ func probeMain() {
|
||||
endpointReporter := endpoint.NewReporter(hostID, hostName, *spyProcs, *useConntrack, scanner)
|
||||
defer endpointReporter.Stop()
|
||||
|
||||
p := probe.New(*spyInterval, *publishInterval, clients)
|
||||
p := probe.New(probeID, *spyInterval, *publishInterval, clients)
|
||||
p.AddTicker(processCache)
|
||||
hostReporter := host.NewReporter(hostID, hostName, probeID, clients)
|
||||
defer hostReporter.Stop()
|
||||
|
||||
43
report/probes.go
Normal file
43
report/probes.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Probes contains details of the probe(s) which generated a report.
|
||||
type Probes map[string]Probe
|
||||
|
||||
// Copy produces a copy of the Probes
|
||||
func (ps Probes) Copy() Probes {
|
||||
result := Probes{}
|
||||
for id, probe := range ps {
|
||||
result[id] = probe.Copy()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Merge two sets of Probes, keeping the records with the latest LastSeen
|
||||
func (ps Probes) Merge(other Probes) Probes {
|
||||
result := ps.Copy()
|
||||
for id, probe := range other {
|
||||
o, ok := result[id]
|
||||
if !ok || o.LastSeen.Before(probe.LastSeen) {
|
||||
result[id] = probe
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Probe is the details for a single probe that generated a report.
|
||||
type Probe struct {
|
||||
ID string `json:"id"`
|
||||
LastSeen time.Time `json:"lastSeen"`
|
||||
}
|
||||
|
||||
// Copy produces a copy of the Probe
|
||||
func (p Probe) Copy() Probe {
|
||||
return Probe{
|
||||
ID: p.ID,
|
||||
LastSeen: p.LastSeen,
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,9 @@ type Report struct {
|
||||
// must be equal, but we don't require that equal reports have
|
||||
// the same id.
|
||||
ID string `deepequal:"skip"`
|
||||
|
||||
// Probes is the details of the probes who reported this report
|
||||
Probes Probes
|
||||
}
|
||||
|
||||
// MakeReport makes a clean report, ready to Merge() other reports into.
|
||||
@@ -97,6 +100,7 @@ func MakeReport() Report {
|
||||
Sampling: Sampling{},
|
||||
Window: 0,
|
||||
ID: fmt.Sprintf("%d", rand.Int63()),
|
||||
Probes: Probes{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +118,7 @@ func (r Report) Copy() Report {
|
||||
Sampling: r.Sampling,
|
||||
Window: r.Window,
|
||||
ID: fmt.Sprintf("%d", rand.Int63()),
|
||||
Probes: r.Probes.Copy(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +135,7 @@ func (r Report) Merge(other Report) Report {
|
||||
cp.Service = r.Service.Merge(other.Service)
|
||||
cp.Overlay = r.Overlay.Merge(other.Overlay)
|
||||
cp.Sampling = r.Sampling.Merge(other.Sampling)
|
||||
cp.Probes = r.Probes.Merge(other.Probes)
|
||||
cp.Window += other.Window
|
||||
return cp
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user