mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
API_V1: Extract time param parsing logic (#6860)
* extract API time param parsing logic in a func Signed-off-by: blalov <boiskila@gmail.com>
This commit is contained in:
parent
1dbd799354
commit
84b00564f4
|
@ -318,18 +318,10 @@ func (api *API) options(r *http.Request) apiFuncResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) query(r *http.Request) apiFuncResult {
|
func (api *API) query(r *http.Request) apiFuncResult {
|
||||||
var ts time.Time
|
ts, err := parseTimeParam(r, "time", api.now())
|
||||||
if t := r.FormValue("time"); t != "" {
|
if err != nil {
|
||||||
var err error
|
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
||||||
ts, err = parseTime(t)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.Wrapf(err, "invalid parameter 'time'")
|
|
||||||
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ts = api.now()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
if to := r.FormValue("timeout"); to != "" {
|
if to := r.FormValue("timeout"); to != "" {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
|
@ -512,26 +504,13 @@ func (api *API) series(r *http.Request) apiFuncResult {
|
||||||
return apiFuncResult{nil, &apiError{errorBadData, errors.New("no match[] parameter provided")}, nil, nil}
|
return apiFuncResult{nil, &apiError{errorBadData, errors.New("no match[] parameter provided")}, nil, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
var start time.Time
|
start, err := parseTimeParam(r, "start", minTime)
|
||||||
if t := r.FormValue("start"); t != "" {
|
if err != nil {
|
||||||
var err error
|
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
||||||
start, err = parseTime(t)
|
|
||||||
if err != nil {
|
|
||||||
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
start = minTime
|
|
||||||
}
|
}
|
||||||
|
end, err := parseTimeParam(r, "end", maxTime)
|
||||||
var end time.Time
|
if err != nil {
|
||||||
if t := r.FormValue("end"); t != "" {
|
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
||||||
var err error
|
|
||||||
end, err = parseTime(t)
|
|
||||||
if err != nil {
|
|
||||||
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
end = maxTime
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var matcherSets [][]*labels.Matcher
|
var matcherSets [][]*labels.Matcher
|
||||||
|
@ -1320,26 +1299,13 @@ func (api *API) deleteSeries(r *http.Request) apiFuncResult {
|
||||||
return apiFuncResult{nil, &apiError{errorBadData, errors.New("no match[] parameter provided")}, nil, nil}
|
return apiFuncResult{nil, &apiError{errorBadData, errors.New("no match[] parameter provided")}, nil, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
var start time.Time
|
start, err := parseTimeParam(r, "start", minTime)
|
||||||
if t := r.FormValue("start"); t != "" {
|
if err != nil {
|
||||||
var err error
|
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
||||||
start, err = parseTime(t)
|
|
||||||
if err != nil {
|
|
||||||
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
start = minTime
|
|
||||||
}
|
}
|
||||||
|
end, err := parseTimeParam(r, "end", maxTime)
|
||||||
var end time.Time
|
if err != nil {
|
||||||
if t := r.FormValue("end"); t != "" {
|
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
||||||
var err error
|
|
||||||
end, err = parseTime(t)
|
|
||||||
if err != nil {
|
|
||||||
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
end = maxTime
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range r.Form["match[]"] {
|
for _, s := range r.Form["match[]"] {
|
||||||
|
@ -1474,6 +1440,18 @@ func (api *API) respondError(w http.ResponseWriter, apiErr *apiError, data inter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseTimeParam(r *http.Request, paramName string, defaultValue time.Time) (time.Time, error) {
|
||||||
|
val := r.FormValue(paramName)
|
||||||
|
if val == "" {
|
||||||
|
return defaultValue, nil
|
||||||
|
}
|
||||||
|
result, err := parseTime(val)
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, errors.Wrapf(err, "Invalid time value for '%s'", paramName)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseTime(s string) (time.Time, error) {
|
func parseTime(s string) (time.Time, error) {
|
||||||
if t, err := strconv.ParseFloat(s, 64); err == nil {
|
if t, err := strconv.ParseFloat(s, 64); err == nil {
|
||||||
s, ns := math.Modf(t)
|
s, ns := math.Modf(t)
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -41,6 +40,7 @@ import (
|
||||||
"github.com/prometheus/common/promlog"
|
"github.com/prometheus/common/promlog"
|
||||||
"github.com/prometheus/common/route"
|
"github.com/prometheus/common/route"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/prometheus/config"
|
"github.com/prometheus/prometheus/config"
|
||||||
"github.com/prometheus/prometheus/pkg/gate"
|
"github.com/prometheus/prometheus/pkg/gate"
|
||||||
"github.com/prometheus/prometheus/pkg/labels"
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
|
@ -2172,6 +2172,68 @@ func TestRespondError(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseTimeParam(t *testing.T) {
|
||||||
|
type resultType struct {
|
||||||
|
asTime time.Time
|
||||||
|
asError func() error
|
||||||
|
}
|
||||||
|
|
||||||
|
ts, err := parseTime("1582468023986")
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
paramName string
|
||||||
|
paramValue string
|
||||||
|
defaultValue time.Time
|
||||||
|
result resultType
|
||||||
|
}{
|
||||||
|
{ // When data is valid.
|
||||||
|
paramName: "start",
|
||||||
|
paramValue: "1582468023986",
|
||||||
|
defaultValue: minTime,
|
||||||
|
result: resultType{
|
||||||
|
asTime: ts,
|
||||||
|
asError: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // When data is empty string.
|
||||||
|
paramName: "end",
|
||||||
|
paramValue: "",
|
||||||
|
defaultValue: maxTime,
|
||||||
|
result: resultType{
|
||||||
|
asTime: maxTime,
|
||||||
|
asError: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ // When data is not valid.
|
||||||
|
paramName: "foo",
|
||||||
|
paramValue: "baz",
|
||||||
|
defaultValue: maxTime,
|
||||||
|
result: resultType{
|
||||||
|
asTime: time.Time{},
|
||||||
|
asError: func() error {
|
||||||
|
_, err := parseTime("baz")
|
||||||
|
return errors.Wrapf(err, "Invalid time value for '%s'", "foo")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
req, err := http.NewRequest("GET", "localhost:42/foo?"+test.paramName+"="+test.paramValue, nil)
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
|
||||||
|
result := test.result
|
||||||
|
asTime, err := parseTimeParam(req, test.paramName, test.defaultValue)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
testutil.ErrorEqual(t, result.asError(), err)
|
||||||
|
} else {
|
||||||
|
testutil.Assert(t, asTime.Equal(result.asTime), "time as return value: %s not parsed correctly. Expected %s. Actual %s", test.paramValue, result.asTime, asTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseTime(t *testing.T) {
|
func TestParseTime(t *testing.T) {
|
||||||
ts, err := time.Parse(time.RFC3339Nano, "2015-06-03T13:21:58.555Z")
|
ts, err := time.Parse(time.RFC3339Nano, "2015-06-03T13:21:58.555Z")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue