Prometheus: Run Explore range queries trough backend (#39133)
* Run Explore range queries trough backend * Remove trailing comma * Add timeRange step alignment to backend * Remove creation of instant query on backend as it is not supported ATM * Remove non-related frontend changes * Pass offset to calculate aligned range trough prom query * Update order in query error message * tableRefIds shouldn't contain undefined refIds * Remove cloning of dataframes when processing * Don't mutate response * Remove ordering of processed frames * Remove df because not needed
This commit is contained in:
@@ -51,6 +51,7 @@ type QueryModel struct {
|
||||
RangeQuery bool `json:"range"`
|
||||
InstantQuery bool `json:"instant"`
|
||||
IntervalFactor int64 `json:"intervalFactor"`
|
||||
OffsetSec int64 `json:"offsetSec"`
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
@@ -162,13 +163,20 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
||||
span.SetTag("stop_unixnano", query.End.UnixNano())
|
||||
defer span.Finish()
|
||||
|
||||
value, _, err := client.QueryRange(ctx, query.Expr, timeRange)
|
||||
var results model.Value
|
||||
|
||||
if err != nil {
|
||||
return &result, err
|
||||
switch query.QueryType {
|
||||
case Range:
|
||||
results, _, err = client.QueryRange(ctx, query.Expr, timeRange)
|
||||
if err != nil {
|
||||
return &result, fmt.Errorf("query: %s failed with: %v", query.Expr, err)
|
||||
}
|
||||
|
||||
default:
|
||||
return &result, fmt.Errorf("unknown Query type detected %#v", query.QueryType)
|
||||
}
|
||||
|
||||
frame, err := parseResponse(value, query)
|
||||
frame, err := parseResponse(results, query)
|
||||
if err != nil {
|
||||
return &result, err
|
||||
}
|
||||
@@ -283,13 +291,20 @@ func (s *Service) parseQuery(queryContext *backend.QueryDataRequest, dsInfo *Dat
|
||||
expr = strings.ReplaceAll(expr, "$__range", strconv.FormatInt(rangeS, 10)+"s")
|
||||
expr = strings.ReplaceAll(expr, "$__rate_interval", intervalv2.FormatDuration(calculateRateInterval(interval, dsInfo.TimeInterval, s.intervalCalculator)))
|
||||
|
||||
queryType := Range
|
||||
|
||||
// Align query range to step. It rounds start and end down to a multiple of step.
|
||||
start := int64(math.Floor((float64(query.TimeRange.From.Unix()+model.OffsetSec)/interval.Seconds()))*interval.Seconds() - float64(model.OffsetSec))
|
||||
end := int64(math.Floor((float64(query.TimeRange.To.Unix()+model.OffsetSec)/interval.Seconds()))*interval.Seconds() - float64(model.OffsetSec))
|
||||
|
||||
qs = append(qs, &PrometheusQuery{
|
||||
Expr: expr,
|
||||
Step: interval,
|
||||
LegendFormat: model.LegendFormat,
|
||||
Start: query.TimeRange.From,
|
||||
End: query.TimeRange.To,
|
||||
Start: time.Unix(start, 0),
|
||||
End: time.Unix(end, 0),
|
||||
RefId: query.RefID,
|
||||
QueryType: queryType,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -275,6 +275,45 @@ func TestPrometheus_parseQuery(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [1m]})", models[0].Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing query model of range query", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(48 * time.Hour),
|
||||
}
|
||||
|
||||
query := queryContext(`{
|
||||
"expr": "go_goroutines",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"refId": "A",
|
||||
"range": true
|
||||
}`, timeRange)
|
||||
|
||||
dsInfo := &DatasourceInfo{}
|
||||
models, err := service.parseQuery(query, dsInfo)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, Range, models[0].QueryType)
|
||||
})
|
||||
|
||||
t.Run("parsing query model of with default query type", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(48 * time.Hour),
|
||||
}
|
||||
|
||||
query := queryContext(`{
|
||||
"expr": "go_goroutines",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"refId": "A"
|
||||
}`, timeRange)
|
||||
|
||||
dsInfo := &DatasourceInfo{}
|
||||
models, err := service.parseQuery(query, dsInfo)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, Range, models[0].QueryType)
|
||||
})
|
||||
}
|
||||
|
||||
func queryContext(json string, timeRange backend.TimeRange) *backend.QueryDataRequest {
|
||||
|
||||
@@ -9,4 +9,13 @@ type PrometheusQuery struct {
|
||||
Start time.Time
|
||||
End time.Time
|
||||
RefId string
|
||||
QueryType PrometheusQueryType
|
||||
}
|
||||
|
||||
type PrometheusQueryType string
|
||||
|
||||
const (
|
||||
Range PrometheusQueryType = "range"
|
||||
//This is currently not used, but we will use it in next iteration
|
||||
Instant PrometheusQueryType = "instant"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user