diff --git a/pkg/expr/commands.go b/pkg/expr/commands.go index 02b81edffd7..8f410f04b01 100644 --- a/pkg/expr/commands.go +++ b/pkg/expr/commands.go @@ -21,11 +21,12 @@ type Command interface { type MathCommand struct { RawExpression string Expression *mathexp.Expr + refID string } // NewMathCommand creates a new MathCommand. It will return an error // if there is an error parsing expr. -func NewMathCommand(expr string) (*MathCommand, error) { +func NewMathCommand(refID, expr string) (*MathCommand, error) { parsedExpr, err := mathexp.New(expr) if err != nil { return nil, err @@ -33,6 +34,7 @@ func NewMathCommand(expr string) (*MathCommand, error) { return &MathCommand{ RawExpression: expr, Expression: parsedExpr, + refID: refID, }, nil } @@ -47,7 +49,7 @@ func UnmarshalMathCommand(rn *rawNode) (*MathCommand, error) { return nil, fmt.Errorf("expected math command for refId %v expression to be a string, got %T", rn.RefID, rawExpr) } - gm, err := NewMathCommand(exprString) + gm, err := NewMathCommand(rn.RefID, exprString) if err != nil { return nil, fmt.Errorf("invalid math command type in '%v': %v", rn.RefID, err) } @@ -63,21 +65,23 @@ func (gm *MathCommand) NeedsVars() []string { // Execute runs the command and returns the results or an error if the command // failed to execute. func (gm *MathCommand) Execute(ctx context.Context, vars mathexp.Vars) (mathexp.Results, error) { - return gm.Expression.Execute(vars) + return gm.Expression.Execute(gm.refID, vars) } // ReduceCommand is an expression command for reduction of a timeseries such as a min, mean, or max. type ReduceCommand struct { Reducer string VarToReduce string + refID string } // NewReduceCommand creates a new ReduceCMD. -func NewReduceCommand(reducer, varToReduce string) *ReduceCommand { +func NewReduceCommand(refID, reducer, varToReduce string) *ReduceCommand { // TODO: validate reducer here, before execution return &ReduceCommand{ Reducer: reducer, VarToReduce: varToReduce, + refID: refID, } } @@ -102,7 +106,7 @@ func UnmarshalReduceCommand(rn *rawNode) (*ReduceCommand, error) { return nil, fmt.Errorf("expected reducer to be a string, got %T for refId %v", rawReducer, rn.RefID) } - return NewReduceCommand(redFunc, varToReduce), nil + return NewReduceCommand(rn.RefID, redFunc, varToReduce), nil } // NeedsVars returns the variable names (refIds) that are dependencies @@ -120,7 +124,7 @@ func (gr *ReduceCommand) Execute(ctx context.Context, vars mathexp.Vars) (mathex if !ok { return newRes, fmt.Errorf("can only reduce type series, got type %v", val.Type()) } - num, err := series.Reduce(gr.Reducer) + num, err := series.Reduce(gr.refID, gr.Reducer) if err != nil { return newRes, err } @@ -136,10 +140,11 @@ type ResampleCommand struct { Downsampler string Upsampler string TimeRange backend.TimeRange + refID string } // NewResampleCommand creates a new ResampleCMD. -func NewResampleCommand(rawWindow, varToResample string, downsampler string, upsampler string, tr backend.TimeRange) (*ResampleCommand, error) { +func NewResampleCommand(refID, rawWindow, varToResample string, downsampler string, upsampler string, tr backend.TimeRange) (*ResampleCommand, error) { // TODO: validate reducer here, before execution window, err := gtime.ParseDuration(rawWindow) if err != nil { @@ -151,6 +156,7 @@ func NewResampleCommand(rawWindow, varToResample string, downsampler string, ups Downsampler: downsampler, Upsampler: upsampler, TimeRange: tr, + refID: refID, }, nil } @@ -194,7 +200,7 @@ func UnmarshalResampleCommand(rn *rawNode) (*ResampleCommand, error) { return nil, fmt.Errorf("expected resample downsampler to be a string, got type %T for refId %v", upsampler, rn.RefID) } - return NewResampleCommand(window, varToResample, downsampler, upsampler, rn.TimeRange) + return NewResampleCommand(rn.RefID, window, varToResample, downsampler, upsampler, rn.TimeRange) } // NeedsVars returns the variable names (refIds) that are dependencies @@ -212,7 +218,7 @@ func (gr *ResampleCommand) Execute(ctx context.Context, vars mathexp.Vars) (math if !ok { return newRes, fmt.Errorf("can only resample type series, got type %v", val.Type()) } - num, err := series.Resample(gr.Window, gr.Downsampler, gr.Upsampler, gr.TimeRange) + num, err := series.Resample(gr.refID, gr.Window, gr.Downsampler, gr.Upsampler, gr.TimeRange) if err != nil { return newRes, err } diff --git a/pkg/expr/mathexp/exp.go b/pkg/expr/mathexp/exp.go index a748a0f9418..124d9712ba2 100644 --- a/pkg/expr/mathexp/exp.go +++ b/pkg/expr/mathexp/exp.go @@ -24,6 +24,7 @@ type State struct { // Could hold more properties that change behavior around: // - Unions (How many result A and many Result B in case A + B are joined) // - NaN/Null behavior + RefID string } // Vars holds the results of datasource queries or other expression commands. @@ -43,10 +44,11 @@ func New(expr string, funcs ...map[string]parse.Func) (*Expr, error) { } // Execute applies a parse expression to the context and executes it -func (e *Expr) Execute(vars Vars) (r Results, err error) { +func (e *Expr) Execute(refID string, vars Vars) (r Results, err error) { s := &State{ - Expr: e, - Vars: vars, + Expr: e, + Vars: vars, + RefID: refID, } return e.executeState(s) } @@ -78,7 +80,7 @@ func errRecover(errp *error, s *State) { func (e *State) walk(node parse.Node) (res Results, err error) { switch node := node.(type) { case *parse.ScalarNode: - res = NewScalarResults(&node.Float64) + res = NewScalarResults(e.RefID, &node.Float64) case *parse.VarNode: res = e.Vars[node.Name] case *parse.BinaryNode: @@ -103,19 +105,19 @@ func (e *State) walkUnary(node *parse.UnaryNode) (Results, error) { var newVal Value switch rt := val.(type) { case Scalar: - newVal = NewScalar(nil) + newVal = NewScalar(e.RefID, nil) f := rt.GetFloat64Value() if f != nil { newF, err := unaryOp(node.OpStr, *f) if err != nil { return newResults, err } - newVal = NewScalar(&newF) + newVal = NewScalar(e.RefID, &newF) } case Number: - newVal, err = unaryNumber(rt, node.OpStr) + newVal, err = e.unaryNumber(rt, node.OpStr) case Series: - newVal, err = unarySeries(rt, node.OpStr) + newVal, err = e.unarySeries(rt, node.OpStr) default: return newResults, fmt.Errorf("can not perform a unary operation on type %v", rt.Type()) } @@ -127,8 +129,8 @@ func (e *State) walkUnary(node *parse.UnaryNode) (Results, error) { return newResults, nil } -func unarySeries(s Series, op string) (Series, error) { - newSeries := NewSeries(s.GetName(), s.GetLabels(), s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, s.Len()) +func (e *State) unarySeries(s Series, op string) (Series, error) { + newSeries := NewSeries(e.RefID, s.GetLabels(), s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, s.Len()) for i := 0; i < s.Len(); i++ { t, f := s.GetPoint(i) if f == nil { @@ -148,8 +150,8 @@ func unarySeries(s Series, op string) (Series, error) { return newSeries, nil } -func unaryNumber(n Number, op string) (Number, error) { - newNumber := NewNumber(n.GetName(), n.GetLabels()) +func (e *State) unaryNumber(n Number, op string) (Number, error) { + newNumber := NewNumber(e.RefID, n.GetLabels()) f := n.GetFloat64Value() if f != nil { @@ -253,7 +255,6 @@ func (e *State) walkBinary(node *parse.BinaryNode) (Results, error) { } unions := union(ar, br) for _, uni := range unions { - name := uni.Labels.String() var value Value switch at := uni.A.(type) { case Scalar: @@ -263,7 +264,7 @@ func (e *State) walkBinary(node *parse.BinaryNode) (Results, error) { case Scalar: bFloat := bt.GetFloat64Value() if aFloat == nil || bFloat == nil { - value = NewScalar(nil) + value = NewScalar(e.RefID, nil) break } f := math.NaN() @@ -273,13 +274,13 @@ func (e *State) walkBinary(node *parse.BinaryNode) (Results, error) { return res, err } } - value = NewScalar(&f) + value = NewScalar(e.RefID, &f) // Scalar op Scalar case Number: - value, err = biScalarNumber(name, uni.Labels, node.OpStr, bt, aFloat, false) + value, err = e.biScalarNumber(uni.Labels, node.OpStr, bt, aFloat, false) // Scalar op Series case Series: - value, err = biSeriesNumber(name, uni.Labels, node.OpStr, bt, aFloat, false) + value, err = e.biSeriesNumber(uni.Labels, node.OpStr, bt, aFloat, false) default: return res, fmt.Errorf("not implemented: binary %v on %T and %T", node.OpStr, uni.A, uni.B) } @@ -288,14 +289,14 @@ func (e *State) walkBinary(node *parse.BinaryNode) (Results, error) { // Series Op Scalar case Scalar: bFloat := bt.GetFloat64Value() - value, err = biSeriesNumber(name, uni.Labels, node.OpStr, at, bFloat, true) + value, err = e.biSeriesNumber(uni.Labels, node.OpStr, at, bFloat, true) // case Series Op Number case Number: bFloat := bt.GetFloat64Value() - value, err = biSeriesNumber(name, uni.Labels, node.OpStr, at, bFloat, true) + value, err = e.biSeriesNumber(uni.Labels, node.OpStr, at, bFloat, true) // case Series op Series case Series: - value, err = biSeriesSeries(name, uni.Labels, node.OpStr, at, bt) + value, err = e.biSeriesSeries(uni.Labels, node.OpStr, at, bt) default: return res, fmt.Errorf("not implemented: binary %v on %T and %T", node.OpStr, uni.A, uni.B) } @@ -304,12 +305,12 @@ func (e *State) walkBinary(node *parse.BinaryNode) (Results, error) { switch bt := uni.B.(type) { case Scalar: bFloat := bt.GetFloat64Value() - value, err = biScalarNumber(name, uni.Labels, node.OpStr, at, bFloat, true) + value, err = e.biScalarNumber(uni.Labels, node.OpStr, at, bFloat, true) case Number: bFloat := bt.GetFloat64Value() - value, err = biScalarNumber(name, uni.Labels, node.OpStr, at, bFloat, true) + value, err = e.biScalarNumber(uni.Labels, node.OpStr, at, bFloat, true) case Series: - value, err = biSeriesNumber(name, uni.Labels, node.OpStr, bt, aFloat, false) + value, err = e.biSeriesNumber(uni.Labels, node.OpStr, bt, aFloat, false) default: return res, fmt.Errorf("not implemented: binary %v on %T and %T", node.OpStr, uni.A, uni.B) } @@ -409,8 +410,8 @@ func binaryOp(op string, a, b float64) (r float64, err error) { return r, nil } -func biScalarNumber(name string, labels data.Labels, op string, number Number, scalarVal *float64, numberFirst bool) (Number, error) { - newNumber := NewNumber(name, labels) +func (e *State) biScalarNumber(labels data.Labels, op string, number Number, scalarVal *float64, numberFirst bool) (Number, error) { + newNumber := NewNumber(e.RefID, labels) f := number.GetFloat64Value() if f == nil || scalarVal == nil { newNumber.SetValue(nil) @@ -430,8 +431,8 @@ func biScalarNumber(name string, labels data.Labels, op string, number Number, s return newNumber, nil } -func biSeriesNumber(name string, labels data.Labels, op string, s Series, scalarVal *float64, seriesFirst bool) (Series, error) { - newSeries := NewSeries(name, labels, s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, s.Len()) +func (e *State) biSeriesNumber(labels data.Labels, op string, s Series, scalarVal *float64, seriesFirst bool) (Series, error) { + newSeries := NewSeries(e.RefID, labels, s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, s.Len()) var err error for i := 0; i < s.Len(); i++ { nF := math.NaN() @@ -460,7 +461,7 @@ func biSeriesNumber(name string, labels data.Labels, op string, s Series, scalar // ... if would you like some series with your series and then get some series, or is that enough series? // biSeriesSeries performs a the binary operation for each value in the two series where the times // are equal. If there are datapoints in A or B that do not share a time, they will be dropped. -func biSeriesSeries(name string, labels data.Labels, op string, aSeries, bSeries Series) (Series, error) { +func (e *State) biSeriesSeries(labels data.Labels, op string, aSeries, bSeries Series) (Series, error) { bPoints := make(map[time.Time]*float64) for i := 0; i < bSeries.Len(); i++ { t, f := bSeries.GetPoint(i) @@ -469,7 +470,7 @@ func biSeriesSeries(name string, labels data.Labels, op string, aSeries, bSeries } } - newSeries := NewSeries(name, labels, aSeries.TimeIdx, aSeries.TimeIsNullable || bSeries.TimeIsNullable, aSeries.ValueIdx, aSeries.ValueIsNullabe || bSeries.ValueIsNullabe, 0) + newSeries := NewSeries(e.RefID, labels, aSeries.TimeIdx, aSeries.TimeIsNullable || bSeries.TimeIsNullable, aSeries.ValueIdx, aSeries.ValueIsNullabe || bSeries.ValueIsNullabe, 0) for aIdx := 0; aIdx < aSeries.Len(); aIdx++ { aTime, aF := aSeries.GetPoint(aIdx) bF, ok := bPoints[*aTime] @@ -505,7 +506,7 @@ func (e *State) walkFunc(node *parse.FuncNode) (Results, error) { case *parse.VarNode: v = e.Vars[t.Name] case *parse.ScalarNode: - v = NewScalarResults(&t.Float64) + v = NewScalarResults(e.RefID, &t.Float64) case *parse.FuncNode: v, err = e.walkFunc(t) case *parse.UnaryNode: diff --git a/pkg/expr/mathexp/exp_nan_null_val_test.go b/pkg/expr/mathexp/exp_nan_null_val_test.go index eda17748061..866125e3174 100644 --- a/pkg/expr/mathexp/exp_nan_null_val_test.go +++ b/pkg/expr/mathexp/exp_nan_null_val_test.go @@ -144,7 +144,7 @@ func TestNaN(t *testing.T) { e, err := New(tt.expr) tt.newErrIs(t, err) if e != nil { - res, err := e.Execute(tt.vars) + res, err := e.Execute("", tt.vars) tt.execErrIs(t, err) if diff := cmp.Diff(res, tt.results, options...); diff != "" { assert.FailNow(t, tt.name, diff) @@ -175,21 +175,21 @@ func TestNullValues(t *testing.T) { expr: "! null()", newErrIs: assert.NoError, execErrIs: assert.NoError, - results: NewScalarResults(nil), + results: NewScalarResults("", nil), }, { name: "scalar: binary null() + null(): is null", expr: "null() + null()", newErrIs: assert.NoError, execErrIs: assert.NoError, - results: NewScalarResults(nil), + results: NewScalarResults("", nil), }, { name: "scalar: binary 1 + null(): is null", expr: "1 + null()", newErrIs: assert.NoError, execErrIs: assert.NoError, - results: NewScalarResults(nil), + results: NewScalarResults("", nil), }, { name: "series: unary with a null value in it has a null value in result", @@ -406,7 +406,7 @@ func TestNullValues(t *testing.T) { e, err := New(tt.expr) tt.newErrIs(t, err) if e != nil { - res, err := e.Execute(tt.vars) + res, err := e.Execute("", tt.vars) tt.execErrIs(t, err) if diff := cmp.Diff(tt.results, res, options...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) diff --git a/pkg/expr/mathexp/exp_scalar_no_test.go b/pkg/expr/mathexp/exp_scalar_no_test.go index 9106e2d54bf..33b79e0ccb5 100644 --- a/pkg/expr/mathexp/exp_scalar_no_test.go +++ b/pkg/expr/mathexp/exp_scalar_no_test.go @@ -24,7 +24,7 @@ func TestScalarExpr(t *testing.T) { newErrIs: assert.NoError, execErrIs: assert.NoError, resultIs: assert.Equal, - Results: Results{[]Value{NewScalar(float64Pointer(1.0))}}, + Results: Results{[]Value{NewScalar("", float64Pointer(1.0))}}, }, { name: "unary: scalar", @@ -33,7 +33,7 @@ func TestScalarExpr(t *testing.T) { newErrIs: assert.NoError, execErrIs: assert.NoError, resultIs: assert.Equal, - Results: Results{[]Value{NewScalar(float64Pointer(0.0))}}, + Results: Results{[]Value{NewScalar("", float64Pointer(0.0))}}, }, { name: "binary: scalar Op scalar", @@ -42,7 +42,7 @@ func TestScalarExpr(t *testing.T) { newErrIs: assert.NoError, execErrIs: assert.NoError, resultIs: assert.Equal, - Results: Results{[]Value{NewScalar(float64Pointer(2.0))}}, + Results: Results{[]Value{NewScalar("", float64Pointer(2.0))}}, }, { name: "binary: scalar Op scalar - divide by zero", @@ -51,7 +51,7 @@ func TestScalarExpr(t *testing.T) { newErrIs: assert.NoError, execErrIs: assert.NoError, resultIs: assert.Equal, - Results: Results{[]Value{NewScalar(float64Pointer(math.Inf(1)))}}, + Results: Results{[]Value{NewScalar("", float64Pointer(math.Inf(1)))}}, }, { name: "binary: scalar Op number", @@ -78,7 +78,7 @@ func TestScalarExpr(t *testing.T) { e, err := New(tt.expr) tt.newErrIs(t, err) if e != nil { - res, err := e.Execute(tt.vars) + res, err := e.Execute("", tt.vars) tt.execErrIs(t, err) tt.resultIs(t, tt.Results, res) } @@ -129,7 +129,7 @@ func TestNumberExpr(t *testing.T) { e, err := New(tt.expr) tt.newErrIs(t, err) if e != nil { - res, err := e.Execute(tt.vars) + res, err := e.Execute("", tt.vars) tt.execErrIs(t, err) tt.resultIs(t, tt.results, res) } diff --git a/pkg/expr/mathexp/exp_series_test.go b/pkg/expr/mathexp/exp_series_test.go index 62996d140be..877f1a0d0cd 100644 --- a/pkg/expr/mathexp/exp_series_test.go +++ b/pkg/expr/mathexp/exp_series_test.go @@ -90,7 +90,7 @@ func TestSeriesExpr(t *testing.T) { execErrIs: assert.NoError, results: Results{ []Value{ - makeSeriesNullableTime("id=1", data.Labels{"id": "1"}, nullTimeTP{ + makeSeriesNullableTime("", data.Labels{"id": "1"}, nullTimeTP{ unixTimePointer(5, 0), float64Pointer(9), }, nullTimeTP{ unixTimePointer(10, 0), float64Pointer(8), @@ -106,7 +106,7 @@ func TestSeriesExpr(t *testing.T) { execErrIs: assert.NoError, results: Results{ []Value{ - makeSeriesNullableTime("id=1", data.Labels{"id": "1"}, nullTimeTP{ + makeSeriesNullableTime("", data.Labels{"id": "1"}, nullTimeTP{ unixTimePointer(5, 0), float64Pointer(9), }, nullTimeTP{ unixTimePointer(10, 0), float64Pointer(8), @@ -122,12 +122,12 @@ func TestSeriesExpr(t *testing.T) { execErrIs: assert.NoError, results: Results{ []Value{ - makeSeriesNullableTime("sensor=a, turbine=1", data.Labels{"sensor": "a", "turbine": "1"}, nullTimeTP{ + makeSeriesNullableTime("", data.Labels{"sensor": "a", "turbine": "1"}, nullTimeTP{ unixTimePointer(5, 0), float64Pointer(6 * .5), }, nullTimeTP{ unixTimePointer(10, 0), float64Pointer(8 * .2), }), - makeSeriesNullableTime("sensor=b, turbine=1", data.Labels{"sensor": "b", "turbine": "1"}, nullTimeTP{ + makeSeriesNullableTime("", data.Labels{"sensor": "b", "turbine": "1"}, nullTimeTP{ unixTimePointer(5, 0), float64Pointer(10 * .5), }, nullTimeTP{ unixTimePointer(10, 0), float64Pointer(16 * .2), @@ -178,7 +178,7 @@ func TestSeriesExpr(t *testing.T) { e, err := New(tt.expr) tt.newErrIs(t, err) if e != nil { - res, err := e.Execute(tt.vars) + res, err := e.Execute("", tt.vars) tt.execErrIs(t, err) if diff := cmp.Diff(tt.results, res, data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) @@ -372,7 +372,7 @@ func TestSeriesAlternateFormsExpr(t *testing.T) { e, err := New(tt.expr) tt.newErrIs(t, err) if e != nil { - res, err := e.Execute(tt.vars) + res, err := e.Execute("", tt.vars) tt.execErrIs(t, err) if diff := cmp.Diff(tt.results, res, data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) diff --git a/pkg/expr/mathexp/funcs.go b/pkg/expr/mathexp/funcs.go index 527fe8a22f2..e3ab2156fcc 100644 --- a/pkg/expr/mathexp/funcs.go +++ b/pkg/expr/mathexp/funcs.go @@ -35,7 +35,7 @@ var builtins = map[string]parse.Func{ func abs(e *State, varSet Results) (Results, error) { newRes := Results{} for _, res := range varSet.Values { - newVal, err := perFloat(res, math.Abs) + newVal, err := perFloat(e, res, math.Abs) if err != nil { return newRes, err } @@ -48,7 +48,7 @@ func abs(e *State, varSet Results) (Results, error) { func log(e *State, varSet Results) (Results, error) { newRes := Results{} for _, res := range varSet.Values { - newVal, err := perFloat(res, math.Log) + newVal, err := perFloat(e, res, math.Log) if err != nil { return newRes, err } @@ -60,25 +60,25 @@ func log(e *State, varSet Results) (Results, error) { // nan returns a scalar nan value func nan(e *State) Results { aNaN := math.NaN() - return NewScalarResults(&aNaN) + return NewScalarResults(e.RefID, &aNaN) } // inf returns a scalar positive infinity value func inf(e *State) Results { aInf := math.Inf(0) - return NewScalarResults(&aInf) + return NewScalarResults(e.RefID, &aInf) } // null returns a null scalar value func null(e *State) Results { - return NewScalarResults(nil) + return NewScalarResults(e.RefID, nil) } -func perFloat(val Value, floatF func(x float64) float64) (Value, error) { +func perFloat(e *State, val Value, floatF func(x float64) float64) (Value, error) { var newVal Value switch val.Type() { case parse.TypeNumberSet: - n := NewNumber(val.GetName(), val.GetLabels()) + n := NewNumber(e.RefID, val.GetLabels()) f := val.(Number).GetFloat64Value() nF := math.NaN() if f != nil { @@ -92,10 +92,10 @@ func perFloat(val Value, floatF func(x float64) float64) (Value, error) { if f != nil { nF = floatF(*f) } - newVal = NewScalar(&nF) + newVal = NewScalar(e.RefID, &nF) case parse.TypeSeriesSet: resSeries := val.(Series) - newSeries := NewSeries(resSeries.GetName(), resSeries.GetLabels(), resSeries.TimeIdx, resSeries.TimeIsNullable, resSeries.ValueIdx, resSeries.ValueIsNullabe, resSeries.Len()) + newSeries := NewSeries(e.RefID, resSeries.GetLabels(), resSeries.TimeIdx, resSeries.TimeIsNullable, resSeries.ValueIdx, resSeries.ValueIsNullabe, resSeries.Len()) for i := 0; i < resSeries.Len(); i++ { t, f := resSeries.GetPoint(i) nF := math.NaN() diff --git a/pkg/expr/mathexp/funcs_test.go b/pkg/expr/mathexp/funcs_test.go index 031b477c18d..87764c79481 100644 --- a/pkg/expr/mathexp/funcs_test.go +++ b/pkg/expr/mathexp/funcs_test.go @@ -38,7 +38,7 @@ func TestFunc(t *testing.T) { newErrIs: assert.NoError, execErrIs: assert.NoError, resultIs: assert.Equal, - results: Results{[]Value{NewScalar(float64Pointer(1.0))}}, + results: Results{[]Value{NewScalar("", float64Pointer(1.0))}}, }, { name: "abs on series", @@ -79,7 +79,7 @@ func TestFunc(t *testing.T) { e, err := New(tt.expr) tt.newErrIs(t, err) if e != nil { - res, err := e.Execute(tt.vars) + res, err := e.Execute("", tt.vars) tt.execErrIs(t, err) tt.resultIs(t, tt.results, res) } diff --git a/pkg/expr/mathexp/reduce.go b/pkg/expr/mathexp/reduce.go index 1c0d63118aa..34a5a862058 100644 --- a/pkg/expr/mathexp/reduce.go +++ b/pkg/expr/mathexp/reduce.go @@ -73,12 +73,12 @@ func Count(fv *data.Field) *float64 { } // Reduce turns the Series into a Number based on the given reduction function -func (s Series) Reduce(rFunc string) (Number, error) { +func (s Series) Reduce(refID, rFunc string) (Number, error) { var l data.Labels if s.GetLabels() != nil { l = s.GetLabels().Copy() } - number := NewNumber(fmt.Sprintf("%v_%v", rFunc, s.GetName()), l) + number := NewNumber(refID, l) var f *float64 fVec := s.Frame.Fields[1] switch rFunc { diff --git a/pkg/expr/mathexp/reduce_test.go b/pkg/expr/mathexp/reduce_test.go index c7252f75242..18d2f8e96fd 100644 --- a/pkg/expr/mathexp/reduce_test.go +++ b/pkg/expr/mathexp/reduce_test.go @@ -57,7 +57,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("sum_", nil, float64Pointer(3)), + makeNumber("", nil, float64Pointer(3)), }, }, }, @@ -70,7 +70,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("sum_", nil, NaN), + makeNumber("", nil, NaN), }, }, }, @@ -83,7 +83,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("sum_", nil, float64Pointer(0)), + makeNumber("", nil, float64Pointer(0)), }, }, }, @@ -96,7 +96,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("mean_", nil, NaN), + makeNumber("", nil, NaN), }, }, }, @@ -109,7 +109,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("mean_", nil, NaN), + makeNumber("", nil, NaN), }, }, }, @@ -122,7 +122,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("min_", nil, NaN), + makeNumber("", nil, NaN), }, }, }, @@ -135,7 +135,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("min_", nil, NaN), + makeNumber("", nil, NaN), }, }, }, @@ -148,7 +148,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("max_", nil, NaN), + makeNumber("", nil, NaN), }, }, }, @@ -161,7 +161,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("max_", nil, NaN), + makeNumber("", nil, NaN), }, }, }, @@ -174,7 +174,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("mean_", nil, float64Pointer(1.5)), + makeNumber("", nil, float64Pointer(1.5)), }, }, }, @@ -187,7 +187,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("count_", nil, float64Pointer(0)), + makeNumber("", nil, float64Pointer(0)), }, }, }, @@ -210,7 +210,7 @@ func TestSeriesReduce(t *testing.T) { resultsIs: require.Equal, results: Results{ []Value{ - makeNumber("mean_", data.Labels{"host": "a"}, float64Pointer(1.5)), + makeNumber("", data.Labels{"host": "a"}, float64Pointer(1.5)), }, }, }, @@ -221,7 +221,7 @@ func TestSeriesReduce(t *testing.T) { results := Results{} seriesSet := tt.vars[tt.varToReduce] for _, series := range seriesSet.Values { - ns, err := series.Value().(*Series).Reduce(tt.red) + ns, err := series.Value().(*Series).Reduce("", tt.red) tt.errIs(t, err) if err != nil { return diff --git a/pkg/expr/mathexp/resample.go b/pkg/expr/mathexp/resample.go index 45531dd389b..5f7d7213a03 100644 --- a/pkg/expr/mathexp/resample.go +++ b/pkg/expr/mathexp/resample.go @@ -9,12 +9,12 @@ import ( ) // Resample turns the Series into a Number based on the given reduction function -func (s Series) Resample(interval time.Duration, downsampler string, upsampler string, tr backend.TimeRange) (Series, error) { +func (s Series) Resample(refID string, interval time.Duration, downsampler string, upsampler string, tr backend.TimeRange) (Series, error) { newSeriesLength := int(float64(tr.To.Sub(tr.From).Nanoseconds()) / float64(interval.Nanoseconds())) if newSeriesLength <= 0 { return s, fmt.Errorf("the series cannot be sampled further; the time range is shorter than the interval") } - resampled := NewSeries(s.GetName(), s.GetLabels(), s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, newSeriesLength+1) + resampled := NewSeries(refID, s.GetLabels(), s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, newSeriesLength+1) bookmark := 0 var lastSeen *float64 idx := 0 diff --git a/pkg/expr/mathexp/resample_test.go b/pkg/expr/mathexp/resample_test.go index 8100031c04c..772f3e75c97 100644 --- a/pkg/expr/mathexp/resample_test.go +++ b/pkg/expr/mathexp/resample_test.go @@ -248,7 +248,7 @@ func TestResampleSeries(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - series, err := tt.seriesToResample.Resample(tt.interval, tt.downsampler, tt.upsampler, tt.timeRange) + series, err := tt.seriesToResample.Resample("", tt.interval, tt.downsampler, tt.upsampler, tt.timeRange) if tt.series.Frame == nil { require.Error(t, err) } else { diff --git a/pkg/expr/mathexp/type_series.go b/pkg/expr/mathexp/type_series.go index ac716a80556..6b258100fde 100644 --- a/pkg/expr/mathexp/type_series.go +++ b/pkg/expr/mathexp/type_series.go @@ -61,13 +61,13 @@ func SeriesFromFrame(frame *data.Frame) (s Series, err error) { } // NewSeries returns a dataframe of type Series. -func NewSeries(name string, labels data.Labels, timeIdx int, nullableTime bool, valueIdx int, nullableValue bool, size int) Series { +func NewSeries(refID string, labels data.Labels, timeIdx int, nullableTime bool, valueIdx int, nullableValue bool, size int) Series { fields := make([]*data.Field, 2) if nullableValue { - fields[valueIdx] = data.NewField(name, labels, make([]*float64, size)) + fields[valueIdx] = data.NewField(refID, labels, make([]*float64, size)) } else { - fields[valueIdx] = data.NewField(name, labels, make([]float64, size)) + fields[valueIdx] = data.NewField(refID, labels, make([]float64, size)) } if nullableTime { diff --git a/pkg/expr/mathexp/types.go b/pkg/expr/mathexp/types.go index 78b4a323ffc..867796eaa70 100644 --- a/pkg/expr/mathexp/types.go +++ b/pkg/expr/mathexp/types.go @@ -30,7 +30,6 @@ type Value interface { Value() interface{} GetLabels() data.Labels SetLabels(data.Labels) - GetName() string AsDataFrame() *data.Frame } @@ -49,23 +48,21 @@ func (s Scalar) GetLabels() data.Labels { return nil } func (s Scalar) SetLabels(ls data.Labels) {} -func (s Scalar) GetName() string { return s.Frame.Name } - // AsDataFrame returns the underlying *data.Frame. func (s Scalar) AsDataFrame() *data.Frame { return s.Frame } // NewScalar creates a Scalar holding value f. -func NewScalar(f *float64) Scalar { +func NewScalar(name string, f *float64) Scalar { frame := data.NewFrame("", - data.NewField("Scalar", nil, []*float64{f}), + data.NewField(name, nil, []*float64{f}), ) return Scalar{frame} } // NewScalarResults creates a Results holding a single Scalar -func NewScalarResults(f *float64) Results { +func NewScalarResults(name string, f *float64) Results { return Results{ - Values: []Value{NewScalar(f)}, + Values: []Value{NewScalar(name, f)}, } } @@ -87,8 +84,6 @@ func (n Number) GetLabels() data.Labels { return n.Frame.Fields[0].Labels } func (n Number) SetLabels(ls data.Labels) { n.Frame.Fields[0].Labels = ls } -func (n Number) GetName() string { return n.Frame.Name } - // AsDataFrame returns the underlying *data.Frame. func (n Number) AsDataFrame() *data.Frame { return n.Frame } diff --git a/pkg/expr/service_test.go b/pkg/expr/service_test.go index 85396ea146c..612f907e3f3 100644 --- a/pkg/expr/service_test.go +++ b/pkg/expr/service_test.go @@ -46,7 +46,7 @@ func TestService(t *testing.T) { bDF := data.NewFrame("", data.NewField("Time", nil, []*time.Time{utp(1)}), - data.NewField("", nil, []*float64{fp(4)})) + data.NewField("B", nil, []*float64{fp(4)})) bDF.RefID = "B" expect := &backend.QueryDataResponse{