|
|
|
|
@ -28,6 +28,7 @@ import ( |
|
|
|
|
"golang.org/x/net/context" |
|
|
|
|
|
|
|
|
|
"github.com/prometheus/prometheus/promql" |
|
|
|
|
"github.com/prometheus/prometheus/retrieval" |
|
|
|
|
"github.com/prometheus/prometheus/storage/local" |
|
|
|
|
"github.com/prometheus/prometheus/storage/metric" |
|
|
|
|
"github.com/prometheus/prometheus/util/httputil" |
|
|
|
|
@ -66,6 +67,10 @@ func (e *apiError) Error() string { |
|
|
|
|
return fmt.Sprintf("%s: %s", e.typ, e.err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type targetRetriever interface { |
|
|
|
|
Targets() []retrieval.Target |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type response struct { |
|
|
|
|
Status status `json:"status"` |
|
|
|
|
Data interface{} `json:"data,omitempty"` |
|
|
|
|
@ -88,17 +93,20 @@ type API struct { |
|
|
|
|
Storage local.Storage |
|
|
|
|
QueryEngine *promql.Engine |
|
|
|
|
|
|
|
|
|
targetRetriever targetRetriever |
|
|
|
|
|
|
|
|
|
context func(r *http.Request) context.Context |
|
|
|
|
now func() model.Time |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NewAPI returns an initialized API type.
|
|
|
|
|
func NewAPI(qe *promql.Engine, st local.Storage) *API { |
|
|
|
|
func NewAPI(qe *promql.Engine, st local.Storage, tr targetRetriever) *API { |
|
|
|
|
return &API{ |
|
|
|
|
QueryEngine: qe, |
|
|
|
|
Storage: st, |
|
|
|
|
context: route.Context, |
|
|
|
|
now: model.Now, |
|
|
|
|
QueryEngine: qe, |
|
|
|
|
Storage: st, |
|
|
|
|
targetRetriever: tr, |
|
|
|
|
context: route.Context, |
|
|
|
|
now: model.Now, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -129,6 +137,8 @@ func (api *API) Register(r *route.Router) { |
|
|
|
|
|
|
|
|
|
r.Get("/series", instr("series", api.series)) |
|
|
|
|
r.Del("/series", instr("drop_series", api.dropSeries)) |
|
|
|
|
|
|
|
|
|
r.Get("/targets", instr("targets", api.targets)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type queryData struct { |
|
|
|
|
@ -328,6 +338,43 @@ func (api *API) dropSeries(r *http.Request) (interface{}, *apiError) { |
|
|
|
|
return res, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type Target struct { |
|
|
|
|
// Labels before any processing.
|
|
|
|
|
DiscoveredLabels model.LabelSet `json:"discoveredLabels"` |
|
|
|
|
// Any labels that are added to this target and its metrics.
|
|
|
|
|
Labels model.LabelSet `json:"labels"` |
|
|
|
|
|
|
|
|
|
ScrapeUrl string `json:"scrapeUrl"` |
|
|
|
|
|
|
|
|
|
LastError string `json:"lastError"` |
|
|
|
|
LastScrape time.Time `json:"lastScrape"` |
|
|
|
|
Health retrieval.TargetHealth `json:"health"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (api *API) targets(r *http.Request) (interface{}, *apiError) { |
|
|
|
|
targets := api.targetRetriever.Targets() |
|
|
|
|
res := make([]*Target, len(targets)) |
|
|
|
|
|
|
|
|
|
for i, t := range targets { |
|
|
|
|
lastErrStr := "" |
|
|
|
|
lastErr := t.LastError() |
|
|
|
|
if lastErr != nil { |
|
|
|
|
lastErrStr = lastErr.Error() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
res[i] = &Target{ |
|
|
|
|
DiscoveredLabels: t.DiscoveredLabels(), |
|
|
|
|
Labels: t.Labels(), |
|
|
|
|
ScrapeUrl: t.URL().String(), |
|
|
|
|
LastError: lastErrStr, |
|
|
|
|
LastScrape: t.LastScrape(), |
|
|
|
|
Health: t.Health(), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return res, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func respond(w http.ResponseWriter, data interface{}) { |
|
|
|
|
w.Header().Set("Content-Type", "application/json") |
|
|
|
|
w.WriteHeader(http.StatusOK) |
|
|
|
|
|