Implement endpoint for UI routing tree representation

This commit is contained in:
Fabian Reinartz 2015-10-21 16:34:56 +02:00
parent e151f029b7
commit 524d08d567
4 changed files with 89 additions and 2 deletions

35
api.go
View File

@ -32,15 +32,19 @@ import (
type API struct {
alerts provider.Alerts
silences provider.Silences
route func() *UIRoute
// context is an indirection for testing.
context func(r *http.Request) context.Context
}
func RegisterAPI(r *route.Router, alerts provider.Alerts, silences provider.Silences) *API {
func RegisterAPI(r *route.Router, alerts provider.Alerts, silences provider.Silences, rf func() *UIRoute) *API {
api := &API{
context: route.Context,
alerts: alerts,
silences: silences,
route: rf,
}
// Register legacy forwarder for alert pushing.
@ -49,6 +53,8 @@ func RegisterAPI(r *route.Router, alerts provider.Alerts, silences provider.Sile
// Register actual API.
r = r.WithPrefix("/v1")
r.Get("/routes", api.routes)
r.Get("/alerts", api.listAlerts)
r.Post("/alerts", api.addAlerts)
@ -80,6 +86,33 @@ func (e *apiError) Error() string {
return fmt.Sprintf("%s: %s", e.typ, e.err)
}
func pruneUIRoute(r *UIRoute) {
for _, sr := range r.Routes {
pruneUIRoute(sr)
}
var nr []*UIRoute
for _, sr := range r.Routes {
if len(sr.Groups) == 0 && len(sr.Routes) == 0 {
continue
}
nr = append(nr, sr)
}
r.Routes = nr
}
func (api *API) routes(w http.ResponseWriter, req *http.Request) {
r := api.route()
if req.FormValue("pruneEmpty") == "true" {
pruneUIRoute(r)
}
respond(w, r)
}
func (api *API) listAlerts(w http.ResponseWriter, r *http.Request) {
alerts := api.alerts.GetPending()
defer alerts.Close()

View File

@ -54,6 +54,41 @@ func (d *Dispatcher) Run() {
close(d.done)
}
type UIRoute struct {
RouteOpts *RouteOpts
Matchers types.Matchers
Groups []*UIGroup
Routes []*UIRoute
}
type UIGroup struct {
Labels model.LabelSet
Alerts model.Alerts
}
func (d *Dispatcher) Populate(r *UIRoute) {
for _, sr := range r.Routes {
d.Populate(sr)
}
groups, ok := d.aggrGroups[r.RouteOpts]
if !ok {
return
}
for _, ag := range groups {
var as []*types.Alert
for _, a := range ag.alerts {
as = append(as, a)
}
g := &UIGroup{
Labels: ag.labels,
Alerts: types.Alerts(as...),
}
r.Groups = append(r.Groups, g)
}
}
func (d *Dispatcher) run(it provider.AlertIterator) {
cleanup := time.NewTicker(30 * time.Second)
defer cleanup.Stop()

View File

@ -128,7 +128,12 @@ func main() {
router := route.New()
RegisterWeb(router)
RegisterAPI(router.WithPrefix("/api"), alerts, silences)
RegisterAPI(router.WithPrefix("/api"), alerts, silences, func() *UIRoute {
uir := disp.route.UIRoute()
disp.Populate(uir)
return uir
})
go http.ListenAndServe(*listenAddress, router)

View File

@ -115,6 +115,20 @@ func NewRoutes(croutes []*config.Route, parent *Route) []*Route {
return res
}
func (r *Route) UIRoute() *UIRoute {
var subs []*UIRoute
for _, sr := range r.Routes {
subs = append(subs, sr.UIRoute())
}
uir := &UIRoute{
RouteOpts: &r.RouteOpts,
Matchers: r.Matchers,
Routes: subs,
}
return uir
}
// Match does a depth-first left-to-right search through the route tree
// and returns the flattened configuration for the reached node.
func (r *Route) Match(lset model.LabelSet) []*RouteOpts {