Skip to content

Commit

Permalink
perf(query): Align start/end times with step
Browse files Browse the repository at this point in the history
Range queries will now have their start and end times aligned with the
step. This will help metric stores take better advantage of caches for
queries. See
(https://promlabs.com/blog/2020/06/18/the-anatomy-of-a-promql-query#range-queries)
for details on range queries.

- closes #1472
  • Loading branch information
Pokom committed Nov 7, 2022
1 parent 831c65c commit b94f65d
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions pkg/prom/query.go
Expand Up @@ -258,9 +258,18 @@ func (ctx *Context) query(query string, t time.Time) (interface{}, v1.Warnings,
return toReturn, warnings, nil
}

// isRequestStepAligned will check if the start and end times are aligned with the step
func (ctx *Context) isRequestStepAligned(start, end time.Time, step time.Duration) bool {
return start.Unix()%step.Milliseconds() == 0 && end.Unix()%step.Milliseconds() == 0
}

func (ctx *Context) QueryRange(query string, start, end time.Time, step time.Duration) QueryResultsChan {
resCh := make(QueryResultsChan)

if !ctx.isRequestStepAligned(start, end, step) {
start, end = ctx.alignWindow(start, end, step)
}

go runQueryRange(query, start, end, step, ctx, resCh, "")

return resCh
Expand Down Expand Up @@ -357,6 +366,7 @@ func (ctx *Context) RawQueryRange(query string, start, end time.Time, step time.

func (ctx *Context) queryRange(query string, start, end time.Time, step time.Duration) (interface{}, v1.Warnings, error) {
body, err := ctx.RawQueryRange(query, start, end, step)

if err != nil {
return nil, nil, err
}
Expand All @@ -382,6 +392,12 @@ func (ctx *Context) queryRange(query string, start, end time.Time, step time.Dur
return toReturn, warnings, nil
}

func (ctx *Context) alignWindow(start time.Time, end time.Time, step time.Duration) (time.Time, time.Time) {
alignedStart := (start.Unix() / step.Milliseconds()) * start.Unix()
alignedEnd := (end.Unix() / step.Milliseconds()) * end.Unix()
return time.UnixMilli(alignedStart), time.UnixMilli(alignedEnd)
}

// Extracts the warnings from the resulting json if they exist (part of the prometheus response api).
func warningsFrom(result interface{}) v1.Warnings {
var warnings v1.Warnings
Expand Down

0 comments on commit b94f65d

Please sign in to comment.