Browse Source

perf(query): Align start/end times with step

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

Signed-off-by: pokom <mark.poko@grafana.com>
pokom 3 năm trước cách đây
mục cha
commit
ef27ef8d06
1 tập tin đã thay đổi với 16 bổ sung0 xóa
  1. 16 0
      pkg/prom/query.go

+ 16 - 0
pkg/prom/query.go

@@ -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
@@ -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
 	}
@@ -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