From 3c0e2b3c2e521e4c318a8aa34fac00df2ad71e97 Mon Sep 17 00:00:00 2001 From: siddontang Date: Fri, 24 Nov 2017 20:12:53 +0800 Subject: [PATCH] v1: support series API --- api/prometheus/v1/api.go | 30 ++++++++++++++++++++++++ api/prometheus/v1/api_test.go | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/api/prometheus/v1/api.go b/api/prometheus/v1/api.go index 2e506ae..cb07022 100644 --- a/api/prometheus/v1/api.go +++ b/api/prometheus/v1/api.go @@ -78,6 +78,8 @@ type API interface { QueryRange(ctx context.Context, query string, r Range) (model.Value, error) // LabelValues performs a query for the values of the given label. LabelValues(ctx context.Context, label string) (model.LabelValues, error) + // Series finds series by label matchers. + Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error) } // queryResult contains result data for a query. @@ -208,6 +210,34 @@ func (h *httpAPI) LabelValues(ctx context.Context, label string) (model.LabelVal return labelValues, err } +func (h *httpAPI) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error) { + u := h.client.URL(epSeries, nil) + q := u.Query() + + for _, m := range matches { + q.Add("match[]", m) + } + + q.Set("start", startTime.Format(time.RFC3339Nano)) + q.Set("end", endTime.Format(time.RFC3339Nano)) + + u.RawQuery = q.Encode() + + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, err + } + + _, body, err := h.client.Do(ctx, req) + if err != nil { + return nil, err + } + + var mset []model.LabelSet + err = json.Unmarshal(body, &mset) + return mset, err +} + // apiClient wraps a regular client and processes successful API responses. // Successful also includes responses that errored at the API level. type apiClient struct { diff --git a/api/prometheus/v1/api_test.go b/api/prometheus/v1/api_test.go index 2c8b1b2..e557d68 100644 --- a/api/prometheus/v1/api_test.go +++ b/api/prometheus/v1/api_test.go @@ -112,6 +112,12 @@ func TestAPIs(t *testing.T) { } } + doSeries := func(matcher string, startTime time.Time, endTime time.Time) func() (interface{}, error) { + return func() (interface{}, error) { + return queryAPI.Series(context.Background(), []string{matcher}, startTime, endTime) + } + } + queryTests := []apiTest{ { do: doQuery("2", testTime), @@ -181,6 +187,43 @@ func TestAPIs(t *testing.T) { reqPath: "/api/v1/label/mylabel/values", err: fmt.Errorf("some error"), }, + + { + do: doSeries("up", testTime.Add(-time.Minute), testTime), + inRes: []map[string]string{ + { + "__name__": "up", + "job": "prometheus", + "instance": "localhost:9090"}, + }, + reqMethod: "GET", + reqPath: "/api/v1/series", + reqParam: url.Values{ + "match": []string{"up"}, + "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, + "end": []string{testTime.Format(time.RFC3339Nano)}, + }, + res: []model.LabelSet{ + model.LabelSet{ + "__name__": "up", + "job": "prometheus", + "instance": "localhost:9090", + }, + }, + }, + + { + do: doSeries("up", testTime.Add(-time.Minute), testTime), + inErr: fmt.Errorf("some error"), + reqMethod: "GET", + reqPath: "/api/v1/series", + reqParam: url.Values{ + "match": []string{"up"}, + "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, + "end": []string{testTime.Format(time.RFC3339Nano)}, + }, + err: fmt.Errorf("some error"), + }, } var tests []apiTest