Allow setting custom lookback delta for instant queries (#9946)
* Allow setting custom lookback delta for instant queries Signed-off-by: Vilius Pranckaitis <vpranckaitis@gmail.com>
This commit is contained in:
parent
595d134354
commit
4660656312
|
@ -128,6 +128,8 @@ type Query interface {
|
|||
type QueryOpts struct {
|
||||
// Enables recording per-step statistics if the engine has it enabled as well. Disabled by default.
|
||||
EnablePerStepStats bool
|
||||
// Lookback delta duration for this query.
|
||||
LookbackDelta time.Duration
|
||||
}
|
||||
|
||||
// query implements the Query interface.
|
||||
|
@ -437,11 +439,17 @@ func (ng *Engine) newQuery(q storage.Queryable, opts *QueryOpts, expr parser.Exp
|
|||
opts = &QueryOpts{}
|
||||
}
|
||||
|
||||
lookbackDelta := opts.LookbackDelta
|
||||
if lookbackDelta <= 0 {
|
||||
lookbackDelta = ng.lookbackDelta
|
||||
}
|
||||
|
||||
es := &parser.EvalStmt{
|
||||
Expr: PreprocessExpr(expr, start, end),
|
||||
Start: start,
|
||||
End: end,
|
||||
Interval: interval,
|
||||
Expr: PreprocessExpr(expr, start, end),
|
||||
Start: start,
|
||||
End: end,
|
||||
Interval: interval,
|
||||
LookbackDelta: lookbackDelta,
|
||||
}
|
||||
qry := &query{
|
||||
stmt: es,
|
||||
|
@ -636,7 +644,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *parser.Eval
|
|||
ctx: ctxInnerEval,
|
||||
maxSamples: ng.maxSamplesPerQuery,
|
||||
logger: ng.logger,
|
||||
lookbackDelta: ng.lookbackDelta,
|
||||
lookbackDelta: s.LookbackDelta,
|
||||
samplesStats: query.sampleStats,
|
||||
noStepSubqueryIntervalFn: ng.noStepSubqueryIntervalFn,
|
||||
}
|
||||
|
@ -688,7 +696,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *parser.Eval
|
|||
ctx: ctxInnerEval,
|
||||
maxSamples: ng.maxSamplesPerQuery,
|
||||
logger: ng.logger,
|
||||
lookbackDelta: ng.lookbackDelta,
|
||||
lookbackDelta: s.LookbackDelta,
|
||||
samplesStats: query.sampleStats,
|
||||
noStepSubqueryIntervalFn: ng.noStepSubqueryIntervalFn,
|
||||
}
|
||||
|
@ -801,7 +809,7 @@ func (ng *Engine) getTimeRangesForSelector(s *parser.EvalStmt, n *parser.VectorS
|
|||
}
|
||||
|
||||
if evalRange == 0 {
|
||||
start = start - durationMilliseconds(ng.lookbackDelta)
|
||||
start = start - durationMilliseconds(s.LookbackDelta)
|
||||
} else {
|
||||
// For all matrix queries we want to ensure that we have (end-start) + range selected
|
||||
// this way we have `range` data before the start time
|
||||
|
|
|
@ -3120,3 +3120,96 @@ func TestRangeQuery(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryLookbackDelta(t *testing.T) {
|
||||
var (
|
||||
load = `load 5m
|
||||
metric 0 1 2
|
||||
`
|
||||
query = "metric"
|
||||
lastDatapointTs = time.Unix(600, 0)
|
||||
)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
ts time.Time
|
||||
engineLookback, queryLookback time.Duration
|
||||
expectSamples bool
|
||||
}{
|
||||
{
|
||||
name: "default lookback delta",
|
||||
ts: lastDatapointTs.Add(defaultLookbackDelta),
|
||||
expectSamples: true,
|
||||
},
|
||||
{
|
||||
name: "outside default lookback delta",
|
||||
ts: lastDatapointTs.Add(defaultLookbackDelta + time.Millisecond),
|
||||
expectSamples: false,
|
||||
},
|
||||
{
|
||||
name: "custom engine lookback delta",
|
||||
ts: lastDatapointTs.Add(10 * time.Minute),
|
||||
engineLookback: 10 * time.Minute,
|
||||
expectSamples: true,
|
||||
},
|
||||
{
|
||||
name: "outside custom engine lookback delta",
|
||||
ts: lastDatapointTs.Add(10*time.Minute + time.Millisecond),
|
||||
engineLookback: 10 * time.Minute,
|
||||
expectSamples: false,
|
||||
},
|
||||
{
|
||||
name: "custom query lookback delta",
|
||||
ts: lastDatapointTs.Add(20 * time.Minute),
|
||||
engineLookback: 10 * time.Minute,
|
||||
queryLookback: 20 * time.Minute,
|
||||
expectSamples: true,
|
||||
},
|
||||
{
|
||||
name: "outside custom query lookback delta",
|
||||
ts: lastDatapointTs.Add(20*time.Minute + time.Millisecond),
|
||||
engineLookback: 10 * time.Minute,
|
||||
queryLookback: 20 * time.Minute,
|
||||
expectSamples: false,
|
||||
},
|
||||
{
|
||||
name: "negative custom query lookback delta",
|
||||
ts: lastDatapointTs.Add(20 * time.Minute),
|
||||
engineLookback: -10 * time.Minute,
|
||||
queryLookback: 20 * time.Minute,
|
||||
expectSamples: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
c := c
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
test, err := NewTest(t, load)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
|
||||
err = test.Run()
|
||||
require.NoError(t, err)
|
||||
|
||||
eng := test.QueryEngine()
|
||||
if c.engineLookback != 0 {
|
||||
eng.lookbackDelta = c.engineLookback
|
||||
}
|
||||
opts := &QueryOpts{
|
||||
LookbackDelta: c.queryLookback,
|
||||
}
|
||||
qry, err := eng.NewInstantQuery(test.Queryable(), opts, query, c.ts)
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
require.NoError(t, res.Err)
|
||||
vec, ok := res.Value.(Vector)
|
||||
require.True(t, ok)
|
||||
if c.expectSamples {
|
||||
require.NotEmpty(t, vec)
|
||||
} else {
|
||||
require.Empty(t, vec)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ type EvalStmt struct {
|
|||
Start, End time.Time
|
||||
// Time between two evaluated instants for the range [Start:End].
|
||||
Interval time.Duration
|
||||
// Lookback delta to use for this evaluation.
|
||||
LookbackDelta time.Duration
|
||||
}
|
||||
|
||||
func (*EvalStmt) PromQLStmt() {}
|
||||
|
|
Loading…
Reference in New Issue