-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
add on and ignoring clauses in binOpExpr #4391
Conversation
7b946ac
to
06a3ae7
Compare
@owen-d this PR is target to resolve the TODO item - |
@owen-d let's make sure querysharding is happy with this. |
@@ -675,7 +675,11 @@ func TestMapping(t *testing.T) { | |||
{ | |||
in: `1 + sum by (cluster) (rate({foo="bar"}[5m]))`, | |||
expr: &BinOpExpr{ | |||
op: OpTypeAdd, | |||
op: OpTypeAdd, |
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 need example with this new operator. The binary operation should never be shardable so I think we're fine.
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.
thanks @cyriltovena for your comments, make sense, added example for new operator in shardmapper unit test - 9cb1a81
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's currrently implemented like this:
func (e *BinOpExpr) Shardable() bool {
return shardableOps[e.op] && e.SampleExpr.Shardable() && e.RHS.Shardable()
}
However, I think we should prohibit sharding when we're changing the label groupings such as in on
or without
as it effectively changes the labels and thus invalidates correctness guarantees in sharded aggregation. @garrettlish can you make the change to the Shardable
method to return false
if either on
or without
are specified?
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.
From my perspective the addition looks good. It would be great to have a doc addition though.
I let @owen-d give the final word.
Awesome, I'll give this a review soon :) |
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.
Hey @garrettlish, this looks great. Thanks for taking care of my todo for me 🎉 . I've left a few comments I'd like addressed, but then I'm happy to merge it. Really great job uncovering the complexity in here and navigating it well. I expect after this change, we'll need to implement group_{left,right}
soon 😁 .
pkg/logql/evaluator.go
Outdated
pair := pairs[hash] | ||
if pair[i] != nil { | ||
failStepEvaluator(eval, errors.New("multiple matches for labels")) |
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.
Nice, was looking for this. It would be great to include a test case that hits this condition. However, instead of trying to mutate the underlying Evaluator by type switching, can we instead use a scoped error
that the is set here and checked in the func() error
part of the newStepEvaluator
(https://github.com/grafana/loki/blob/main/pkg/logql/evaluator.go#L604)?
pkg/logql/evaluator.go
Outdated
@@ -1017,3 +1033,17 @@ func absentLabels(expr SampleExpr) labels.Labels { | |||
} | |||
return m | |||
} | |||
|
|||
// failStepEvaluator marks the step evaluator as failed | |||
func failStepEvaluator(se StepEvaluator, err error) { |
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.
I'd prefer not to mutate via type switching here, both because mutation can make for a trickier codebase and because type switching is hard to extend well (for instance, if we add newer StepEvaluator
implementations).
pkg/logql/expr.y
Outdated
@@ -33,7 +33,8 @@ import ( | |||
str string | |||
duration time.Duration | |||
LiteralExpr *LiteralExpr | |||
BinOpModifier BinOpOptions | |||
BinOpModifier *BinOpOptions | |||
BoolModifier *BinOpOptions |
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: formatting :)
pkg/logql/expr.y
Outdated
| boolModifier ON OPEN_PARENTHESIS CLOSE_PARENTHESIS | ||
{ | ||
$$ = $1 | ||
$$.VectorMatching = &VectorMatching{On: true, Include: []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: I suspect this can be nil
here
$$.VectorMatching = &VectorMatching{On: true, Include: []string{}} | |
$$.VectorMatching = &VectorMatching{On: true, Include: nil} |
pkg/logql/expr.y
Outdated
| boolModifier IGNORING OPEN_PARENTHESIS CLOSE_PARENTHESIS | ||
{ | ||
$$ = $1 | ||
$$.VectorMatching = &VectorMatching{On: false, Include: []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: I suspect this can be nil
here
$$.VectorMatching = &VectorMatching{On: false, Include: []string{}} | |
$$.VectorMatching = &VectorMatching{On: false, Include: nil} |
@@ -675,7 +675,11 @@ func TestMapping(t *testing.T) { | |||
{ | |||
in: `1 + sum by (cluster) (rate({foo="bar"}[5m]))`, | |||
expr: &BinOpExpr{ | |||
op: OpTypeAdd, | |||
op: OpTypeAdd, |
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's currrently implemented like this:
func (e *BinOpExpr) Shardable() bool {
return shardableOps[e.op] && e.SampleExpr.Shardable() && e.RHS.Shardable()
}
However, I think we should prohibit sharding when we're changing the label groupings such as in on
or without
as it effectively changes the labels and thus invalidates correctness guarantees in sharded aggregation. @garrettlish can you make the change to the Shardable
method to return false
if either on
or without
are specified?
f36957c
to
581e4f2
Compare
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.
Looks great! One little request then I think we're ready to merge :)
Thanks for the great PR!
@@ -998,6 +998,10 @@ func (e *BinOpExpr) String() string { | |||
|
|||
// impl SampleExpr | |||
func (e *BinOpExpr) Shardable() bool { | |||
if e.opts != nil && e.opts.VectorMatching != nil { |
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: It'd be great to have a sharding test to ensure this
if e.opts != nil && e.opts.VectorMatching != nil { | |
// `without ()` is the zero value for VectorMatching and is also equivalent | |
// to not specifying a VectorMatching at all and thus can | |
// technically pass to the next expression for sharding concerns. | |
var zero VectorMatching | |
if e.opts != nil && e.opts.VectorMatching != nil && *e.opts.VectorMatching != zero { |
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.
@owen-d
We cannot use *e.opts.VectorMatching != zero
to check whether VectorMatching struct is empty, it is because VectorMatching
has Include []string
, it will cause Invalid operation: *e.opts.VectorMatching != zero (the operator != is not defined on VectorMatching)
.
I thought e.opts != nil && e.opts.VectorMatching != nil
should be good enough since e.opts.VectorMatching
is a pointer? Am I missing anything? Any thoughts, please advise! Thanks!
type BinOpOptions struct {
ReturnBool bool
VectorMatching *VectorMatching
}
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.
added sharding test - 0ab8264 and https://github.com/garrettlish/loki/blob/onOrIgnoring/pkg/logql/shardmapper_test.go#L984, could you please help review it again? Thanks!
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 bummer, slice comparison 😭 . Anyway, e.opts != nil && e.opts.VectorMatching != nil
should be fine. I was mainly protecting us from preventing sharding when the expression used without ()
, which is the same as not specifying without
at all. I don't think that should block this PR though. Great work, LGTM!
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.
I can't get the git suggestion to take my entire suggested reorg of just the docs part of this PR. It wants to reformat some of the suggestion as comment (instead of suggestion).
I'd like you to implement this rewrite. I'd like you to then further add a sentence or two just above each of the examples describing what the example demonstrates. Without that, doc readers really only see an example of the syntax.
My rewrite of the docs addition for file docs/sources/logql/_index.md: Keywords on and ignoringThe
Example:
The
Example:
|
Sorry @garrettlish, github formatted my rewrite. I wanted to give you the source to use. |
@KMiller-Grafana thanks for your comments, reformat the doc based on your suggestion - 0ab8264, please help review it again, thanks! |
0ab8264
to
867869f
Compare
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.
Thanks for the doc rewrite. One more item is needed. Please add a sentence or 2 just before each example, describing what the example does. Without that, an example becomes a syntax example. A sentence or two will help docs readers to understand the larger picture of what the example shows, and why these keywords are useful.
191dc6b
to
b837d8e
Compare
@KMiller-Grafana sorry, I missed your first comment 😭, added description for each example: b837d8e |
* use a scoped error to replace mutate stepEvaluator via type switching * change VectorMatching Include from empty string array to nil * prohibit sharding when we're changing the label groupings such as on or ignoring * add unit test to cover multiple matches for labels error * fix expr.y format issue
* reformat on and ignoring keywords doc * add sharding unit test for on and ignoring keywords
…s to understand the larger picture
b837d8e
to
8064e3d
Compare
will amend docs in a second pass
What this PR does / why we need it:
Add
on
andignoring
clauses in binOpExpr, theon
andignoring
modifier allows binary operation against different labelset.Which issue(s) this PR fixes:
Fixes TODO
TODO(owen-d): add (on,ignoring) clauses to binOpExpr
Special notes for your reviewer:
Checklist