|
|
|
@ -998,6 +998,8 @@ func extractGroupsFromPath(p []parser.Node) (bool, []string) {
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// checkAndExpandSeriesSet expands expr's UnexpandedSeriesSet into expr's Series.
|
|
|
|
|
// If the Series field is already non-nil, it's a no-op.
|
|
|
|
|
func checkAndExpandSeriesSet(ctx context.Context, expr parser.Expr) (annotations.Annotations, error) {
|
|
|
|
|
switch e := expr.(type) {
|
|
|
|
|
case *parser.MatrixSelector:
|
|
|
|
@ -1449,6 +1451,70 @@ func (ev *evaluator) rangeEvalAgg(ctx context.Context, aggExpr *parser.Aggregate
|
|
|
|
|
return result, warnings
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// evalVectorSelector generates a Matrix between ev.startTimestamp and ev.endTimestamp (inclusive), each point spaced ev.interval apart, from vs.
|
|
|
|
|
// vs.Series has to be expanded before calling this method.
|
|
|
|
|
// For every series iterator in vs.Series, the method iterates in ev.interval sized steps from ev.startTimestamp until and including ev.endTimestamp,
|
|
|
|
|
// collecting every corresponding sample (obtained via ev.vectorSelectorSingle) into a Series.
|
|
|
|
|
// All of the generated Series are collected into a Matrix, that gets returned.
|
|
|
|
|
func (ev *evaluator) evalVectorSelector(ctx context.Context, vs *parser.VectorSelector) Matrix {
|
|
|
|
|
numSteps := int((ev.endTimestamp-ev.startTimestamp)/ev.interval) + 1
|
|
|
|
|
|
|
|
|
|
mat := make(Matrix, 0, len(vs.Series))
|
|
|
|
|
var prevSS *Series
|
|
|
|
|
it := storage.NewMemoizedEmptyIterator(durationMilliseconds(ev.lookbackDelta))
|
|
|
|
|
var chkIter chunkenc.Iterator
|
|
|
|
|
for _, s := range vs.Series {
|
|
|
|
|
if err := contextDone(ctx, "expression evaluation"); err != nil {
|
|
|
|
|
ev.error(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chkIter = s.Iterator(chkIter)
|
|
|
|
|
it.Reset(chkIter)
|
|
|
|
|
ss := Series{
|
|
|
|
|
Metric: s.Labels(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ts, step := ev.startTimestamp, -1; ts <= ev.endTimestamp; ts += ev.interval {
|
|
|
|
|
step++
|
|
|
|
|
_, f, h, ok := ev.vectorSelectorSingle(it, vs, ts)
|
|
|
|
|
if !ok {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if h == nil {
|
|
|
|
|
ev.currentSamples++
|
|
|
|
|
ev.samplesStats.IncrementSamplesAtStep(step, 1)
|
|
|
|
|
if ev.currentSamples > ev.maxSamples {
|
|
|
|
|
ev.error(ErrTooManySamples(env))
|
|
|
|
|
}
|
|
|
|
|
if ss.Floats == nil {
|
|
|
|
|
ss.Floats = reuseOrGetFPointSlices(prevSS, numSteps)
|
|
|
|
|
}
|
|
|
|
|
ss.Floats = append(ss.Floats, FPoint{F: f, T: ts})
|
|
|
|
|
} else {
|
|
|
|
|
point := HPoint{H: h, T: ts}
|
|
|
|
|
histSize := point.size()
|
|
|
|
|
ev.currentSamples += histSize
|
|
|
|
|
ev.samplesStats.IncrementSamplesAtStep(step, int64(histSize))
|
|
|
|
|
if ev.currentSamples > ev.maxSamples {
|
|
|
|
|
ev.error(ErrTooManySamples(env))
|
|
|
|
|
}
|
|
|
|
|
if ss.Histograms == nil {
|
|
|
|
|
ss.Histograms = reuseOrGetHPointSlices(prevSS, numSteps)
|
|
|
|
|
}
|
|
|
|
|
ss.Histograms = append(ss.Histograms, point)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(ss.Floats)+len(ss.Histograms) > 0 {
|
|
|
|
|
mat = append(mat, ss)
|
|
|
|
|
prevSS = &mat[len(mat)-1]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ev.samplesStats.UpdatePeak(ev.currentSamples)
|
|
|
|
|
return mat
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// evalSubquery evaluates given SubqueryExpr and returns an equivalent
|
|
|
|
|
// evaluated MatrixSelector in its place. Note that the Name and LabelMatchers are not set.
|
|
|
|
|
func (ev *evaluator) evalSubquery(ctx context.Context, subq *parser.SubqueryExpr) (*parser.MatrixSelector, int, annotations.Annotations) {
|
|
|
|
@ -1887,56 +1953,7 @@ func (ev *evaluator) eval(ctx context.Context, expr parser.Expr) (parser.Value,
|
|
|
|
|
if err != nil {
|
|
|
|
|
ev.error(errWithWarnings{fmt.Errorf("expanding series: %w", err), ws})
|
|
|
|
|
}
|
|
|
|
|
mat := make(Matrix, 0, len(e.Series))
|
|
|
|
|
var prevSS *Series
|
|
|
|
|
it := storage.NewMemoizedEmptyIterator(durationMilliseconds(ev.lookbackDelta))
|
|
|
|
|
var chkIter chunkenc.Iterator
|
|
|
|
|
for i, s := range e.Series {
|
|
|
|
|
if err := contextDone(ctx, "expression evaluation"); err != nil {
|
|
|
|
|
ev.error(err)
|
|
|
|
|
}
|
|
|
|
|
chkIter = s.Iterator(chkIter)
|
|
|
|
|
it.Reset(chkIter)
|
|
|
|
|
ss := Series{
|
|
|
|
|
Metric: e.Series[i].Labels(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ts, step := ev.startTimestamp, -1; ts <= ev.endTimestamp; ts += ev.interval {
|
|
|
|
|
step++
|
|
|
|
|
_, f, h, ok := ev.vectorSelectorSingle(it, e, ts)
|
|
|
|
|
if ok {
|
|
|
|
|
if h == nil {
|
|
|
|
|
ev.currentSamples++
|
|
|
|
|
ev.samplesStats.IncrementSamplesAtStep(step, 1)
|
|
|
|
|
if ev.currentSamples > ev.maxSamples {
|
|
|
|
|
ev.error(ErrTooManySamples(env))
|
|
|
|
|
}
|
|
|
|
|
if ss.Floats == nil {
|
|
|
|
|
ss.Floats = reuseOrGetFPointSlices(prevSS, numSteps)
|
|
|
|
|
}
|
|
|
|
|
ss.Floats = append(ss.Floats, FPoint{F: f, T: ts})
|
|
|
|
|
} else {
|
|
|
|
|
point := HPoint{H: h, T: ts}
|
|
|
|
|
histSize := point.size()
|
|
|
|
|
ev.currentSamples += histSize
|
|
|
|
|
ev.samplesStats.IncrementSamplesAtStep(step, int64(histSize))
|
|
|
|
|
if ev.currentSamples > ev.maxSamples {
|
|
|
|
|
ev.error(ErrTooManySamples(env))
|
|
|
|
|
}
|
|
|
|
|
if ss.Histograms == nil {
|
|
|
|
|
ss.Histograms = reuseOrGetHPointSlices(prevSS, numSteps)
|
|
|
|
|
}
|
|
|
|
|
ss.Histograms = append(ss.Histograms, point)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(ss.Floats)+len(ss.Histograms) > 0 {
|
|
|
|
|
mat = append(mat, ss)
|
|
|
|
|
prevSS = &mat[len(mat)-1]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ev.samplesStats.UpdatePeak(ev.currentSamples)
|
|
|
|
|
mat := ev.evalVectorSelector(ctx, e)
|
|
|
|
|
return mat, ws
|
|
|
|
|
|
|
|
|
|
case *parser.MatrixSelector:
|
|
|
|
|