mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Expressions: Field names from refId (#29755)
so one can see which expression data came from when visualizing
This commit is contained in:
parent
a515c54404
commit
67372378ac
@ -21,11 +21,12 @@ type Command interface {
|
|||||||
type MathCommand struct {
|
type MathCommand struct {
|
||||||
RawExpression string
|
RawExpression string
|
||||||
Expression *mathexp.Expr
|
Expression *mathexp.Expr
|
||||||
|
refID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMathCommand creates a new MathCommand. It will return an error
|
// NewMathCommand creates a new MathCommand. It will return an error
|
||||||
// if there is an error parsing expr.
|
// 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)
|
parsedExpr, err := mathexp.New(expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -33,6 +34,7 @@ func NewMathCommand(expr string) (*MathCommand, error) {
|
|||||||
return &MathCommand{
|
return &MathCommand{
|
||||||
RawExpression: expr,
|
RawExpression: expr,
|
||||||
Expression: parsedExpr,
|
Expression: parsedExpr,
|
||||||
|
refID: refID,
|
||||||
}, nil
|
}, 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)
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid math command type in '%v': %v", rn.RefID, err)
|
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
|
// Execute runs the command and returns the results or an error if the command
|
||||||
// failed to execute.
|
// failed to execute.
|
||||||
func (gm *MathCommand) Execute(ctx context.Context, vars mathexp.Vars) (mathexp.Results, error) {
|
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.
|
// ReduceCommand is an expression command for reduction of a timeseries such as a min, mean, or max.
|
||||||
type ReduceCommand struct {
|
type ReduceCommand struct {
|
||||||
Reducer string
|
Reducer string
|
||||||
VarToReduce string
|
VarToReduce string
|
||||||
|
refID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReduceCommand creates a new ReduceCMD.
|
// NewReduceCommand creates a new ReduceCMD.
|
||||||
func NewReduceCommand(reducer, varToReduce string) *ReduceCommand {
|
func NewReduceCommand(refID, reducer, varToReduce string) *ReduceCommand {
|
||||||
// TODO: validate reducer here, before execution
|
// TODO: validate reducer here, before execution
|
||||||
return &ReduceCommand{
|
return &ReduceCommand{
|
||||||
Reducer: reducer,
|
Reducer: reducer,
|
||||||
VarToReduce: varToReduce,
|
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 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
|
// 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 {
|
if !ok {
|
||||||
return newRes, fmt.Errorf("can only reduce type series, got type %v", val.Type())
|
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 {
|
if err != nil {
|
||||||
return newRes, err
|
return newRes, err
|
||||||
}
|
}
|
||||||
@ -136,10 +140,11 @@ type ResampleCommand struct {
|
|||||||
Downsampler string
|
Downsampler string
|
||||||
Upsampler string
|
Upsampler string
|
||||||
TimeRange backend.TimeRange
|
TimeRange backend.TimeRange
|
||||||
|
refID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewResampleCommand creates a new ResampleCMD.
|
// 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
|
// TODO: validate reducer here, before execution
|
||||||
window, err := gtime.ParseDuration(rawWindow)
|
window, err := gtime.ParseDuration(rawWindow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -151,6 +156,7 @@ func NewResampleCommand(rawWindow, varToResample string, downsampler string, ups
|
|||||||
Downsampler: downsampler,
|
Downsampler: downsampler,
|
||||||
Upsampler: upsampler,
|
Upsampler: upsampler,
|
||||||
TimeRange: tr,
|
TimeRange: tr,
|
||||||
|
refID: refID,
|
||||||
}, nil
|
}, 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 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
|
// 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 {
|
if !ok {
|
||||||
return newRes, fmt.Errorf("can only resample type series, got type %v", val.Type())
|
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 {
|
if err != nil {
|
||||||
return newRes, err
|
return newRes, err
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ type State struct {
|
|||||||
// Could hold more properties that change behavior around:
|
// Could hold more properties that change behavior around:
|
||||||
// - Unions (How many result A and many Result B in case A + B are joined)
|
// - Unions (How many result A and many Result B in case A + B are joined)
|
||||||
// - NaN/Null behavior
|
// - NaN/Null behavior
|
||||||
|
RefID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vars holds the results of datasource queries or other expression commands.
|
// 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
|
// 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{
|
s := &State{
|
||||||
Expr: e,
|
Expr: e,
|
||||||
Vars: vars,
|
Vars: vars,
|
||||||
|
RefID: refID,
|
||||||
}
|
}
|
||||||
return e.executeState(s)
|
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) {
|
func (e *State) walk(node parse.Node) (res Results, err error) {
|
||||||
switch node := node.(type) {
|
switch node := node.(type) {
|
||||||
case *parse.ScalarNode:
|
case *parse.ScalarNode:
|
||||||
res = NewScalarResults(&node.Float64)
|
res = NewScalarResults(e.RefID, &node.Float64)
|
||||||
case *parse.VarNode:
|
case *parse.VarNode:
|
||||||
res = e.Vars[node.Name]
|
res = e.Vars[node.Name]
|
||||||
case *parse.BinaryNode:
|
case *parse.BinaryNode:
|
||||||
@ -103,19 +105,19 @@ func (e *State) walkUnary(node *parse.UnaryNode) (Results, error) {
|
|||||||
var newVal Value
|
var newVal Value
|
||||||
switch rt := val.(type) {
|
switch rt := val.(type) {
|
||||||
case Scalar:
|
case Scalar:
|
||||||
newVal = NewScalar(nil)
|
newVal = NewScalar(e.RefID, nil)
|
||||||
f := rt.GetFloat64Value()
|
f := rt.GetFloat64Value()
|
||||||
if f != nil {
|
if f != nil {
|
||||||
newF, err := unaryOp(node.OpStr, *f)
|
newF, err := unaryOp(node.OpStr, *f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newResults, err
|
return newResults, err
|
||||||
}
|
}
|
||||||
newVal = NewScalar(&newF)
|
newVal = NewScalar(e.RefID, &newF)
|
||||||
}
|
}
|
||||||
case Number:
|
case Number:
|
||||||
newVal, err = unaryNumber(rt, node.OpStr)
|
newVal, err = e.unaryNumber(rt, node.OpStr)
|
||||||
case Series:
|
case Series:
|
||||||
newVal, err = unarySeries(rt, node.OpStr)
|
newVal, err = e.unarySeries(rt, node.OpStr)
|
||||||
default:
|
default:
|
||||||
return newResults, fmt.Errorf("can not perform a unary operation on type %v", rt.Type())
|
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
|
return newResults, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unarySeries(s Series, op string) (Series, error) {
|
func (e *State) unarySeries(s Series, op string) (Series, error) {
|
||||||
newSeries := NewSeries(s.GetName(), s.GetLabels(), s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, s.Len())
|
newSeries := NewSeries(e.RefID, s.GetLabels(), s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, s.Len())
|
||||||
for i := 0; i < s.Len(); i++ {
|
for i := 0; i < s.Len(); i++ {
|
||||||
t, f := s.GetPoint(i)
|
t, f := s.GetPoint(i)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
@ -148,8 +150,8 @@ func unarySeries(s Series, op string) (Series, error) {
|
|||||||
return newSeries, nil
|
return newSeries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unaryNumber(n Number, op string) (Number, error) {
|
func (e *State) unaryNumber(n Number, op string) (Number, error) {
|
||||||
newNumber := NewNumber(n.GetName(), n.GetLabels())
|
newNumber := NewNumber(e.RefID, n.GetLabels())
|
||||||
|
|
||||||
f := n.GetFloat64Value()
|
f := n.GetFloat64Value()
|
||||||
if f != nil {
|
if f != nil {
|
||||||
@ -253,7 +255,6 @@ func (e *State) walkBinary(node *parse.BinaryNode) (Results, error) {
|
|||||||
}
|
}
|
||||||
unions := union(ar, br)
|
unions := union(ar, br)
|
||||||
for _, uni := range unions {
|
for _, uni := range unions {
|
||||||
name := uni.Labels.String()
|
|
||||||
var value Value
|
var value Value
|
||||||
switch at := uni.A.(type) {
|
switch at := uni.A.(type) {
|
||||||
case Scalar:
|
case Scalar:
|
||||||
@ -263,7 +264,7 @@ func (e *State) walkBinary(node *parse.BinaryNode) (Results, error) {
|
|||||||
case Scalar:
|
case Scalar:
|
||||||
bFloat := bt.GetFloat64Value()
|
bFloat := bt.GetFloat64Value()
|
||||||
if aFloat == nil || bFloat == nil {
|
if aFloat == nil || bFloat == nil {
|
||||||
value = NewScalar(nil)
|
value = NewScalar(e.RefID, nil)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
f := math.NaN()
|
f := math.NaN()
|
||||||
@ -273,13 +274,13 @@ func (e *State) walkBinary(node *parse.BinaryNode) (Results, error) {
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value = NewScalar(&f)
|
value = NewScalar(e.RefID, &f)
|
||||||
// Scalar op Scalar
|
// Scalar op Scalar
|
||||||
case Number:
|
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
|
// Scalar op Series
|
||||||
case 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:
|
default:
|
||||||
return res, fmt.Errorf("not implemented: binary %v on %T and %T", node.OpStr, uni.A, uni.B)
|
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
|
// Series Op Scalar
|
||||||
case Scalar:
|
case Scalar:
|
||||||
bFloat := bt.GetFloat64Value()
|
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 Series Op Number
|
||||||
case Number:
|
case Number:
|
||||||
bFloat := bt.GetFloat64Value()
|
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 op Series
|
||||||
case Series:
|
case Series:
|
||||||
value, err = biSeriesSeries(name, uni.Labels, node.OpStr, at, bt)
|
value, err = e.biSeriesSeries(uni.Labels, node.OpStr, at, bt)
|
||||||
default:
|
default:
|
||||||
return res, fmt.Errorf("not implemented: binary %v on %T and %T", node.OpStr, uni.A, uni.B)
|
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) {
|
switch bt := uni.B.(type) {
|
||||||
case Scalar:
|
case Scalar:
|
||||||
bFloat := bt.GetFloat64Value()
|
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:
|
case Number:
|
||||||
bFloat := bt.GetFloat64Value()
|
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:
|
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:
|
default:
|
||||||
return res, fmt.Errorf("not implemented: binary %v on %T and %T", node.OpStr, uni.A, uni.B)
|
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
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func biScalarNumber(name string, labels data.Labels, op string, number Number, scalarVal *float64, numberFirst bool) (Number, error) {
|
func (e *State) biScalarNumber(labels data.Labels, op string, number Number, scalarVal *float64, numberFirst bool) (Number, error) {
|
||||||
newNumber := NewNumber(name, labels)
|
newNumber := NewNumber(e.RefID, labels)
|
||||||
f := number.GetFloat64Value()
|
f := number.GetFloat64Value()
|
||||||
if f == nil || scalarVal == nil {
|
if f == nil || scalarVal == nil {
|
||||||
newNumber.SetValue(nil)
|
newNumber.SetValue(nil)
|
||||||
@ -430,8 +431,8 @@ func biScalarNumber(name string, labels data.Labels, op string, number Number, s
|
|||||||
return newNumber, nil
|
return newNumber, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func biSeriesNumber(name string, labels data.Labels, op string, s Series, scalarVal *float64, seriesFirst bool) (Series, error) {
|
func (e *State) biSeriesNumber(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())
|
newSeries := NewSeries(e.RefID, labels, s.TimeIdx, s.TimeIsNullable, s.ValueIdx, s.ValueIsNullabe, s.Len())
|
||||||
var err error
|
var err error
|
||||||
for i := 0; i < s.Len(); i++ {
|
for i := 0; i < s.Len(); i++ {
|
||||||
nF := math.NaN()
|
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?
|
// ... 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
|
// 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.
|
// 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)
|
bPoints := make(map[time.Time]*float64)
|
||||||
for i := 0; i < bSeries.Len(); i++ {
|
for i := 0; i < bSeries.Len(); i++ {
|
||||||
t, f := bSeries.GetPoint(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++ {
|
for aIdx := 0; aIdx < aSeries.Len(); aIdx++ {
|
||||||
aTime, aF := aSeries.GetPoint(aIdx)
|
aTime, aF := aSeries.GetPoint(aIdx)
|
||||||
bF, ok := bPoints[*aTime]
|
bF, ok := bPoints[*aTime]
|
||||||
@ -505,7 +506,7 @@ func (e *State) walkFunc(node *parse.FuncNode) (Results, error) {
|
|||||||
case *parse.VarNode:
|
case *parse.VarNode:
|
||||||
v = e.Vars[t.Name]
|
v = e.Vars[t.Name]
|
||||||
case *parse.ScalarNode:
|
case *parse.ScalarNode:
|
||||||
v = NewScalarResults(&t.Float64)
|
v = NewScalarResults(e.RefID, &t.Float64)
|
||||||
case *parse.FuncNode:
|
case *parse.FuncNode:
|
||||||
v, err = e.walkFunc(t)
|
v, err = e.walkFunc(t)
|
||||||
case *parse.UnaryNode:
|
case *parse.UnaryNode:
|
||||||
|
@ -144,7 +144,7 @@ func TestNaN(t *testing.T) {
|
|||||||
e, err := New(tt.expr)
|
e, err := New(tt.expr)
|
||||||
tt.newErrIs(t, err)
|
tt.newErrIs(t, err)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
res, err := e.Execute(tt.vars)
|
res, err := e.Execute("", tt.vars)
|
||||||
tt.execErrIs(t, err)
|
tt.execErrIs(t, err)
|
||||||
if diff := cmp.Diff(res, tt.results, options...); diff != "" {
|
if diff := cmp.Diff(res, tt.results, options...); diff != "" {
|
||||||
assert.FailNow(t, tt.name, diff)
|
assert.FailNow(t, tt.name, diff)
|
||||||
@ -175,21 +175,21 @@ func TestNullValues(t *testing.T) {
|
|||||||
expr: "! null()",
|
expr: "! null()",
|
||||||
newErrIs: assert.NoError,
|
newErrIs: assert.NoError,
|
||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
results: NewScalarResults(nil),
|
results: NewScalarResults("", nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scalar: binary null() + null(): is null",
|
name: "scalar: binary null() + null(): is null",
|
||||||
expr: "null() + null()",
|
expr: "null() + null()",
|
||||||
newErrIs: assert.NoError,
|
newErrIs: assert.NoError,
|
||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
results: NewScalarResults(nil),
|
results: NewScalarResults("", nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scalar: binary 1 + null(): is null",
|
name: "scalar: binary 1 + null(): is null",
|
||||||
expr: "1 + null()",
|
expr: "1 + null()",
|
||||||
newErrIs: assert.NoError,
|
newErrIs: assert.NoError,
|
||||||
execErrIs: 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",
|
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)
|
e, err := New(tt.expr)
|
||||||
tt.newErrIs(t, err)
|
tt.newErrIs(t, err)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
res, err := e.Execute(tt.vars)
|
res, err := e.Execute("", tt.vars)
|
||||||
tt.execErrIs(t, err)
|
tt.execErrIs(t, err)
|
||||||
if diff := cmp.Diff(tt.results, res, options...); diff != "" {
|
if diff := cmp.Diff(tt.results, res, options...); diff != "" {
|
||||||
t.Errorf("Result mismatch (-want +got):\n%s", diff)
|
t.Errorf("Result mismatch (-want +got):\n%s", diff)
|
||||||
|
@ -24,7 +24,7 @@ func TestScalarExpr(t *testing.T) {
|
|||||||
newErrIs: assert.NoError,
|
newErrIs: assert.NoError,
|
||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
resultIs: assert.Equal,
|
resultIs: assert.Equal,
|
||||||
Results: Results{[]Value{NewScalar(float64Pointer(1.0))}},
|
Results: Results{[]Value{NewScalar("", float64Pointer(1.0))}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unary: scalar",
|
name: "unary: scalar",
|
||||||
@ -33,7 +33,7 @@ func TestScalarExpr(t *testing.T) {
|
|||||||
newErrIs: assert.NoError,
|
newErrIs: assert.NoError,
|
||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
resultIs: assert.Equal,
|
resultIs: assert.Equal,
|
||||||
Results: Results{[]Value{NewScalar(float64Pointer(0.0))}},
|
Results: Results{[]Value{NewScalar("", float64Pointer(0.0))}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "binary: scalar Op scalar",
|
name: "binary: scalar Op scalar",
|
||||||
@ -42,7 +42,7 @@ func TestScalarExpr(t *testing.T) {
|
|||||||
newErrIs: assert.NoError,
|
newErrIs: assert.NoError,
|
||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
resultIs: assert.Equal,
|
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",
|
name: "binary: scalar Op scalar - divide by zero",
|
||||||
@ -51,7 +51,7 @@ func TestScalarExpr(t *testing.T) {
|
|||||||
newErrIs: assert.NoError,
|
newErrIs: assert.NoError,
|
||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
resultIs: assert.Equal,
|
resultIs: assert.Equal,
|
||||||
Results: Results{[]Value{NewScalar(float64Pointer(math.Inf(1)))}},
|
Results: Results{[]Value{NewScalar("", float64Pointer(math.Inf(1)))}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "binary: scalar Op number",
|
name: "binary: scalar Op number",
|
||||||
@ -78,7 +78,7 @@ func TestScalarExpr(t *testing.T) {
|
|||||||
e, err := New(tt.expr)
|
e, err := New(tt.expr)
|
||||||
tt.newErrIs(t, err)
|
tt.newErrIs(t, err)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
res, err := e.Execute(tt.vars)
|
res, err := e.Execute("", tt.vars)
|
||||||
tt.execErrIs(t, err)
|
tt.execErrIs(t, err)
|
||||||
tt.resultIs(t, tt.Results, res)
|
tt.resultIs(t, tt.Results, res)
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ func TestNumberExpr(t *testing.T) {
|
|||||||
e, err := New(tt.expr)
|
e, err := New(tt.expr)
|
||||||
tt.newErrIs(t, err)
|
tt.newErrIs(t, err)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
res, err := e.Execute(tt.vars)
|
res, err := e.Execute("", tt.vars)
|
||||||
tt.execErrIs(t, err)
|
tt.execErrIs(t, err)
|
||||||
tt.resultIs(t, tt.results, res)
|
tt.resultIs(t, tt.results, res)
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ func TestSeriesExpr(t *testing.T) {
|
|||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeSeriesNullableTime("id=1", data.Labels{"id": "1"}, nullTimeTP{
|
makeSeriesNullableTime("", data.Labels{"id": "1"}, nullTimeTP{
|
||||||
unixTimePointer(5, 0), float64Pointer(9),
|
unixTimePointer(5, 0), float64Pointer(9),
|
||||||
}, nullTimeTP{
|
}, nullTimeTP{
|
||||||
unixTimePointer(10, 0), float64Pointer(8),
|
unixTimePointer(10, 0), float64Pointer(8),
|
||||||
@ -106,7 +106,7 @@ func TestSeriesExpr(t *testing.T) {
|
|||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeSeriesNullableTime("id=1", data.Labels{"id": "1"}, nullTimeTP{
|
makeSeriesNullableTime("", data.Labels{"id": "1"}, nullTimeTP{
|
||||||
unixTimePointer(5, 0), float64Pointer(9),
|
unixTimePointer(5, 0), float64Pointer(9),
|
||||||
}, nullTimeTP{
|
}, nullTimeTP{
|
||||||
unixTimePointer(10, 0), float64Pointer(8),
|
unixTimePointer(10, 0), float64Pointer(8),
|
||||||
@ -122,12 +122,12 @@ func TestSeriesExpr(t *testing.T) {
|
|||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]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),
|
unixTimePointer(5, 0), float64Pointer(6 * .5),
|
||||||
}, nullTimeTP{
|
}, nullTimeTP{
|
||||||
unixTimePointer(10, 0), float64Pointer(8 * .2),
|
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),
|
unixTimePointer(5, 0), float64Pointer(10 * .5),
|
||||||
}, nullTimeTP{
|
}, nullTimeTP{
|
||||||
unixTimePointer(10, 0), float64Pointer(16 * .2),
|
unixTimePointer(10, 0), float64Pointer(16 * .2),
|
||||||
@ -178,7 +178,7 @@ func TestSeriesExpr(t *testing.T) {
|
|||||||
e, err := New(tt.expr)
|
e, err := New(tt.expr)
|
||||||
tt.newErrIs(t, err)
|
tt.newErrIs(t, err)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
res, err := e.Execute(tt.vars)
|
res, err := e.Execute("", tt.vars)
|
||||||
tt.execErrIs(t, err)
|
tt.execErrIs(t, err)
|
||||||
if diff := cmp.Diff(tt.results, res, data.FrameTestCompareOptions()...); diff != "" {
|
if diff := cmp.Diff(tt.results, res, data.FrameTestCompareOptions()...); diff != "" {
|
||||||
t.Errorf("Result mismatch (-want +got):\n%s", diff)
|
t.Errorf("Result mismatch (-want +got):\n%s", diff)
|
||||||
@ -372,7 +372,7 @@ func TestSeriesAlternateFormsExpr(t *testing.T) {
|
|||||||
e, err := New(tt.expr)
|
e, err := New(tt.expr)
|
||||||
tt.newErrIs(t, err)
|
tt.newErrIs(t, err)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
res, err := e.Execute(tt.vars)
|
res, err := e.Execute("", tt.vars)
|
||||||
tt.execErrIs(t, err)
|
tt.execErrIs(t, err)
|
||||||
if diff := cmp.Diff(tt.results, res, data.FrameTestCompareOptions()...); diff != "" {
|
if diff := cmp.Diff(tt.results, res, data.FrameTestCompareOptions()...); diff != "" {
|
||||||
t.Errorf("Result mismatch (-want +got):\n%s", diff)
|
t.Errorf("Result mismatch (-want +got):\n%s", diff)
|
||||||
|
@ -35,7 +35,7 @@ var builtins = map[string]parse.Func{
|
|||||||
func abs(e *State, varSet Results) (Results, error) {
|
func abs(e *State, varSet Results) (Results, error) {
|
||||||
newRes := Results{}
|
newRes := Results{}
|
||||||
for _, res := range varSet.Values {
|
for _, res := range varSet.Values {
|
||||||
newVal, err := perFloat(res, math.Abs)
|
newVal, err := perFloat(e, res, math.Abs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newRes, err
|
return newRes, err
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ func abs(e *State, varSet Results) (Results, error) {
|
|||||||
func log(e *State, varSet Results) (Results, error) {
|
func log(e *State, varSet Results) (Results, error) {
|
||||||
newRes := Results{}
|
newRes := Results{}
|
||||||
for _, res := range varSet.Values {
|
for _, res := range varSet.Values {
|
||||||
newVal, err := perFloat(res, math.Log)
|
newVal, err := perFloat(e, res, math.Log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newRes, err
|
return newRes, err
|
||||||
}
|
}
|
||||||
@ -60,25 +60,25 @@ func log(e *State, varSet Results) (Results, error) {
|
|||||||
// nan returns a scalar nan value
|
// nan returns a scalar nan value
|
||||||
func nan(e *State) Results {
|
func nan(e *State) Results {
|
||||||
aNaN := math.NaN()
|
aNaN := math.NaN()
|
||||||
return NewScalarResults(&aNaN)
|
return NewScalarResults(e.RefID, &aNaN)
|
||||||
}
|
}
|
||||||
|
|
||||||
// inf returns a scalar positive infinity value
|
// inf returns a scalar positive infinity value
|
||||||
func inf(e *State) Results {
|
func inf(e *State) Results {
|
||||||
aInf := math.Inf(0)
|
aInf := math.Inf(0)
|
||||||
return NewScalarResults(&aInf)
|
return NewScalarResults(e.RefID, &aInf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// null returns a null scalar value
|
// null returns a null scalar value
|
||||||
func null(e *State) Results {
|
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
|
var newVal Value
|
||||||
switch val.Type() {
|
switch val.Type() {
|
||||||
case parse.TypeNumberSet:
|
case parse.TypeNumberSet:
|
||||||
n := NewNumber(val.GetName(), val.GetLabels())
|
n := NewNumber(e.RefID, val.GetLabels())
|
||||||
f := val.(Number).GetFloat64Value()
|
f := val.(Number).GetFloat64Value()
|
||||||
nF := math.NaN()
|
nF := math.NaN()
|
||||||
if f != nil {
|
if f != nil {
|
||||||
@ -92,10 +92,10 @@ func perFloat(val Value, floatF func(x float64) float64) (Value, error) {
|
|||||||
if f != nil {
|
if f != nil {
|
||||||
nF = floatF(*f)
|
nF = floatF(*f)
|
||||||
}
|
}
|
||||||
newVal = NewScalar(&nF)
|
newVal = NewScalar(e.RefID, &nF)
|
||||||
case parse.TypeSeriesSet:
|
case parse.TypeSeriesSet:
|
||||||
resSeries := val.(Series)
|
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++ {
|
for i := 0; i < resSeries.Len(); i++ {
|
||||||
t, f := resSeries.GetPoint(i)
|
t, f := resSeries.GetPoint(i)
|
||||||
nF := math.NaN()
|
nF := math.NaN()
|
||||||
|
@ -38,7 +38,7 @@ func TestFunc(t *testing.T) {
|
|||||||
newErrIs: assert.NoError,
|
newErrIs: assert.NoError,
|
||||||
execErrIs: assert.NoError,
|
execErrIs: assert.NoError,
|
||||||
resultIs: assert.Equal,
|
resultIs: assert.Equal,
|
||||||
results: Results{[]Value{NewScalar(float64Pointer(1.0))}},
|
results: Results{[]Value{NewScalar("", float64Pointer(1.0))}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "abs on series",
|
name: "abs on series",
|
||||||
@ -79,7 +79,7 @@ func TestFunc(t *testing.T) {
|
|||||||
e, err := New(tt.expr)
|
e, err := New(tt.expr)
|
||||||
tt.newErrIs(t, err)
|
tt.newErrIs(t, err)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
res, err := e.Execute(tt.vars)
|
res, err := e.Execute("", tt.vars)
|
||||||
tt.execErrIs(t, err)
|
tt.execErrIs(t, err)
|
||||||
tt.resultIs(t, tt.results, res)
|
tt.resultIs(t, tt.results, res)
|
||||||
}
|
}
|
||||||
|
@ -73,12 +73,12 @@ func Count(fv *data.Field) *float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reduce turns the Series into a Number based on the given reduction function
|
// 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
|
var l data.Labels
|
||||||
if s.GetLabels() != nil {
|
if s.GetLabels() != nil {
|
||||||
l = s.GetLabels().Copy()
|
l = s.GetLabels().Copy()
|
||||||
}
|
}
|
||||||
number := NewNumber(fmt.Sprintf("%v_%v", rFunc, s.GetName()), l)
|
number := NewNumber(refID, l)
|
||||||
var f *float64
|
var f *float64
|
||||||
fVec := s.Frame.Fields[1]
|
fVec := s.Frame.Fields[1]
|
||||||
switch rFunc {
|
switch rFunc {
|
||||||
|
@ -57,7 +57,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("sum_", nil, float64Pointer(3)),
|
makeNumber("", nil, float64Pointer(3)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -70,7 +70,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("sum_", nil, NaN),
|
makeNumber("", nil, NaN),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -83,7 +83,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("sum_", nil, float64Pointer(0)),
|
makeNumber("", nil, float64Pointer(0)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -96,7 +96,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("mean_", nil, NaN),
|
makeNumber("", nil, NaN),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -109,7 +109,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("mean_", nil, NaN),
|
makeNumber("", nil, NaN),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -122,7 +122,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("min_", nil, NaN),
|
makeNumber("", nil, NaN),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -135,7 +135,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("min_", nil, NaN),
|
makeNumber("", nil, NaN),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -148,7 +148,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("max_", nil, NaN),
|
makeNumber("", nil, NaN),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -161,7 +161,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("max_", nil, NaN),
|
makeNumber("", nil, NaN),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -174,7 +174,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("mean_", nil, float64Pointer(1.5)),
|
makeNumber("", nil, float64Pointer(1.5)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -187,7 +187,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]Value{
|
||||||
makeNumber("count_", nil, float64Pointer(0)),
|
makeNumber("", nil, float64Pointer(0)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -210,7 +210,7 @@ func TestSeriesReduce(t *testing.T) {
|
|||||||
resultsIs: require.Equal,
|
resultsIs: require.Equal,
|
||||||
results: Results{
|
results: Results{
|
||||||
[]Value{
|
[]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{}
|
results := Results{}
|
||||||
seriesSet := tt.vars[tt.varToReduce]
|
seriesSet := tt.vars[tt.varToReduce]
|
||||||
for _, series := range seriesSet.Values {
|
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)
|
tt.errIs(t, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -9,12 +9,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Resample turns the Series into a Number based on the given reduction function
|
// 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()))
|
newSeriesLength := int(float64(tr.To.Sub(tr.From).Nanoseconds()) / float64(interval.Nanoseconds()))
|
||||||
if newSeriesLength <= 0 {
|
if newSeriesLength <= 0 {
|
||||||
return s, fmt.Errorf("the series cannot be sampled further; the time range is shorter than the interval")
|
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
|
bookmark := 0
|
||||||
var lastSeen *float64
|
var lastSeen *float64
|
||||||
idx := 0
|
idx := 0
|
||||||
|
@ -248,7 +248,7 @@ func TestResampleSeries(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
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 {
|
if tt.series.Frame == nil {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,13 +61,13 @@ func SeriesFromFrame(frame *data.Frame) (s Series, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewSeries returns a dataframe of type Series.
|
// 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)
|
fields := make([]*data.Field, 2)
|
||||||
|
|
||||||
if nullableValue {
|
if nullableValue {
|
||||||
fields[valueIdx] = data.NewField(name, labels, make([]*float64, size))
|
fields[valueIdx] = data.NewField(refID, labels, make([]*float64, size))
|
||||||
} else {
|
} else {
|
||||||
fields[valueIdx] = data.NewField(name, labels, make([]float64, size))
|
fields[valueIdx] = data.NewField(refID, labels, make([]float64, size))
|
||||||
}
|
}
|
||||||
|
|
||||||
if nullableTime {
|
if nullableTime {
|
||||||
|
@ -30,7 +30,6 @@ type Value interface {
|
|||||||
Value() interface{}
|
Value() interface{}
|
||||||
GetLabels() data.Labels
|
GetLabels() data.Labels
|
||||||
SetLabels(data.Labels)
|
SetLabels(data.Labels)
|
||||||
GetName() string
|
|
||||||
AsDataFrame() *data.Frame
|
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) SetLabels(ls data.Labels) {}
|
||||||
|
|
||||||
func (s Scalar) GetName() string { return s.Frame.Name }
|
|
||||||
|
|
||||||
// AsDataFrame returns the underlying *data.Frame.
|
// AsDataFrame returns the underlying *data.Frame.
|
||||||
func (s Scalar) AsDataFrame() *data.Frame { return s.Frame }
|
func (s Scalar) AsDataFrame() *data.Frame { return s.Frame }
|
||||||
|
|
||||||
// NewScalar creates a Scalar holding value f.
|
// NewScalar creates a Scalar holding value f.
|
||||||
func NewScalar(f *float64) Scalar {
|
func NewScalar(name string, f *float64) Scalar {
|
||||||
frame := data.NewFrame("",
|
frame := data.NewFrame("",
|
||||||
data.NewField("Scalar", nil, []*float64{f}),
|
data.NewField(name, nil, []*float64{f}),
|
||||||
)
|
)
|
||||||
return Scalar{frame}
|
return Scalar{frame}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewScalarResults creates a Results holding a single Scalar
|
// NewScalarResults creates a Results holding a single Scalar
|
||||||
func NewScalarResults(f *float64) Results {
|
func NewScalarResults(name string, f *float64) Results {
|
||||||
return 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) 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.
|
// AsDataFrame returns the underlying *data.Frame.
|
||||||
func (n Number) AsDataFrame() *data.Frame { return n.Frame }
|
func (n Number) AsDataFrame() *data.Frame { return n.Frame }
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func TestService(t *testing.T) {
|
|||||||
|
|
||||||
bDF := data.NewFrame("",
|
bDF := data.NewFrame("",
|
||||||
data.NewField("Time", nil, []*time.Time{utp(1)}),
|
data.NewField("Time", nil, []*time.Time{utp(1)}),
|
||||||
data.NewField("", nil, []*float64{fp(4)}))
|
data.NewField("B", nil, []*float64{fp(4)}))
|
||||||
bDF.RefID = "B"
|
bDF.RefID = "B"
|
||||||
|
|
||||||
expect := &backend.QueryDataResponse{
|
expect := &backend.QueryDataResponse{
|
||||||
|
Loading…
Reference in New Issue
Block a user