|
|
|
@ -2740,7 +2740,7 @@ func (ev *evaluator) aggregation(e *parser.AggregateExpr, q float64, inputMatrix
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for si := range inputMatrix { |
|
|
|
|
s, ok := ev.nextSample(enh.Ts, inputMatrix, si) |
|
|
|
|
f, h, ok := ev.nextValues(enh.Ts, &inputMatrix[si]) |
|
|
|
|
if !ok { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
@ -2749,18 +2749,18 @@ func (ev *evaluator) aggregation(e *parser.AggregateExpr, q float64, inputMatrix
|
|
|
|
|
// Initialize this group if it's the first time we've seen it.
|
|
|
|
|
if !seen[seriesToResult[si]] { |
|
|
|
|
*group = groupedAggregation{ |
|
|
|
|
floatValue: s.F, |
|
|
|
|
floatMean: s.F, |
|
|
|
|
floatValue: f, |
|
|
|
|
floatMean: f, |
|
|
|
|
groupCount: 1, |
|
|
|
|
} |
|
|
|
|
switch { |
|
|
|
|
case s.H == nil: |
|
|
|
|
case h == nil: |
|
|
|
|
group.hasFloat = true |
|
|
|
|
case op == parser.SUM: |
|
|
|
|
group.histogramValue = s.H.Copy() |
|
|
|
|
group.histogramValue = h.Copy() |
|
|
|
|
group.hasHistogram = true |
|
|
|
|
case op == parser.AVG: |
|
|
|
|
group.histogramMean = s.H.Copy() |
|
|
|
|
group.histogramMean = h.Copy() |
|
|
|
|
group.hasHistogram = true |
|
|
|
|
case op == parser.STDVAR || op == parser.STDDEV: |
|
|
|
|
group.groupCount = 0 |
|
|
|
@ -2771,10 +2771,7 @@ func (ev *evaluator) aggregation(e *parser.AggregateExpr, q float64, inputMatrix
|
|
|
|
|
group.floatValue = 0 |
|
|
|
|
case parser.QUANTILE: |
|
|
|
|
group.heap = make(vectorByValueHeap, 1) |
|
|
|
|
group.heap[0] = Sample{ |
|
|
|
|
F: s.F, |
|
|
|
|
Metric: s.Metric, |
|
|
|
|
} |
|
|
|
|
group.heap[0] = Sample{F: f} |
|
|
|
|
case parser.GROUP: |
|
|
|
|
group.floatValue = 1 |
|
|
|
|
} |
|
|
|
@ -2784,25 +2781,25 @@ func (ev *evaluator) aggregation(e *parser.AggregateExpr, q float64, inputMatrix
|
|
|
|
|
|
|
|
|
|
switch op { |
|
|
|
|
case parser.SUM: |
|
|
|
|
if s.H != nil { |
|
|
|
|
if h != nil { |
|
|
|
|
group.hasHistogram = true |
|
|
|
|
if group.histogramValue != nil { |
|
|
|
|
group.histogramValue.Add(s.H) |
|
|
|
|
group.histogramValue.Add(h) |
|
|
|
|
} |
|
|
|
|
// Otherwise the aggregation contained floats
|
|
|
|
|
// previously and will be invalid anyway. No
|
|
|
|
|
// point in copying the histogram in that case.
|
|
|
|
|
} else { |
|
|
|
|
group.hasFloat = true |
|
|
|
|
group.floatValue += s.F |
|
|
|
|
group.floatValue += f |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case parser.AVG: |
|
|
|
|
group.groupCount++ |
|
|
|
|
if s.H != nil { |
|
|
|
|
if h != nil { |
|
|
|
|
group.hasHistogram = true |
|
|
|
|
if group.histogramMean != nil { |
|
|
|
|
left := s.H.Copy().Div(float64(group.groupCount)) |
|
|
|
|
left := h.Copy().Div(float64(group.groupCount)) |
|
|
|
|
right := group.histogramMean.Copy().Div(float64(group.groupCount)) |
|
|
|
|
toAdd := left.Sub(right) |
|
|
|
|
group.histogramMean.Add(toAdd) |
|
|
|
@ -2813,13 +2810,13 @@ func (ev *evaluator) aggregation(e *parser.AggregateExpr, q float64, inputMatrix
|
|
|
|
|
} else { |
|
|
|
|
group.hasFloat = true |
|
|
|
|
if math.IsInf(group.floatMean, 0) { |
|
|
|
|
if math.IsInf(s.F, 0) && (group.floatMean > 0) == (s.F > 0) { |
|
|
|
|
if math.IsInf(f, 0) && (group.floatMean > 0) == (f > 0) { |
|
|
|
|
// The `floatMean` and `s.F` values are `Inf` of the same sign. They
|
|
|
|
|
// can't be subtracted, but the value of `floatMean` is correct
|
|
|
|
|
// already.
|
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
if !math.IsInf(s.F, 0) && !math.IsNaN(s.F) { |
|
|
|
|
if !math.IsInf(f, 0) && !math.IsNaN(f) { |
|
|
|
|
// At this stage, the mean is an infinite. If the added
|
|
|
|
|
// value is neither an Inf or a Nan, we can keep that mean
|
|
|
|
|
// value.
|
|
|
|
@ -2830,35 +2827,35 @@ func (ev *evaluator) aggregation(e *parser.AggregateExpr, q float64, inputMatrix
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Divide each side of the `-` by `group.groupCount` to avoid float64 overflows.
|
|
|
|
|
group.floatMean += s.F/float64(group.groupCount) - group.floatMean/float64(group.groupCount) |
|
|
|
|
group.floatMean += f/float64(group.groupCount) - group.floatMean/float64(group.groupCount) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case parser.GROUP: |
|
|
|
|
// Do nothing. Required to avoid the panic in `default:` below.
|
|
|
|
|
|
|
|
|
|
case parser.MAX: |
|
|
|
|
if group.floatValue < s.F || math.IsNaN(group.floatValue) { |
|
|
|
|
group.floatValue = s.F |
|
|
|
|
if group.floatValue < f || math.IsNaN(group.floatValue) { |
|
|
|
|
group.floatValue = f |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case parser.MIN: |
|
|
|
|
if group.floatValue > s.F || math.IsNaN(group.floatValue) { |
|
|
|
|
group.floatValue = s.F |
|
|
|
|
if group.floatValue > f || math.IsNaN(group.floatValue) { |
|
|
|
|
group.floatValue = f |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case parser.COUNT: |
|
|
|
|
group.groupCount++ |
|
|
|
|
|
|
|
|
|
case parser.STDVAR, parser.STDDEV: |
|
|
|
|
if s.H == nil { // Ignore native histograms.
|
|
|
|
|
if h == nil { // Ignore native histograms.
|
|
|
|
|
group.groupCount++ |
|
|
|
|
delta := s.F - group.floatMean |
|
|
|
|
delta := f - group.floatMean |
|
|
|
|
group.floatMean += delta / float64(group.groupCount) |
|
|
|
|
group.floatValue += delta * (s.F - group.floatMean) |
|
|
|
|
group.floatValue += delta * (f - group.floatMean) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case parser.QUANTILE: |
|
|
|
|
group.heap = append(group.heap, s) |
|
|
|
|
group.heap = append(group.heap, Sample{F: f}) |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
panic(fmt.Errorf("expected aggregation operator but got %q", op)) |
|
|
|
|