Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
67372378
Unverified
Commit
67372378
authored
Dec 11, 2020
by
Kyle Brandt
Committed by
GitHub
Dec 11, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Expressions: Field names from refId (#29755)
so one can see which expression data came from when visualizing
parent
a515c544
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
100 additions
and
98 deletions
+100
-98
pkg/expr/commands.go
+15
-9
pkg/expr/mathexp/exp.go
+31
-30
pkg/expr/mathexp/exp_nan_null_val_test.go
+5
-5
pkg/expr/mathexp/exp_scalar_no_test.go
+6
-6
pkg/expr/mathexp/exp_series_test.go
+6
-6
pkg/expr/mathexp/funcs.go
+9
-9
pkg/expr/mathexp/funcs_test.go
+2
-2
pkg/expr/mathexp/reduce.go
+2
-2
pkg/expr/mathexp/reduce_test.go
+13
-13
pkg/expr/mathexp/resample.go
+2
-2
pkg/expr/mathexp/resample_test.go
+1
-1
pkg/expr/mathexp/type_series.go
+3
-3
pkg/expr/mathexp/types.go
+4
-9
pkg/expr/service_test.go
+1
-1
No files found.
pkg/expr/commands.go
View file @
67372378
...
...
@@ -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
(
re
fID
,
re
ducer
,
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
(
r
n
.
RefID
,
r
edFunc
,
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
(
r
efID
,
r
awWindow
,
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
}
...
...
pkg/expr/mathexp/exp.go
View file @
67372378
...
...
@@ -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
:
...
...
pkg/expr/mathexp/exp_nan_null_val_test.go
View file @
67372378
...
...
@@ -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
)
...
...
pkg/expr/mathexp/exp_scalar_no_test.go
View file @
67372378
...
...
@@ -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
)
}
...
...
pkg/expr/mathexp/exp_series_test.go
View file @
67372378
...
...
@@ -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
)
...
...
pkg/expr/mathexp/funcs.go
View file @
67372378
...
...
@@ -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
()
...
...
pkg/expr/mathexp/funcs_test.go
View file @
67372378
...
...
@@ -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
)
}
...
...
pkg/expr/mathexp/reduce.go
View file @
67372378
...
...
@@ -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
(
r
efID
,
r
Func
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
{
...
...
pkg/expr/mathexp/reduce_test.go
View file @
67372378
...
...
@@ -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
...
...
pkg/expr/mathexp/resample.go
View file @
67372378
...
...
@@ -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
...
...
pkg/expr/mathexp/resample_test.go
View file @
67372378
...
...
@@ -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
{
...
...
pkg/expr/mathexp/type_series.go
View file @
67372378
...
...
@@ -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
{
...
...
pkg/expr/mathexp/types.go
View file @
67372378
...
...
@@ -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
}
...
...
pkg/expr/service_test.go
View file @
67372378
...
...
@@ -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
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment