Hardcode rate() for sparse histograms
Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com>
This commit is contained in:
parent
67871fd1f2
commit
4cb4fe44f2
|
@ -497,6 +497,27 @@ func (api *API) queryRange(r *http.Request) (result apiFuncResult) {
|
||||||
return apiFuncResult{nil, &apiError{errorBadData, errors.New("need exactly 1 selector")}, nil, nil}
|
return apiFuncResult{nil, &apiError{errorBadData, errors.New("need exactly 1 selector")}, nil, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasRate, rateDuration := false, time.Duration(0)
|
||||||
|
parser.Inspect(expr, func(node parser.Node, path []parser.Node) error {
|
||||||
|
switch n := node.(type) {
|
||||||
|
case *parser.Call:
|
||||||
|
if n.Func.Name == "rate" {
|
||||||
|
hasRate = true
|
||||||
|
rateDuration = n.Args[0].(*parser.MatrixSelector).Range
|
||||||
|
return errors.New("stop it here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
var numRateSamples int
|
||||||
|
if hasRate {
|
||||||
|
numRateSamples = int(end.Sub(start)/step + 1)
|
||||||
|
if start.Add(time.Duration(numRateSamples-1) * step).After(end) {
|
||||||
|
numRateSamples--
|
||||||
|
}
|
||||||
|
start = start.Add(-rateDuration) // Adjusting for the first point lookback.
|
||||||
|
}
|
||||||
|
|
||||||
q, err := api.Queryable.Querier(ctx, timestamp.FromTime(start), timestamp.FromTime(end))
|
q, err := api.Queryable.Querier(ctx, timestamp.FromTime(start), timestamp.FromTime(end))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apiFuncResult{nil, &apiError{errorExec, err}, nil, nil}
|
return apiFuncResult{nil, &apiError{errorExec, err}, nil, nil}
|
||||||
|
@ -544,6 +565,55 @@ func (api *API) queryRange(r *http.Request) (result apiFuncResult) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hasRate {
|
||||||
|
newRes := make(promql.Matrix, len(res))
|
||||||
|
for i := range newRes {
|
||||||
|
newRes[i].Metric = res[i].Metric
|
||||||
|
points := make([]promql.Point, numRateSamples)
|
||||||
|
|
||||||
|
rawPoints := res[i].Points
|
||||||
|
|
||||||
|
startIdx, endIdx := 0, 0
|
||||||
|
for idx := range points {
|
||||||
|
pointTime := start.Add(time.Duration(idx) * step)
|
||||||
|
lookbackTime := pointTime.Add(-rateDuration)
|
||||||
|
points[idx].T = timestamp.FromTime(pointTime)
|
||||||
|
if len(rawPoints) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for startIdx < len(rawPoints) && timestamp.Time(rawPoints[startIdx].T).Before(lookbackTime) {
|
||||||
|
startIdx++
|
||||||
|
}
|
||||||
|
if startIdx >= len(rawPoints) {
|
||||||
|
startIdx = len(rawPoints) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for endIdx < len(rawPoints) && timestamp.Time(rawPoints[endIdx].T).Before(pointTime) {
|
||||||
|
endIdx++
|
||||||
|
}
|
||||||
|
if endIdx >= len(rawPoints) {
|
||||||
|
endIdx = len(rawPoints) - 1
|
||||||
|
} else if timestamp.Time(rawPoints[endIdx].T).After(pointTime) && (len(rawPoints) == 1 || endIdx == 0) {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
endIdx--
|
||||||
|
}
|
||||||
|
|
||||||
|
valDiff := rawPoints[endIdx].V - rawPoints[startIdx].V
|
||||||
|
timeDiffSeconds := float64(timestamp.Time(rawPoints[endIdx].T).Sub(timestamp.Time(rawPoints[startIdx].T))) / float64(time.Second)
|
||||||
|
|
||||||
|
if timeDiffSeconds != 0 {
|
||||||
|
points[idx].V = valDiff / timeDiffSeconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newRes[i].Points = points
|
||||||
|
}
|
||||||
|
|
||||||
|
res = newRes
|
||||||
|
}
|
||||||
|
|
||||||
sort.Sort(res)
|
sort.Sort(res)
|
||||||
|
|
||||||
return apiFuncResult{&queryData{
|
return apiFuncResult{&queryData{
|
||||||
|
|
Loading…
Reference in New Issue