|
|
|
@ -85,7 +85,7 @@ type Query interface {
|
|
|
|
|
// Statement returns the parsed statement of the query.
|
|
|
|
|
Statement() Statement |
|
|
|
|
// Stats returns statistics about the lifetime of the query.
|
|
|
|
|
Stats() *stats.TimerGroup |
|
|
|
|
Stats() *stats.QueryTimers |
|
|
|
|
// Cancel signals that a running query execution should be aborted.
|
|
|
|
|
Cancel() |
|
|
|
|
} |
|
|
|
@ -99,7 +99,7 @@ type query struct {
|
|
|
|
|
// Statement of the parsed query.
|
|
|
|
|
stmt Statement |
|
|
|
|
// Timer stats for the query execution.
|
|
|
|
|
stats *stats.TimerGroup |
|
|
|
|
stats *stats.QueryTimers |
|
|
|
|
// Result matrix for reuse.
|
|
|
|
|
matrix Matrix |
|
|
|
|
// Cancellation function for the query.
|
|
|
|
@ -115,7 +115,7 @@ func (q *query) Statement() Statement {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Stats implements the Query interface.
|
|
|
|
|
func (q *query) Stats() *stats.TimerGroup { |
|
|
|
|
func (q *query) Stats() *stats.QueryTimers { |
|
|
|
|
return q.stats |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -276,7 +276,7 @@ func (ng *Engine) newQuery(q storage.Queryable, expr Expr, start, end time.Time,
|
|
|
|
|
qry := &query{ |
|
|
|
|
stmt: es, |
|
|
|
|
ng: ng, |
|
|
|
|
stats: stats.NewTimerGroup(), |
|
|
|
|
stats: stats.NewQueryTimers(), |
|
|
|
|
queryable: q, |
|
|
|
|
} |
|
|
|
|
return qry |
|
|
|
@ -294,7 +294,7 @@ func (ng *Engine) newTestQuery(f func(context.Context) error) Query {
|
|
|
|
|
q: "test statement", |
|
|
|
|
stmt: testStmt(f), |
|
|
|
|
ng: ng, |
|
|
|
|
stats: stats.NewTimerGroup(), |
|
|
|
|
stats: stats.NewQueryTimers(), |
|
|
|
|
} |
|
|
|
|
return qry |
|
|
|
|
} |
|
|
|
@ -310,25 +310,25 @@ func (ng *Engine) exec(ctx context.Context, q *query) (Value, error) {
|
|
|
|
|
ctx, cancel := context.WithTimeout(ctx, ng.timeout) |
|
|
|
|
q.cancel = cancel |
|
|
|
|
|
|
|
|
|
execTimer := q.stats.GetTimer(stats.ExecTotalTime).Start() |
|
|
|
|
defer execTimer.Stop() |
|
|
|
|
queueTimer := q.stats.GetTimer(stats.ExecQueueTime).Start() |
|
|
|
|
execSpanTimer, ctx := q.stats.GetSpanTimer(ctx, stats.ExecTotalTime) |
|
|
|
|
defer execSpanTimer.Finish() |
|
|
|
|
|
|
|
|
|
queueSpanTimer, _ := q.stats.GetSpanTimer(ctx, stats.ExecQueueTime, ng.metrics.queryQueueTime) |
|
|
|
|
|
|
|
|
|
if err := ng.gate.Start(ctx); err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
defer ng.gate.Done() |
|
|
|
|
|
|
|
|
|
queueTimer.Stop() |
|
|
|
|
ng.metrics.queryQueueTime.Observe(queueTimer.ElapsedTime().Seconds()) |
|
|
|
|
queueSpanTimer.Finish() |
|
|
|
|
|
|
|
|
|
// Cancel when execution is done or an error was raised.
|
|
|
|
|
defer q.cancel() |
|
|
|
|
|
|
|
|
|
const env = "query execution" |
|
|
|
|
|
|
|
|
|
evalTimer := q.stats.GetTimer(stats.EvalTotalTime).Start() |
|
|
|
|
defer evalTimer.Stop() |
|
|
|
|
evalSpanTimer, ctx := q.stats.GetSpanTimer(ctx, stats.EvalTotalTime) |
|
|
|
|
defer evalSpanTimer.Finish() |
|
|
|
|
|
|
|
|
|
// The base context might already be canceled on the first iteration (e.g. during shutdown).
|
|
|
|
|
if err := contextDone(ctx, env); err != nil { |
|
|
|
@ -355,10 +355,9 @@ func durationMilliseconds(d time.Duration) int64 {
|
|
|
|
|
|
|
|
|
|
// execEvalStmt evaluates the expression of an evaluation statement for the given time range.
|
|
|
|
|
func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (Value, error) { |
|
|
|
|
prepareTimer := query.stats.GetTimer(stats.QueryPreparationTime).Start() |
|
|
|
|
querier, err := ng.populateSeries(ctx, query.queryable, s) |
|
|
|
|
prepareTimer.Stop() |
|
|
|
|
ng.metrics.queryPrepareTime.Observe(prepareTimer.ElapsedTime().Seconds()) |
|
|
|
|
prepareSpanTimer, ctxPrepare := query.stats.GetSpanTimer(ctx, stats.QueryPreparationTime, ng.metrics.queryPrepareTime) |
|
|
|
|
querier, err := ng.populateSeries(ctxPrepare, query.queryable, s) |
|
|
|
|
prepareSpanTimer.Finish() |
|
|
|
|
|
|
|
|
|
// XXX(fabxc): the querier returned by populateSeries might be instantiated
|
|
|
|
|
// we must not return without closing irrespective of the error.
|
|
|
|
@ -371,7 +370,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
|
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
evalTimer := query.stats.GetTimer(stats.InnerEvalTime).Start() |
|
|
|
|
evalSpanTimer, _ := query.stats.GetSpanTimer(ctx, stats.InnerEvalTime, ng.metrics.queryInnerEval) |
|
|
|
|
// Instant evaluation. This is executed as a range evaluation with one step.
|
|
|
|
|
if s.Start == s.End && s.Interval == 0 { |
|
|
|
|
start := timeMilliseconds(s.Start) |
|
|
|
@ -387,8 +386,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
|
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
evalTimer.Stop() |
|
|
|
|
ng.metrics.queryInnerEval.Observe(evalTimer.ElapsedTime().Seconds()) |
|
|
|
|
evalSpanTimer.Finish() |
|
|
|
|
|
|
|
|
|
mat, ok := val.(Matrix) |
|
|
|
|
if !ok { |
|
|
|
@ -427,8 +425,7 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
|
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
evalTimer.Stop() |
|
|
|
|
ng.metrics.queryInnerEval.Observe(evalTimer.ElapsedTime().Seconds()) |
|
|
|
|
evalSpanTimer.Finish() |
|
|
|
|
|
|
|
|
|
mat, ok := val.(Matrix) |
|
|
|
|
if !ok { |
|
|
|
@ -442,11 +439,10 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
|
|
|
|
|
|
|
|
|
|
// TODO(fabxc): order ensured by storage?
|
|
|
|
|
// TODO(fabxc): where to ensure metric labels are a copy from the storage internals.
|
|
|
|
|
sortTimer := query.stats.GetTimer(stats.ResultSortTime).Start() |
|
|
|
|
sortSpanTimer, _ := query.stats.GetSpanTimer(ctx, stats.ResultSortTime, ng.metrics.queryResultSort) |
|
|
|
|
sort.Sort(mat) |
|
|
|
|
sortTimer.Stop() |
|
|
|
|
sortSpanTimer.Finish() |
|
|
|
|
|
|
|
|
|
ng.metrics.queryResultSort.Observe(sortTimer.ElapsedTime().Seconds()) |
|
|
|
|
return mat, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|