-
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] Fix quantile() argument not being passed through #2780
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2780 +/- ##
========================================
- Coverage 61.5% 60.6% -1.0%
========================================
Files 1015 1015
Lines 92824 92920 +96
========================================
- Hits 57106 56315 -791
- Misses 31220 32184 +964
+ Partials 4498 4421 -77
Flags with carried forward coverage won't be shown. Click here to find out more. Continue to review full report at Codecov.
|
src/query/parser/promql/matchers.go
Outdated
@@ -90,27 +90,31 @@ func NewAggregationOperator(expr *promql.AggregateExpr) (parser.Params, error) { | |||
Without: expr.Without, | |||
} | |||
|
|||
op := getAggOpType(opType) | |||
if op == common.UnknownOpType { | |||
switch op := getAggOpType(opType); op { |
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: this switch
has multi-line case
blocks, would be a bit easier on the eyes if they were separated with empty lines.
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.
"quantile(0, quack)", | ||
"quantile(0.8, avg_over_time(quack[30s]))", | ||
"quantile(1, avg(avg_over_time(quack[30s])) by (name))" |
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.
Better use multi_10
metrics, it will give you 10 series.
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.
"queryGroup":"quantile", | ||
"queries":[ |
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.
Mini nit:
"queryGroup":"quantile", | |
"queries":[ | |
"queryGroup": "quantile", | |
"queries": [ |
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.
"quantile(0.8, avg_over_time(quack[30s]))", | ||
"quantile(1, avg(avg_over_time(quack[30s])) by (name))" | ||
], | ||
"steps" : [ |
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.
Mini nit:
"steps" : [ | |
"steps": [ |
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.
src/query/parser/promql/matchers.go
Outdated
@@ -90,27 +90,35 @@ func NewAggregationOperator(expr *promql.AggregateExpr) (parser.Params, error) { | |||
Without: expr.Without, | |||
} | |||
|
|||
op := getAggOpType(opType) | |||
if op == common.UnknownOpType { | |||
switch op := getAggOpType(opType); op { |
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: switch getAggOpType(opType) {
is a simpler way of doing this
switch op := getAggOpType(opType); op { | |
switch getAggOpType(opType) { |
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.
127200b#diff-fc8829d2c3cb3722ece0dc21d2fb4c8b2cf03230f5b641113b7413faf1660fa7L93-R94 , though op
is still needed
src/query/parser/promql/matchers.go
Outdated
val, err := resolveScalarArgument(expr.Param) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
nodeInformation.Parameter = val | ||
return aggregation.NewAggregationOp(op, nodeInformation) | ||
|
||
default: | ||
return aggregation.NewAggregationOp(op, nodeInformation) | ||
} |
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; Don't think you need the default case or the special return here if you move the aggregation.NewAggregationOp(op, nodeInformation)
out of the switch
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.
|
||
# Bug #5276. | ||
# FAILING issue #56. scalar() inside aggregate function arguments kills the server |
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.
What is meant by killing the server? Did this change make the failure in this case worse than it was before?
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.
It seems that quantile(scalar(foo), ...)
eventually becomes quantile(NaN, ...)
, which causes panic in following computations. I've added a check if q == NaN
and a unit test, also updated the comment 9815297
panic: runtime error: index out of range [-9223372036854775808]
goroutine 13088 [running]:
github.com/m3db/m3/src/query/functions/aggregation.quantileFn(0x7ff8000000000001, 0xc007d7e370, 0xa, 0xa, 0xc00d2a11a0)
go/src/github.com/m3db/m3/src/query/functions/aggregation/quantile.go:86 +0x1d5
github.com/m3db/m3/src/query/functions/aggregation.bucketedQuantileFn(0x7ff8000000000001, 0xc007d7e050, 0xa, 0xa, 0xc0005d8380, 0xa, 0x10, 0xa)
go/src/github.com/m3db/m3/src/query/functions/aggregation/quantile.go:67 +0x17a
github.com/m3db/m3/src/query/functions/aggregation.makeQuantileFn.func1(0xc007d7e050, 0xa, 0xa, 0xc0005d8380, 0xa, 0x10, 0x0)
go/src/github.com/m3db/m3/src/query/functions/aggregation/quantile.go:42 +0x68
github.com/m3db/m3/src/query/functions/aggregation.(*baseNode).ProcessBlock(0xc00dbbb8c0, 0xc0060bdef0, 0x298a4f0, 0x1, 0x1ce15e0, 0xc00a19a600, 0x1, 0x1cf2680, 0x2a210e0, 0x1cd1540)
go/src/github.com/m3db/m3/src/query/functions/aggregation/base.go:163 +0x480
<...>
return nil, err | ||
} | ||
|
||
nodeInformation.Parameter = val |
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.
May be worth adding a test for this; may be a bit complex though since it would need to generate the op, get the node, then create a mock block and run it against functions (since we can't really inspect this otherwise; maybe add a NodeInformation()
on parser.Params
? Although that may lead to a deeper rabbithole)
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.
We've discussed this with @linasm and reached a similar conclusion about it being not very straightforward. For now, the tests in aggregators.test
and queries.json
should provide some coverage. I may look into this further in a follow-up PR.
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.
Approved /w nits
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.
Well done overall, had a few minor suggestions.
@@ -48,6 +48,10 @@ func bucketedQuantileFn(q float64, values []float64, bucket []int) float64 { | |||
return math.NaN() | |||
} | |||
|
|||
if math.IsNaN(q) { |
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.
Merge it with the if
above.
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.
expected := math.NaN() | ||
actual := bucketedQuantileFn(math.NaN(), values, buckets) | ||
|
||
test.EqualsWithNans(t, expected, actual) |
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.
Just make it a more direct require.True(t, math.IsNaN(actual))
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.
buckets := []int{0, 1} | ||
|
||
expected := math.NaN() | ||
actual := bucketedQuantileFn(math.NaN(), values, buckets) |
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.
Also please cover the cases with empty values
and empty buckets
(if they are not currently covered).
Can do it in the same test function, especially if you inline those arguments a bit.
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.
@@ -117,6 +117,18 @@ func TestQuantileFnSingleNonNan(t *testing.T) { | |||
test.EqualsWithNansWithDelta(t, expected, actual, math.Pow10(-5)) | |||
} | |||
|
|||
func TestQuantileNanAndEmptyArguments(t *testing.T) { | |||
actual := []float64{ |
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 good idea, but it will not report which case(s) fail.
There is a more standard approach for such tests in go, called 'test tables`, eg.:
tests := []struct { |
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.
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
@arnikola since I made quite a few changes while addressing the comments, I'm re-adding you for review |
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
* master: Support dynamic namespace resolution for embedded coordinators (#2815) [dbnode] Add index regexp DFA compilation cache to avoid allocating DFAs for same expressions (#2814) [dbnode] Set default cache on retrieve to false, prepare testing with cache none (#2813) [tools] Output annotations as base64 (#2743) Add Reset Transformation (#2794) [large-tiles] Fix for a reverse index when querying downsampled namespace (#2808) [dbnode] Evict info files cache before index bootstrap in peers bootstrapper (#2802) [dbnode] Bump default filesystem persist rate limit (#2806) [coordinator] Add metrics and configurability of downsample and ingest writer worker pool (#2797) [dbnode] Fix concurrency granularity of seekerManager.UpdateOpenLease (#2790) [dbnode] Use correct import path for atomic library (#2801) Regenerate carbon automapping rules on namespaces changes (#2793) Enforce matching retention and index block size (#2783) [query] Add ClusterNamespacesWatcher and use to generate downsample automapper rules (#2782) [query][dbnode] Wire up etcd-backed Clusters implementation in coordinator (#2758) [query] Fix quantile() argument not being passed through (#2780) # Conflicts: # src/query/parser/promql/matchers.go
* master: [query] Improve precision for variance and stddev of equal values (#2799) Support dynamic namespace resolution for embedded coordinators (#2815) [dbnode] Add index regexp DFA compilation cache to avoid allocating DFAs for same expressions (#2814) [dbnode] Set default cache on retrieve to false, prepare testing with cache none (#2813) [tools] Output annotations as base64 (#2743) Add Reset Transformation (#2794) [large-tiles] Fix for a reverse index when querying downsampled namespace (#2808) [dbnode] Evict info files cache before index bootstrap in peers bootstrapper (#2802) [dbnode] Bump default filesystem persist rate limit (#2806) [coordinator] Add metrics and configurability of downsample and ingest writer worker pool (#2797) [dbnode] Fix concurrency granularity of seekerManager.UpdateOpenLease (#2790) [dbnode] Use correct import path for atomic library (#2801) Regenerate carbon automapping rules on namespaces changes (#2793) Enforce matching retention and index block size (#2783) [query] Add ClusterNamespacesWatcher and use to generate downsample automapper rules (#2782) [query][dbnode] Wire up etcd-backed Clusters implementation in coordinator (#2758) [query] Fix quantile() argument not being passed through (#2780) [query] Add "median" aggregation to Graphite aggregate() function (#2774) [r2] Ensure KeepOriginal is propagated when adding/reviving rules (#2796) [dbnode] Update default db read limits (#2784)
What this PR does / why we need it:
Fix
quantile()
argument not being passed through when processing promql expression. This improves m3query compatibilitySpecial 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?: