From 0c1e7a5b00449e79b701928ea6187bf395d5680e Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Wed, 11 May 2016 23:59:52 +0200 Subject: [PATCH] Support time range in /api/v1/series endpoint. This adds optional "start" and "end" form values that may be used to restrict the time range of returned series. Fixes https://github.com/prometheus/prometheus/issues/1542 --- web/api/v1/api.go | 25 ++++++++++++- web/api/v1/api_test.go | 80 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/web/api/v1/api.go b/web/api/v1/api.go index df8ce0b34..bce83745e 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -232,6 +232,29 @@ func (api *API) series(r *http.Request) (interface{}, *apiError) { if len(r.Form["match[]"]) == 0 { return nil, &apiError{errorBadData, fmt.Errorf("no match[] parameter provided")} } + + var start model.Time + if t := r.FormValue("start"); t != "" { + var err error + start, err = parseTime(t) + if err != nil { + return nil, &apiError{errorBadData, err} + } + } else { + start = model.Earliest + } + + var end model.Time + if t := r.FormValue("end"); t != "" { + var err error + end, err = parseTime(t) + if err != nil { + return nil, &apiError{errorBadData, err} + } + } else { + end = model.Latest + } + res := map[model.Fingerprint]metric.Metric{} for _, lm := range r.Form["match[]"] { @@ -240,7 +263,7 @@ func (api *API) series(r *http.Request) (interface{}, *apiError) { return nil, &apiError{errorBadData, err} } for fp, met := range api.Storage.MetricsForLabelMatchers( - model.Earliest, model.Latest, // Get every series. + start, end, matchers..., ) { res[fp] = met diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 51976eaa9..89388ab47 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -263,6 +263,86 @@ func TestEndpoints(t *testing.T) { }, }, }, + // Start and end before series starts. + { + endpoint: api.series, + query: url.Values{ + "match[]": []string{`test_metric2`}, + "start": []string{"-2"}, + "end": []string{"-1"}, + }, + response: []model.Metric{}, + }, + // Start and end after series ends. + { + endpoint: api.series, + query: url.Values{ + "match[]": []string{`test_metric2`}, + "start": []string{"100000"}, + "end": []string{"100001"}, + }, + response: []model.Metric{}, + }, + // Start before series starts, end after series ends. + { + endpoint: api.series, + query: url.Values{ + "match[]": []string{`test_metric2`}, + "start": []string{"-1"}, + "end": []string{"100000"}, + }, + response: []model.Metric{ + { + "__name__": "test_metric2", + "foo": "boo", + }, + }, + }, + // Start and end within series. + { + endpoint: api.series, + query: url.Values{ + "match[]": []string{`test_metric2`}, + "start": []string{"1"}, + "end": []string{"100"}, + }, + response: []model.Metric{ + { + "__name__": "test_metric2", + "foo": "boo", + }, + }, + }, + // Start within series, end after. + { + endpoint: api.series, + query: url.Values{ + "match[]": []string{`test_metric2`}, + "start": []string{"1"}, + "end": []string{"100000"}, + }, + response: []model.Metric{ + { + "__name__": "test_metric2", + "foo": "boo", + }, + }, + }, + // Start before series, end within series. + { + endpoint: api.series, + query: url.Values{ + "match[]": []string{`test_metric2`}, + "start": []string{"-1"}, + "end": []string{"1"}, + }, + response: []model.Metric{ + { + "__name__": "test_metric2", + "foo": "boo", + }, + }, + }, // Missing match[] query params in series requests. { endpoint: api.series,