@@ -3,14 +3,14 @@ package queryapi
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "io"
6
7
"net/http"
7
8
"time"
8
9
9
10
"github.com/go-kit/log"
10
11
"github.com/go-kit/log/level"
11
12
"github.com/grafana/regexp"
12
13
"github.com/munnerz/goautoneg"
13
- "github.com/prometheus/prometheus/promql"
14
14
"github.com/prometheus/prometheus/storage"
15
15
"github.com/prometheus/prometheus/util/annotations"
16
16
"github.com/prometheus/prometheus/util/httputil"
@@ -21,11 +21,13 @@ import (
21
21
"github.com/cortexproject/cortex/pkg/querier"
22
22
"github.com/cortexproject/cortex/pkg/util"
23
23
"github.com/cortexproject/cortex/pkg/util/api"
24
+ "github.com/prometheus/prometheus/promql"
25
+ "github.com/thanos-io/promql-engine/logicalplan"
24
26
)
25
27
26
28
type QueryAPI struct {
27
29
queryable storage.SampleAndChunkQueryable
28
- queryEngine promql. QueryEngine
30
+ queryEngine engine. Engine
29
31
now func () time.Time
30
32
statsRenderer v1.StatsRenderer
31
33
logger log.Logger
@@ -34,7 +36,7 @@ type QueryAPI struct {
34
36
}
35
37
36
38
func NewQueryAPI (
37
- qe promql. QueryEngine ,
39
+ qe engine. Engine ,
38
40
q storage.SampleAndChunkQueryable ,
39
41
statsRenderer v1.StatsRenderer ,
40
42
logger log.Logger ,
@@ -100,10 +102,29 @@ func (q *QueryAPI) RangeQueryHandler(r *http.Request) (result apiFuncResult) {
100
102
101
103
ctx = engine .AddEngineTypeToContext (ctx , r )
102
104
ctx = querier .AddBlockStoreTypeToContext (ctx , r .Header .Get (querier .BlockStoreTypeHeader ))
103
- qry , err := q .queryEngine .NewRangeQuery (ctx , q .queryable , opts , r .FormValue ("query" ), convertMsToTime (start ), convertMsToTime (end ), convertMsToDuration (step ))
105
+
106
+ var qry promql.Query
107
+ byteLP , err := io .ReadAll (r .Body )
104
108
if err != nil {
105
- return invalidParamError (httpgrpc .Errorf (http .StatusBadRequest , "%s" , err .Error ()), "query" )
109
+ return apiFuncResult {nil , & apiError {errorBadData , err }, nil , nil }
110
+ }
111
+
112
+ if len (byteLP ) != 0 {
113
+ logicalPlan , err := logicalplan .Unmarshal (byteLP )
114
+ if err != nil {
115
+ return apiFuncResult {nil , & apiError {errorBadData , err }, nil , nil }
116
+ }
117
+ qry , err = q .queryEngine .MakeRangeQueryFromPlan (ctx , q .queryable , opts , logicalPlan , convertMsToTime (start ), convertMsToTime (end ), convertMsToDuration (step ), r .FormValue ("query" ))
118
+ if err != nil {
119
+ return invalidParamError (httpgrpc .Errorf (http .StatusBadRequest , "%s" , err .Error ()), "query" )
120
+ }
121
+ } else {
122
+ qry , err = q .queryEngine .NewRangeQuery (ctx , q .queryable , opts , r .FormValue ("query" ), convertMsToTime (start ), convertMsToTime (end ), convertMsToDuration (step ))
123
+ if err != nil {
124
+ return invalidParamError (httpgrpc .Errorf (http .StatusBadRequest , "%s" , err .Error ()), "query" )
125
+ }
106
126
}
127
+
107
128
// From now on, we must only return with a finalizer in the result (to
108
129
// be called by the caller) or call qry.Close ourselves (which is
109
130
// required in the case of a panic).
@@ -156,9 +177,27 @@ func (q *QueryAPI) InstantQueryHandler(r *http.Request) (result apiFuncResult) {
156
177
157
178
ctx = engine .AddEngineTypeToContext (ctx , r )
158
179
ctx = querier .AddBlockStoreTypeToContext (ctx , r .Header .Get (querier .BlockStoreTypeHeader ))
159
- qry , err := q .queryEngine .NewInstantQuery (ctx , q .queryable , opts , r .FormValue ("query" ), convertMsToTime (ts ))
180
+
181
+ var qry promql.Query
182
+ byteLP , err := io .ReadAll (r .Body )
160
183
if err != nil {
161
- return invalidParamError (httpgrpc .Errorf (http .StatusBadRequest , "%s" , err .Error ()), "query" )
184
+ return apiFuncResult {nil , & apiError {errorBadData , err }, nil , nil }
185
+ }
186
+
187
+ if len (byteLP ) != 0 {
188
+ logicalPlan , err := logicalplan .Unmarshal (byteLP )
189
+ if err != nil {
190
+ return apiFuncResult {nil , & apiError {errorBadData , err }, nil , nil }
191
+ }
192
+ qry , err = q .queryEngine .MakeInstantQueryFromPlan (ctx , q .queryable , opts , logicalPlan , convertMsToTime (ts ), r .FormValue ("query" ))
193
+ if err != nil {
194
+ return invalidParamError (httpgrpc .Errorf (http .StatusBadRequest , "%s" , err .Error ()), "query" )
195
+ }
196
+ } else {
197
+ qry , err = q .queryEngine .NewInstantQuery (ctx , q .queryable , opts , r .FormValue ("query" ), convertMsToTime (ts ))
198
+ if err != nil {
199
+ return invalidParamError (httpgrpc .Errorf (http .StatusBadRequest , "%s" , err .Error ()), "query" )
200
+ }
162
201
}
163
202
164
203
// From now on, we must only return with a finalizer in the result (to
0 commit comments