diff --git a/pkg/client/api.go b/pkg/client/api.go index c79b68ac..1a5ef0aa 100644 --- a/pkg/client/api.go +++ b/pkg/client/api.go @@ -25,6 +25,7 @@ import ( "net/http" "net/url" "path" + "time" "github.com/golang/glog" "github.com/prometheus/common/model" @@ -54,7 +55,6 @@ func (c *httpAPIClient) Do(ctx context.Context, verb, endpoint string, query url u.RawQuery = query.Encode() req, err := http.NewRequest(verb, u.String(), nil) if err != nil { - // TODO: fix this to return Error? return APIResponse{}, fmt.Errorf("error constructing HTTP request to Prometheus: %v", err) } req.WithContext(ctx) @@ -96,7 +96,6 @@ func (c *httpAPIClient) Do(ctx context.Context, verb, endpoint string, query url var res APIResponse if err = json.NewDecoder(body).Decode(&res); err != nil { - // TODO: return what the body actually was? return APIResponse{}, &Error{ Type: ErrBadResponse, Msg: err.Error(), @@ -174,7 +173,9 @@ func (h *queryClient) Query(ctx context.Context, t model.Time, query Selector) ( if t != 0 { vals.Set("time", t.String()) } - // TODO: get timeout from context... + if timeout, hasTimeout := timeoutFromContext(ctx); hasTimeout { + vals.Set("timeout", model.Duration(timeout).String()) + } res, err := h.api.Do(ctx, "GET", queryURL, vals) if err != nil { @@ -199,7 +200,9 @@ func (h *queryClient) QueryRange(ctx context.Context, r Range, query Selector) ( if r.Step != 0 { vals.Set("step", model.Duration(r.Step).String()) } - // TODO: get timeout from context... + if timeout, hasTimeout := timeoutFromContext(ctx); hasTimeout { + vals.Set("timeout", model.Duration(timeout).String()) + } res, err := h.api.Do(ctx, "GET", queryRangeURL, vals) if err != nil { @@ -210,3 +213,13 @@ func (h *queryClient) QueryRange(ctx context.Context, r Range, query Selector) ( err = json.Unmarshal(res.Data, &queryRes) return queryRes, err } + +// timeoutFromContext checks the context for a deadline and calculates a "timeout" duration from it, +// when present +func timeoutFromContext(ctx context.Context) (time.Duration, bool) { + if deadline, hasDeadline := ctx.Deadline(); hasDeadline { + return time.Now().Sub(deadline), true + } + + return time.Duration(0), false +} diff --git a/pkg/client/interfaces.go b/pkg/client/interfaces.go index 5afc30d9..00ee720d 100644 --- a/pkg/client/interfaces.go +++ b/pkg/client/interfaces.go @@ -40,7 +40,9 @@ type Range struct { Step time.Duration } -// TODO: support timeout in the client? +// Client is a Prometheus client for the Prometheus HTTP API. +// The "timeout" parameter for the HTTP API is set based on the context's deadline, +// when present and applicable. type Client interface { // Series lists the time series matching the given series selectors Series(ctx context.Context, interval model.Interval, selectors ...Selector) ([]Series, error)