-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Implement offset modifier for range vector aggregation in LogQL #3455
Changes from 3 commits
57dab90
82a7e84
05e14f9
d6e39f9
eb53fde
1b8f454
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -173,10 +173,18 @@ func (ev *DefaultEvaluator) StepEvaluator( | |||
// if range expression is wrapped with a vector expression | ||||
// we should send the vector expression for allowing reducing labels at the source. | ||||
nextEv = SampleEvaluatorFunc(func(ctx context.Context, nextEvaluator SampleEvaluator, expr SampleExpr, p Params) (StepEvaluator, error) { | ||||
var ( | ||||
start = q.Start().Add(-rangExpr.left.interval) | ||||
end = q.End() | ||||
) | ||||
if rangExpr.left.offset != nil { | ||||
start = start.Add(-rangExpr.left.offset.offset) | ||||
end = end.Add(-rangExpr.left.offset.offset) | ||||
} | ||||
it, err := ev.querier.SelectSamples(ctx, SelectSampleParams{ | ||||
&logproto.SampleQueryRequest{ | ||||
Start: q.Start().Add(-rangExpr.left.interval), | ||||
End: q.End(), | ||||
Start: start, | ||||
End: end, | ||||
Selector: e.String(), // intentionally send the the vector for reducing labels. | ||||
Shards: q.Shards(), | ||||
}, | ||||
|
@@ -189,10 +197,18 @@ func (ev *DefaultEvaluator) StepEvaluator( | |||
} | ||||
return vectorAggEvaluator(ctx, nextEv, e, q) | ||||
case *rangeAggregationExpr: | ||||
var ( | ||||
start = q.Start().Add(-e.left.interval) | ||||
end = q.End() | ||||
) | ||||
if e.left.offset != nil { | ||||
start = start.Add(-e.left.offset.offset) | ||||
end = end.Add(-e.left.offset.offset) | ||||
} | ||||
it, err := ev.querier.SelectSamples(ctx, SelectSampleParams{ | ||||
&logproto.SampleQueryRequest{ | ||||
Start: q.Start().Add(-e.left.interval), | ||||
End: q.End(), | ||||
Start: start, | ||||
End: end, | ||||
Selector: expr.String(), | ||||
Shards: q.Shards(), | ||||
}, | ||||
|
@@ -412,11 +428,15 @@ func rangeAggEvaluator( | |||
if err != nil { | ||||
return nil, err | ||||
} | ||||
var offset int64 | ||||
if expr.left.offset != nil { | ||||
offset = expr.left.offset.offset.Nanoseconds() | ||||
} | ||||
iter := newRangeVectorIterator( | ||||
it, | ||||
expr.left.interval.Nanoseconds(), | ||||
q.Step().Nanoseconds(), | ||||
q.Start().UnixNano(), q.End().UnixNano(), | ||||
q.Start().UnixNano(), q.End().UnixNano(), offset, | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can simplify this as well. There's no need to make the iterator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @owen-d thanks for your comments. I am passing the offset to iterator is because I'd like to shift the returned samples timestamp from history timestamp to current timestamp, otherwise, the returned samples timestamp are historical timestamp which is not meaningful. Any thoughts? Please advise, thanks! For example: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I originally had the same assumption as Owen, eg. you could just pass in the modified start/end. But now with your explanation I understand why it's like this. I think you could only offset back L148 only and that would be fine. loki/pkg/logql/range_vector.go Line 148 in 05e14f9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks @cyriltovena for the correction, I noticed the same thing and made changed in https://github.com/grafana/loki/pull/3455/files#diff-f4c7f355512099579b5ea8fa4ceceb6d1eeb2b99b10233b22e0e12ce571b25d1R152 already There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you should add a test with an offset different than zero for the range vector iterator. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Otherwise LGTM for me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make sense, let me add test, thanks @cyriltovena There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cyriltovena added non-zero offset test - 1b8f454, please help review again, thanks! |
||||
) | ||||
if expr.operation == OpRangeTypeAbsent { | ||||
return &absentRangeVectorEvaluator{ | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,7 @@ import ( | |
JSONExpression log.JSONExpression | ||
JSONExpressionList []log.JSONExpression | ||
UnwrapExpr *unwrapExpr | ||
OffsetExpr *offsetExpr | ||
} | ||
|
||
%start root | ||
|
@@ -90,6 +91,7 @@ import ( | |
%type <JSONExpressionList> jsonExpressionList | ||
%type <UnwrapExpr> unwrapExpr | ||
%type <UnitFilter> unitFilter | ||
%type <OffsetExpr> offsetExpr | ||
|
||
%token <bytes> BYTES | ||
%token <str> IDENTIFIER STRING NUMBER | ||
|
@@ -98,7 +100,7 @@ import ( | |
OPEN_PARENTHESIS CLOSE_PARENTHESIS BY WITHOUT COUNT_OVER_TIME RATE SUM AVG MAX MIN COUNT STDDEV STDVAR BOTTOMK TOPK | ||
BYTES_OVER_TIME BYTES_RATE BOOL JSON REGEXP LOGFMT PIPE LINE_FMT LABEL_FMT UNWRAP AVG_OVER_TIME SUM_OVER_TIME MIN_OVER_TIME | ||
MAX_OVER_TIME STDVAR_OVER_TIME STDDEV_OVER_TIME QUANTILE_OVER_TIME BYTES_CONV DURATION_CONV DURATION_SECONDS_CONV | ||
ABSENT_OVER_TIME LABEL_REPLACE UNPACK | ||
ABSENT_OVER_TIME LABEL_REPLACE UNPACK OFFSET | ||
|
||
// Operators are listed with increasing precedence. | ||
%left <binOp> OR | ||
|
@@ -133,19 +135,31 @@ logExpr: | |
; | ||
|
||
logRangeExpr: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love how we're duplicating all paths here. I know we've done this in the past, but it's getting out of hand (not your fault). @cyriltovena we should consider refactoring this a bit, but I'm fine with this PR. |
||
selector RANGE { $$ = newLogRange(newMatcherExpr($1), $2, nil) } | ||
| OPEN_PARENTHESIS selector CLOSE_PARENTHESIS RANGE { $$ = newLogRange(newMatcherExpr($2), $4, nil) } | ||
| selector RANGE unwrapExpr { $$ = newLogRange(newMatcherExpr($1), $2 , $3) } | ||
| OPEN_PARENTHESIS selector CLOSE_PARENTHESIS RANGE unwrapExpr { $$ = newLogRange(newMatcherExpr($2), $4 , $5) } | ||
| selector unwrapExpr RANGE { $$ = newLogRange(newMatcherExpr($1), $3, $2 ) } | ||
| OPEN_PARENTHESIS selector unwrapExpr CLOSE_PARENTHESIS RANGE { $$ = newLogRange(newMatcherExpr($2), $5, $3 ) } | ||
| selector pipelineExpr RANGE { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $2), $3, nil ) } | ||
| OPEN_PARENTHESIS selector pipelineExpr CLOSE_PARENTHESIS RANGE { $$ = newLogRange(newPipelineExpr(newMatcherExpr($2), $3), $5, nil ) } | ||
| selector pipelineExpr unwrapExpr RANGE { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $2), $4, $3) } | ||
| OPEN_PARENTHESIS selector pipelineExpr unwrapExpr CLOSE_PARENTHESIS RANGE { $$ = newLogRange(newPipelineExpr(newMatcherExpr($2), $3), $6, $4) } | ||
| selector RANGE pipelineExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $3), $2, nil) } | ||
| selector RANGE pipelineExpr unwrapExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $3), $2, $4 ) } | ||
| OPEN_PARENTHESIS logRangeExpr CLOSE_PARENTHESIS { $$ = $2 } | ||
selector RANGE { $$ = newLogRange(newMatcherExpr($1), $2, nil, nil ) } | ||
| selector RANGE offsetExpr { $$ = newLogRange(newMatcherExpr($1), $2, nil, $3 ) } | ||
| OPEN_PARENTHESIS selector CLOSE_PARENTHESIS RANGE { $$ = newLogRange(newMatcherExpr($2), $4, nil, nil ) } | ||
| OPEN_PARENTHESIS selector CLOSE_PARENTHESIS RANGE offsetExpr { $$ = newLogRange(newMatcherExpr($2), $4, nil, $5 ) } | ||
| selector RANGE unwrapExpr { $$ = newLogRange(newMatcherExpr($1), $2, $3, nil ) } | ||
| selector RANGE offsetExpr unwrapExpr { $$ = newLogRange(newMatcherExpr($1), $2, $4, $3 ) } | ||
| OPEN_PARENTHESIS selector CLOSE_PARENTHESIS RANGE unwrapExpr { $$ = newLogRange(newMatcherExpr($2), $4, $5, nil ) } | ||
| OPEN_PARENTHESIS selector CLOSE_PARENTHESIS RANGE offsetExpr unwrapExpr { $$ = newLogRange(newMatcherExpr($2), $4, $6, $5 ) } | ||
| selector unwrapExpr RANGE { $$ = newLogRange(newMatcherExpr($1), $3, $2, nil ) } | ||
| selector unwrapExpr RANGE offsetExpr { $$ = newLogRange(newMatcherExpr($1), $3, $2, $4 ) } | ||
| OPEN_PARENTHESIS selector unwrapExpr CLOSE_PARENTHESIS RANGE { $$ = newLogRange(newMatcherExpr($2), $5, $3, nil ) } | ||
| OPEN_PARENTHESIS selector unwrapExpr CLOSE_PARENTHESIS RANGE offsetExpr { $$ = newLogRange(newMatcherExpr($2), $5, $3, $6 ) } | ||
| selector pipelineExpr RANGE { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $2), $3, nil, nil ) } | ||
| selector pipelineExpr RANGE offsetExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $2), $3, nil, $4 ) } | ||
| OPEN_PARENTHESIS selector pipelineExpr CLOSE_PARENTHESIS RANGE { $$ = newLogRange(newPipelineExpr(newMatcherExpr($2), $3), $5, nil, nil ) } | ||
| OPEN_PARENTHESIS selector pipelineExpr CLOSE_PARENTHESIS RANGE offsetExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($2), $3), $5, nil, $6 ) } | ||
| selector pipelineExpr unwrapExpr RANGE { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $2), $4, $3, nil ) } | ||
| selector pipelineExpr unwrapExpr RANGE offsetExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $2), $4, $3, $5 ) } | ||
| OPEN_PARENTHESIS selector pipelineExpr unwrapExpr CLOSE_PARENTHESIS RANGE { $$ = newLogRange(newPipelineExpr(newMatcherExpr($2), $3), $6, $4, nil ) } | ||
| OPEN_PARENTHESIS selector pipelineExpr unwrapExpr CLOSE_PARENTHESIS RANGE offsetExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($2), $3), $6, $4, $7 ) } | ||
| selector RANGE pipelineExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $3), $2, nil, nil) } | ||
| selector RANGE offsetExpr pipelineExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $4), $2, nil, $3 ) } | ||
| selector RANGE pipelineExpr unwrapExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $3), $2, $4, nil ) } | ||
| selector RANGE offsetExpr pipelineExpr unwrapExpr { $$ = newLogRange(newPipelineExpr(newMatcherExpr($1), $4), $2, $5, $3 ) } | ||
| OPEN_PARENTHESIS logRangeExpr CLOSE_PARENTHESIS { $$ = $2 } | ||
| logRangeExpr error | ||
; | ||
|
||
|
@@ -363,6 +377,8 @@ rangeOp: | |
| ABSENT_OVER_TIME { $$ = OpRangeTypeAbsent } | ||
; | ||
|
||
offsetExpr: | ||
OFFSET DURATION { $$ = newOffsetExpr( $2 ) } | ||
|
||
labels: | ||
IDENTIFIER { $$ = []string{ $1 } } | ||
|
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.
small suggestion: it might be easier to simply have offset as
time.Duration
. sinceoffset=0
is the same as a nil offset, we could easily dorather than using the more clunky if statements:
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.
good idea, will make the change