mirror of https://github.com/prometheus/prometheus
Support + operator for sparse histograms (#9949)
Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com>pull/10025/head
parent
187a767292
commit
f580248759
|
@ -1960,10 +1960,12 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
||||||
|
|
||||||
// Account for potentially swapped sidedness.
|
// Account for potentially swapped sidedness.
|
||||||
vl, vr := ls.V, rs.V
|
vl, vr := ls.V, rs.V
|
||||||
|
hl, hr := ls.H, rs.H
|
||||||
if matching.Card == parser.CardOneToMany {
|
if matching.Card == parser.CardOneToMany {
|
||||||
vl, vr = vr, vl
|
vl, vr = vr, vl
|
||||||
|
hl, hr = hr, hl
|
||||||
}
|
}
|
||||||
value, keep := vectorElemBinop(op, vl, vr)
|
value, histogramValue, keep := vectorElemBinop(op, vl, vr, hl, hr)
|
||||||
if returnBool {
|
if returnBool {
|
||||||
if keep {
|
if keep {
|
||||||
value = 1.0
|
value = 1.0
|
||||||
|
@ -1998,11 +2000,14 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
||||||
insertedSigs[insertSig] = struct{}{}
|
insertedSigs[insertSig] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hl != nil && hr != nil) || (hl == nil && hr == nil) {
|
||||||
|
// Both lhs and rhs are of same type.
|
||||||
enh.Out = append(enh.Out, Sample{
|
enh.Out = append(enh.Out, Sample{
|
||||||
Metric: metric,
|
Metric: metric,
|
||||||
Point: Point{V: value},
|
Point: Point{V: value, H: histogramValue},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return enh.Out
|
return enh.Out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2085,7 +2090,7 @@ func (ev *evaluator) VectorscalarBinop(op parser.ItemType, lhs Vector, rhs Scala
|
||||||
if swap {
|
if swap {
|
||||||
lv, rv = rv, lv
|
lv, rv = rv, lv
|
||||||
}
|
}
|
||||||
value, keep := vectorElemBinop(op, lv, rv)
|
value, _, keep := vectorElemBinop(op, lv, rv, nil, nil)
|
||||||
// Catch cases where the scalar is the LHS in a scalar-vector comparison operation.
|
// Catch cases where the scalar is the LHS in a scalar-vector comparison operation.
|
||||||
// We want to always keep the vector element value as the output value, even if it's on the RHS.
|
// We want to always keep the vector element value as the output value, even if it's on the RHS.
|
||||||
if op.IsComparisonOperator() && swap {
|
if op.IsComparisonOperator() && swap {
|
||||||
|
@ -2148,34 +2153,37 @@ func scalarBinop(op parser.ItemType, lhs, rhs float64) float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// vectorElemBinop evaluates a binary operation between two Vector elements.
|
// vectorElemBinop evaluates a binary operation between two Vector elements.
|
||||||
func vectorElemBinop(op parser.ItemType, lhs, rhs float64) (float64, bool) {
|
func vectorElemBinop(op parser.ItemType, lhs, rhs float64, hlhs, hrhs *histogram.FloatHistogram) (float64, *histogram.FloatHistogram, bool) {
|
||||||
switch op {
|
switch op {
|
||||||
case parser.ADD:
|
case parser.ADD:
|
||||||
return lhs + rhs, true
|
if hlhs != nil && hrhs != nil {
|
||||||
|
return 0, hlhs.Copy().Add(hrhs), true
|
||||||
|
}
|
||||||
|
return lhs + rhs, nil, true
|
||||||
case parser.SUB:
|
case parser.SUB:
|
||||||
return lhs - rhs, true
|
return lhs - rhs, nil, true
|
||||||
case parser.MUL:
|
case parser.MUL:
|
||||||
return lhs * rhs, true
|
return lhs * rhs, nil, true
|
||||||
case parser.DIV:
|
case parser.DIV:
|
||||||
return lhs / rhs, true
|
return lhs / rhs, nil, true
|
||||||
case parser.POW:
|
case parser.POW:
|
||||||
return math.Pow(lhs, rhs), true
|
return math.Pow(lhs, rhs), nil, true
|
||||||
case parser.MOD:
|
case parser.MOD:
|
||||||
return math.Mod(lhs, rhs), true
|
return math.Mod(lhs, rhs), nil, true
|
||||||
case parser.EQLC:
|
case parser.EQLC:
|
||||||
return lhs, lhs == rhs
|
return lhs, nil, lhs == rhs
|
||||||
case parser.NEQ:
|
case parser.NEQ:
|
||||||
return lhs, lhs != rhs
|
return lhs, nil, lhs != rhs
|
||||||
case parser.GTR:
|
case parser.GTR:
|
||||||
return lhs, lhs > rhs
|
return lhs, nil, lhs > rhs
|
||||||
case parser.LSS:
|
case parser.LSS:
|
||||||
return lhs, lhs < rhs
|
return lhs, nil, lhs < rhs
|
||||||
case parser.GTE:
|
case parser.GTE:
|
||||||
return lhs, lhs >= rhs
|
return lhs, nil, lhs >= rhs
|
||||||
case parser.LTE:
|
case parser.LTE:
|
||||||
return lhs, lhs <= rhs
|
return lhs, nil, lhs <= rhs
|
||||||
case parser.ATAN2:
|
case parser.ATAN2:
|
||||||
return math.Atan2(lhs, rhs), true
|
return math.Atan2(lhs, rhs), nil, true
|
||||||
}
|
}
|
||||||
panic(errors.Errorf("operator %q not allowed for operations between Vectors", op))
|
panic(errors.Errorf("operator %q not allowed for operations between Vectors", op))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2900,7 +2900,7 @@ func TestSparseHistogram_HistogramQuantile(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSparseHistogram_Sum(t *testing.T) {
|
func TestSparseHistogram_Sum_AddOperator(t *testing.T) {
|
||||||
// TODO(codesome): Integrate histograms into the PromQL testing framework
|
// TODO(codesome): Integrate histograms into the PromQL testing framework
|
||||||
// and write more tests there.
|
// and write more tests there.
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
|
@ -3006,7 +3006,7 @@ func TestSparseHistogram_Sum(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, app.Commit())
|
require.NoError(t, app.Commit())
|
||||||
|
|
||||||
queryString := fmt.Sprintf("sum(%s)", seriesName)
|
queryAndCheck := func(queryString string) {
|
||||||
qry, err := engine.NewInstantQuery(test.Queryable(), queryString, timestamp.Time(ts))
|
qry, err := engine.NewInstantQuery(test.Queryable(), queryString, timestamp.Time(ts))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -3018,6 +3018,18 @@ func TestSparseHistogram_Sum(t *testing.T) {
|
||||||
|
|
||||||
require.Len(t, vector, 1)
|
require.Len(t, vector, 1)
|
||||||
require.Equal(t, &c.expected, vector[0].H)
|
require.Equal(t, &c.expected, vector[0].H)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sum().
|
||||||
|
queryString := fmt.Sprintf("sum(%s)", seriesName)
|
||||||
|
queryAndCheck(queryString)
|
||||||
|
|
||||||
|
// + operator.
|
||||||
|
queryString = fmt.Sprintf(`%s{idx="0"}`, seriesName)
|
||||||
|
for idx := 1; idx < len(c.histograms); idx++ {
|
||||||
|
queryString += fmt.Sprintf(` + ignoring(idx) %s{idx="%d"}`, seriesName, idx)
|
||||||
|
}
|
||||||
|
queryAndCheck(queryString)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue