-
Notifications
You must be signed in to change notification settings - Fork 455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[query] Add support for unary expressions #1647
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1647 +/- ##
========================================
- Coverage 72.3% 72.1% -0.2%
========================================
Files 962 961 -1
Lines 80157 80051 -106
========================================
- Hits 57967 57783 -184
- Misses 18398 18497 +99
+ Partials 3792 3771 -21
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #1647 +/- ##
========================================
+ Coverage 65.3% 71.9% +6.6%
========================================
Files 958 964 +6
Lines 80131 80725 +594
========================================
+ Hits 52369 58092 +5723
+ Misses 24080 18827 -5253
- Partials 3682 3806 +124
Continue to review full report at Codecov.
|
src/query/block/lazy.go
Outdated
stepVals = c.Values() | ||
) | ||
|
||
vals := make([]float64, len(stepVals)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could you use the make([].., 0, ..)
formulation and append instead of directly accessing by idx.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it more efficient to allocate the length up front (instead of capacity) and index in? Or is this a better safe than sorry situation and avoid a potential panic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can get both by doing the other version.
i.e. when using the version with append (below), it's not expanding the slice unless the initial alloc wasn't large enough. so you still get the benefit of the up front alloc but also the safety of not panic'ing.
slice := make([]type, 0, len)
for _, v := range otherThing {
slice = append(slice, v)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay, yeah that makes sense.
src/query/block/lazy.go
Outdated
var ( | ||
c = it.it.Current() | ||
vt = it.opts.ValueTransform() | ||
vals = make([]float64, len(c.values)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too
src/query/block/lazy.go
Outdated
var ( | ||
c = it.it.Current() | ||
stepDPs = c.Values() | ||
dpList = make([]ts.Datapoints, len(stepDPs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here and on line 245 too
src/query/parser/promql/types.go
Outdated
@@ -293,6 +293,18 @@ func getBinaryOpType(opType promql.ItemType) string { | |||
} | |||
} | |||
|
|||
// GetUnaryOpType returns the M3 unary op type based on the Prom op type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; full stops at end of comments
src/query/parser/promql/parse.go
Outdated
|
||
unaryType, ok := GetUnaryOpType(n.Op) | ||
if !ok { | ||
return fmt.Errorf("only + and - operators allowed for unary expressions, received: %s", n.Op.String()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; instead, have GetUnaryOpType return a (unaryType, error) and just return this error there
src/query/parser/promql/types.go
Outdated
@@ -293,6 +293,18 @@ func getBinaryOpType(opType promql.ItemType) string { | |||
} | |||
} | |||
|
|||
// GetUnaryOpType returns the M3 unary op type based on the Prom op type | |||
func GetUnaryOpType(opType promql.ItemType) (string, bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; does this need to be exported?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, good call.
src/query/block/lazy.go
Outdated
val[i].Value = vt(dp.Value) | ||
var ( | ||
c = it.it.Current() | ||
stepDPs = c.Values() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; values
reads a bit better
src/query/block/lazy.go
Outdated
val[i].Value = vt(dp.Value) | ||
var ( | ||
c = it.it.Current() | ||
seriesDPs = c.datapoints |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; values reads better
@@ -418,3 +419,224 @@ func TestUnconsolidatedSeriesIter(t *testing.T) { | |||
|
|||
assert.Equal(t, expected, actual.Datapoints()) | |||
} | |||
|
|||
// negative value offset tests | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: newline
src/query/parser/promql/parse.go
Outdated
return fmt.Errorf("only + and - operators allowed for unary expressions, received: %s", n.Op.String()) | ||
} | ||
|
||
return p.addLazyTransform(0, lazy.UnaryType, unaryType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit janky; I think it's better to split the functions up for now (i.e. noops if it's plus, and creates a value transform otherwise)
e8b82ba
to
3dac576
Compare
src/query/parser/promql/types.go
Outdated
@@ -248,7 +248,7 @@ func NewFunctionExpr( | |||
return p, true, err | |||
|
|||
default: | |||
// TODO: handle other types | |||
// TODO: handle other types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; can probably remove this, think we handle all types
@@ -76,6 +77,39 @@ func TestInvalidOffset(t *testing.T) { | |||
require.Error(t, err) | |||
} | |||
|
|||
func TestUnary(t *testing.T) { | |||
q := "-up" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worth adding +up
case? Can probably generalize this to be like
for _, q := range []string{"+up","-up"} {
....
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+
skips the unary op, so its just a fetch. Will add a test though.
ctrl := gomock.NewController(t) | ||
bb := NewMockBlock(ctrl) | ||
defer ctrl.Finish() | ||
offset := time.Duration(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mind adding one with both transform and offset?
defer ctrl.Finish() | ||
b := NewMockBlock(ctrl) | ||
offset := time.Duration(0) | ||
off := NewLazyBlock(b, testLazyOpts(offset, -1.0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can do testLazyOpts(0, -1.0)
and it'll typecast it properly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah just figured I'd be more explicit with it being a duration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; some suggestions for additional tests but up to you
stepVals = c.Values() | ||
) | ||
|
||
vals := make([]float64, 0, len(stepVals)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
longer term, instead of allocating for each Current()
call, you can reuse a field in the struct. it'd look something like this:
type lazyStepIter struct {
it StepIter
opts LazyOptions
values []float64
}
func (it *lazyStepIter) Current() Step {
var (
c = it.it.Current()
tt, vt = it.opts.TimeTransform(), it.opts.ValueTransform()
stepVals = c.Values()
)
it.values = it.values[:0]
if cap(it.values) < len(stepVals) {
it.values = make([]float64, 0, len(stepVals))
}
...
return ColStep{
...
values: it.values,
}
}
note: this might cause issues if the callers of the this function are relying on the returned value from this function to be valid after multiple calls to Next()/Current(). Dunno how it's used so can't say for sure. Maybe file an issue to look into this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do it this way, would make sense to move all this logic into the Next
function so we don't have to recalculate 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, Next() would definitely be the better place for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
f4206d3
to
4d90fd3
Compare
What this PR does / why we need it:
This PR fixes #1619. It introduces support for unary expressions -- specifically
+
and-
. For example, this query is now supported:Special notes for your reviewer:
Does this PR introduce a user-facing and/or backwards incompatible change?:
Does this PR require updating code package or user-facing documentation?: