@ -45,6 +45,7 @@ const (
subsystem = "engine"
subsystem = "engine"
queryTag = "query"
queryTag = "query"
env = "query execution"
env = "query execution"
defaultLookbackDelta = 5 * time . Minute
// The largest SampleValue that can be converted to an int64 without overflow.
// The largest SampleValue that can be converted to an int64 without overflow.
maxInt64 = 9223372036854774784
maxInt64 = 9223372036854774784
@ -53,10 +54,6 @@ const (
)
)
var (
var (
// LookbackDelta determines the time since the last sample after which a time
// series is considered stale.
LookbackDelta = 5 * time . Minute
// DefaultEvaluationInterval is the default evaluation interval of
// DefaultEvaluationInterval is the default evaluation interval of
// a subquery in milliseconds.
// a subquery in milliseconds.
DefaultEvaluationInterval int64
DefaultEvaluationInterval int64
@ -220,6 +217,9 @@ type EngineOpts struct {
MaxSamples int
MaxSamples int
Timeout time . Duration
Timeout time . Duration
ActiveQueryTracker * ActiveQueryTracker
ActiveQueryTracker * ActiveQueryTracker
// LookbackDelta determines the time since the last sample after which a time
// series is considered stale.
LookbackDelta time . Duration
}
}
// Engine handles the lifetime of queries from beginning to end.
// Engine handles the lifetime of queries from beginning to end.
@ -232,6 +232,7 @@ type Engine struct {
activeQueryTracker * ActiveQueryTracker
activeQueryTracker * ActiveQueryTracker
queryLogger QueryLogger
queryLogger QueryLogger
queryLoggerLock sync . RWMutex
queryLoggerLock sync . RWMutex
lookbackDelta time . Duration
}
}
// NewEngine returns a new engine.
// NewEngine returns a new engine.
@ -305,6 +306,13 @@ func NewEngine(opts EngineOpts) *Engine {
metrics . maxConcurrentQueries . Set ( - 1 )
metrics . maxConcurrentQueries . Set ( - 1 )
}
}
if opts . LookbackDelta == 0 {
opts . LookbackDelta = defaultLookbackDelta
if l := opts . Logger ; l != nil {
level . Debug ( l ) . Log ( "msg" , "lookback delta is zero, setting to default value" , "value" , defaultLookbackDelta )
}
}
if opts . Reg != nil {
if opts . Reg != nil {
opts . Reg . MustRegister (
opts . Reg . MustRegister (
metrics . currentQueries ,
metrics . currentQueries ,
@ -324,6 +332,7 @@ func NewEngine(opts EngineOpts) *Engine {
metrics : metrics ,
metrics : metrics ,
maxSamplesPerQuery : opts . MaxSamples ,
maxSamplesPerQuery : opts . MaxSamples ,
activeQueryTracker : opts . ActiveQueryTracker ,
activeQueryTracker : opts . ActiveQueryTracker ,
lookbackDelta : opts . LookbackDelta ,
}
}
}
}
@ -533,6 +542,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
maxSamples : ng . maxSamplesPerQuery ,
maxSamples : ng . maxSamplesPerQuery ,
defaultEvalInterval : GetDefaultEvaluationInterval ( ) ,
defaultEvalInterval : GetDefaultEvaluationInterval ( ) ,
logger : ng . logger ,
logger : ng . logger ,
lookbackDelta : ng . lookbackDelta ,
}
}
val , err := evaluator . Eval ( s . Expr )
val , err := evaluator . Eval ( s . Expr )
@ -571,7 +581,6 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
default :
default :
panic ( errors . Errorf ( "promql.Engine.exec: unexpected expression type %q" , s . Expr . Type ( ) ) )
panic ( errors . Errorf ( "promql.Engine.exec: unexpected expression type %q" , s . Expr . Type ( ) ) )
}
}
}
}
// Range evaluation.
// Range evaluation.
@ -583,6 +592,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
maxSamples : ng . maxSamplesPerQuery ,
maxSamples : ng . maxSamplesPerQuery ,
defaultEvalInterval : GetDefaultEvaluationInterval ( ) ,
defaultEvalInterval : GetDefaultEvaluationInterval ( ) ,
logger : ng . logger ,
logger : ng . logger ,
lookbackDelta : ng . lookbackDelta ,
}
}
val , err := evaluator . Eval ( s . Expr )
val , err := evaluator . Eval ( s . Expr )
if err != nil {
if err != nil {
@ -626,11 +636,11 @@ func (ng *Engine) populateSeries(ctx context.Context, q storage.Queryable, s *Ev
subqOffset := ng . cumulativeSubqueryOffset ( path )
subqOffset := ng . cumulativeSubqueryOffset ( path )
switch n := node . ( type ) {
switch n := node . ( type ) {
case * VectorSelector :
case * VectorSelector :
if maxOffset < L ookbackDelta+ subqOffset {
if maxOffset < ng. l ookbackDelta+ subqOffset {
maxOffset = L ookbackDelta + subqOffset
maxOffset = ng. l ookbackDelta + subqOffset
}
}
if n . Offset + L ookbackDelta+ subqOffset > maxOffset {
if n . Offset + ng. l ookbackDelta+ subqOffset > maxOffset {
maxOffset = n . Offset + L ookbackDelta + subqOffset
maxOffset = n . Offset + ng. l ookbackDelta + subqOffset
}
}
case * MatrixSelector :
case * MatrixSelector :
if maxOffset < n . Range + subqOffset {
if maxOffset < n . Range + subqOffset {
@ -677,7 +687,7 @@ func (ng *Engine) populateSeries(ctx context.Context, q storage.Queryable, s *Ev
switch n := node . ( type ) {
switch n := node . ( type ) {
case * VectorSelector :
case * VectorSelector :
if evalRange == 0 {
if evalRange == 0 {
params . Start = params . Start - durationMilliseconds ( L ookbackDelta)
params . Start = params . Start - durationMilliseconds ( ng. l ookbackDelta)
} else {
} else {
params . Range = durationMilliseconds ( evalRange )
params . Range = durationMilliseconds ( evalRange )
// For all matrix queries we want to ensure that we have (end-start) + range selected
// For all matrix queries we want to ensure that we have (end-start) + range selected
@ -783,6 +793,7 @@ type evaluator struct {
currentSamples int
currentSamples int
defaultEvalInterval int64
defaultEvalInterval int64
logger log . Logger
logger log . Logger
lookbackDelta time . Duration
}
}
// errorf causes a panic with the input formatted into an error.
// errorf causes a panic with the input formatted into an error.
@ -1272,7 +1283,7 @@ func (ev *evaluator) eval(expr Expr) Value {
case * VectorSelector :
case * VectorSelector :
checkForSeriesSetExpansion ( ev . ctx , e )
checkForSeriesSetExpansion ( ev . ctx , e )
mat := make ( Matrix , 0 , len ( e . series ) )
mat := make ( Matrix , 0 , len ( e . series ) )
it := storage . NewBuffer ( durationMilliseconds ( L ookbackDelta) )
it := storage . NewBuffer ( durationMilliseconds ( ev. l ookbackDelta) )
for i , s := range e . series {
for i , s := range e . series {
it . Reset ( s . Iterator ( ) )
it . Reset ( s . Iterator ( ) )
ss := Series {
ss := Series {
@ -1318,6 +1329,7 @@ func (ev *evaluator) eval(expr Expr) Value {
maxSamples : ev . maxSamples ,
maxSamples : ev . maxSamples ,
defaultEvalInterval : ev . defaultEvalInterval ,
defaultEvalInterval : ev . defaultEvalInterval ,
logger : ev . logger ,
logger : ev . logger ,
lookbackDelta : ev . lookbackDelta ,
}
}
if e . Step != 0 {
if e . Step != 0 {
@ -1353,7 +1365,7 @@ func (ev *evaluator) vectorSelector(node *VectorSelector, ts int64) Vector {
vec = make ( Vector , 0 , len ( node . series ) )
vec = make ( Vector , 0 , len ( node . series ) )
)
)
it := storage . NewBuffer ( durationMilliseconds ( L ookbackDelta) )
it := storage . NewBuffer ( durationMilliseconds ( ev. l ookbackDelta) )
for i , s := range node . series {
for i , s := range node . series {
it . Reset ( s . Iterator ( ) )
it . Reset ( s . Iterator ( ) )
@ -1392,7 +1404,7 @@ func (ev *evaluator) vectorSelectorSingle(it *storage.BufferedSeriesIterator, no
if ! ok || t > refTime {
if ! ok || t > refTime {
t , v , ok = it . PeekBack ( 1 )
t , v , ok = it . PeekBack ( 1 )
if ! ok || t < refTime - durationMilliseconds ( L ookbackDelta) {
if ! ok || t < refTime - durationMilliseconds ( ev. l ookbackDelta) {
return 0 , 0 , false
return 0 , 0 , false
}
}
}
}