Skip to content

Commit 4b918fe

Browse files
committed
time param on endpoint should be optional
Signed-off-by: Alan Protasio <[email protected]>
1 parent 940682a commit 4b918fe

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

pkg/querier/tripperware/instantquery/instant_query.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ import (
88
"net/http"
99
"net/url"
1010
"sort"
11+
"strconv"
1112
"strings"
13+
"time"
1214

1315
jsoniter "github.com/json-iterator/go"
1416
"github.com/opentracing/opentracing-go"
1517
otlog "github.com/opentracing/opentracing-go/log"
18+
"github.com/pkg/errors"
1619
"github.com/prometheus/common/model"
1720
"github.com/prometheus/prometheus/model/timestamp"
1821
"github.com/weaveworks/common/httpgrpc"
@@ -26,7 +29,7 @@ import (
2629
)
2730

2831
var (
29-
InstantQueryCodec tripperware.Codec = instantQueryCodec{}
32+
InstantQueryCodec tripperware.Codec = newInstantQueryCodec()
3033
json = jsoniter.Config{
3134
EscapeHTML: false, // No HTML in our responses.
3235
SortMapKeys: true,
@@ -102,6 +105,11 @@ func (r *PrometheusRequest) WithStats(stats string) tripperware.Request {
102105

103106
type instantQueryCodec struct {
104107
tripperware.Codec
108+
now func() time.Time
109+
}
110+
111+
func newInstantQueryCodec() instantQueryCodec {
112+
return instantQueryCodec{now: time.Now}
105113
}
106114

107115
func (resp *PrometheusInstantQueryResponse) HTTPHeaders() map[string][]string {
@@ -118,10 +126,10 @@ func (resp *PrometheusInstantQueryResponse) HTTPHeaders() map[string][]string {
118126
return nil
119127
}
120128

121-
func (instantQueryCodec) DecodeRequest(_ context.Context, r *http.Request, forwardHeaders []string) (tripperware.Request, error) {
129+
func (c instantQueryCodec) DecodeRequest(_ context.Context, r *http.Request, forwardHeaders []string) (tripperware.Request, error) {
122130
result := PrometheusRequest{Headers: map[string][]string{}}
123131
var err error
124-
result.Time, err = util.ParseTime(r.FormValue("time"))
132+
result.Time, err = parseTimeParam(r, "time", c.now().Unix())
125133
if err != nil {
126134
return nil, decorateWithParamName(err, "time")
127135
}
@@ -443,3 +451,15 @@ func (s *PrometheusInstantQueryData) MarshalJSON() ([]byte, error) {
443451
return s.Result.GetRawBytes(), nil
444452
}
445453
}
454+
455+
func parseTimeParam(r *http.Request, paramName string, defaultValue int64) (int64, error) {
456+
val := r.FormValue(paramName)
457+
if val == "" {
458+
val = strconv.FormatInt(defaultValue, 10)
459+
}
460+
result, err := util.ParseTime(val)
461+
if err != nil {
462+
return 0, errors.Wrapf(err, "Invalid time value for '%s'", paramName)
463+
}
464+
return result, nil
465+
}

pkg/querier/tripperware/instantquery/instant_query_test.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,30 @@ import (
88
"net/http"
99
"strconv"
1010
"testing"
11+
"time"
1112

1213
"github.com/stretchr/testify/assert"
1314
"github.com/stretchr/testify/require"
14-
"github.com/weaveworks/common/httpgrpc"
1515
"github.com/weaveworks/common/user"
1616

1717
"github.com/cortexproject/cortex/pkg/querier/tripperware"
1818
)
1919

2020
func TestRequest(t *testing.T) {
21+
now := time.Now()
22+
codec := instantQueryCodec{now: func() time.Time {
23+
return now
24+
}}
2125

2226
for _, tc := range []struct {
2327
url string
28+
expectedUrl string
2429
expected tripperware.Request
2530
expectedErr error
2631
}{
2732
{
28-
url: "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29&stats=all&time=1536673680",
33+
url: "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29&stats=all&time=1536673680",
34+
expectedUrl: "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29&stats=all&time=1536673680",
2935
expected: &PrometheusRequest{
3036
Path: "/api/v1/query",
3137
Time: 1536673680 * 1e3,
@@ -37,7 +43,8 @@ func TestRequest(t *testing.T) {
3743
},
3844
},
3945
{
40-
url: "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29&time=1536673680",
46+
url: "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29&time=1536673680",
47+
expectedUrl: "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29&time=1536673680",
4148
expected: &PrometheusRequest{
4249
Path: "/api/v1/query",
4350
Time: 1536673680 * 1e3,
@@ -49,8 +56,17 @@ func TestRequest(t *testing.T) {
4956
},
5057
},
5158
{
52-
url: "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29&stats=all",
53-
expectedErr: httpgrpc.Errorf(http.StatusBadRequest, "invalid parameter \"time\"; cannot parse \"\" to a valid timestamp"),
59+
url: "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29",
60+
expectedUrl: fmt.Sprintf("%s%d", "/api/v1/query?query=sum%28container_memory_rss%29+by+%28namespace%29&time=", now.Unix()),
61+
expected: &PrometheusRequest{
62+
Path: "/api/v1/query",
63+
Time: now.Unix() * 1e3,
64+
Query: "sum(container_memory_rss) by (namespace)",
65+
Stats: "",
66+
Headers: map[string][]string{
67+
"Test-Header": {"test"},
68+
},
69+
},
5470
},
5571
} {
5672
t.Run(tc.url, func(t *testing.T) {
@@ -63,16 +79,16 @@ func TestRequest(t *testing.T) {
6379
// Get a deep copy of the request with Context changed to ctx
6480
r = r.Clone(ctx)
6581

66-
req, err := InstantQueryCodec.DecodeRequest(ctx, r, []string{"Test-Header"})
82+
req, err := codec.DecodeRequest(ctx, r, []string{"Test-Header"})
6783
if err != nil {
6884
require.EqualValues(t, tc.expectedErr, err)
6985
return
7086
}
7187
require.EqualValues(t, tc.expected, req)
7288

73-
rdash, err := InstantQueryCodec.EncodeRequest(context.Background(), req)
89+
rdash, err := codec.EncodeRequest(context.Background(), req)
7490
require.NoError(t, err)
75-
require.EqualValues(t, tc.url, rdash.RequestURI)
91+
require.EqualValues(t, tc.expectedUrl, rdash.RequestURI)
7692
})
7793
}
7894
}

0 commit comments

Comments
 (0)