-
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
Send query plan to querier. #11246
Send query plan to querier. #11246
Conversation
Trivy scan found the following vulnerabilities:
|
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.
a few comments, some bits are still missing from my mental model for how this will work but I'll ask about that somewhere else to not clog up the PR review
pkg/logql/evaluator.go
Outdated
// ParamsWithExpressionOverride overrides the query expression so that the query | ||
// string and the expression can differ. This is useful for sharding etc. |
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.
should this comment be useful for query planning when plan my not match externally available logql syntax
?
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.
Yes. Done.
pkg/querier/http.go
Outdated
@@ -73,6 +73,7 @@ func (q *QuerierAPI) RangeQueryHandler(ctx context.Context, req *queryrange.Loki | |||
return logqlmodel.Result{}, err | |||
} | |||
|
|||
// TODO: fun fact req should implement params. So no wrapper would be required 🤷 |
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.
is this true? are you saying it should, or it does currently?
Following the chain, req
is queryrangebase.Request
, which is definitions.Request
. That interface doesn't have a function to get the params, but I think it makes sense for it to have one. I think that's what you're suggesting 👍
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.
The logql.Params
interface is defined as
type Params interface {
Query() string
Start() time.Time
End() time.Time
Step() time.Duration
Interval() time.Duration
Limit() uint32
Direction() logproto.Direction
Shards() []string
}
queryrange.LokiRequest
is very similar but has GetEndTs
instead of End
. I'd not change it here but wanted to surface the difference.
var err error | ||
p.queryExpr, err = syntax.ParseExpr(qs) | ||
return p, err |
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.
does it make sense to keep both the string and parsed expression on this 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.
afaict we either pass the query string to parsing functions like engine.go
we call
expr, err := q.parse(ctx, q.params.Query())
in Eval
or evaluator.go
we call expr, err := syntax.ParseSampleExpr(q.Query())
in Sortable
Other than that we only call Query
to get the query string for passing to error logging. And the Expr
interface has a fmt.Stringer
to support String
, so I think we could store just the parsed expression and remove storing the query 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.
If we want to keep the string it might be nice to rename the function QueryString
, can be confusing at first glance to differentiate between the logql turning Params
into a Query
that can be Exec
'd when we have another function here Query
.
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.
Other than that we only call Query to get the query string for passing to error logging.
That's the sole reason to keep it around. The engine should not use the string other than for logging.
If we want to keep the string it might be nice to rename the function QueryString,
That's a good idea.
if q.checkBlocked(ctx, tenants) { | ||
return nil, logqlmodel.ErrBlocked | ||
} | ||
|
||
switch e := expr.(type) { | ||
switch e := q.params.GetExpression().(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.
should we have the Expr
interface also support a Type
function? or maybe even via the query
struct modify it to save the parsed Expr
instead of just having Params
and a parse
function?
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 could but it would be very similar to this type switch.
This is btw the benefit of the change. We don't have to parse the query.
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.
Overall looks fantastic! Very excited to see this all come together.
Marked the remaining TODOs, left one or two nits, and even a couple substantive questions!
return p.GetQuery() | ||
} | ||
|
||
func (p paramsLabelWrapper) GetExpression() syntax.Expr { |
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.
Hhmm, does it make sense for these to even implement the interface?
Seems like we need a parent interface here, and GetExpression()
, QueryString()
etc can move into a sub-interface of that
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 agree. logql.Params
is an odd interface. I did try to change it just to find out there a logql.QueryParams
that does not really fit the need. Let's see.
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.
Ok, I don't this is feasible in this change. stats is using the params and they must have an expression for the RecordRangeAndInstantQueryMetrics. I can do a follow up and change them so they use their own interface.
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.
Sounds good, it's a non-blocking nit
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 lets clean these up in a follow up. Nice that we have a better sense of how all this should fit together as a result of this PR 👍
_, _, err = rvm.Parse(`{app="foo"} |= "err"`) | ||
_, _, err = rvm.Parse(syntax.MustParseExpr(`{app="foo"} |= "err"`)) | ||
require.Error(t, err) | ||
_, _, err = rvm.Parse(`topk(0, sum(count_over_time({app="foo"} | json | __error__="" [15m])))`) | ||
require.Error(t, err) | ||
// Check fixes for bug where missing or empty parameters for regexp and pattern parsers threw a panic | ||
// Missing parameter to regexp parser | ||
_, _, err = rvm.Parse(`topk(10,sum by(namespace)(count_over_time({application="nginx", site!="eu-west-1-dev"} |= "/artifactory/" != "api" != "binarystore" | regexp [1d])))`) | ||
require.ErrorIs(t, err, logqlmodel.ErrParse) | ||
// Empty parameter to regexp parser | ||
_, _, err = rvm.Parse(`topk(10,sum by(namespace)(count_over_time({application="nginx", site!="eu-west-1-dev"} |= "/artifactory/" != "api" != "binarystore" | regexp ` + "``" + ` [1d])))`) | ||
require.ErrorIs(t, err, logqlmodel.ErrParse) | ||
// Empty parameter to pattern parser | ||
_, _, err = rvm.Parse(`topk(10,sum by(namespace)(count_over_time({application="nginx", site!="eu-west-1-dev"} |= "/artifactory/" != "api" != "binarystore" | pattern ` + `""` + ` [1d])))`) | ||
require.ErrorIs(t, err, logqlmodel.ErrParse) | ||
// Empty parameter to json parser | ||
_, _, err = rvm.Parse(`topk(10,sum by(namespace)(count_over_time({application="nginx", site!="eu-west-1-dev"} |= "/artifactory/" != "api" != "binarystore" | json [1d])))`) |
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.
Since we are using GetExpressions
these cases do not apply anymore. Parsing errors are caught when a request is decoded.
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.
Let's go!
Signed-off-by: Callum Styan <[email protected]>
Signed-off-by: Callum Styan <[email protected]>
**What this PR does / why we need it**: The recent change #11246 requires that `LokiRequest.Plan` is always set. **Checklist** - [ ] Reviewed the [`CONTRIBUTING.md`](https://github.com/grafana/loki/blob/main/CONTRIBUTING.md) guide (**required**) - [ ] Documentation added - [x] Tests updated - [ ] `CHANGELOG.md` updated - [ ] If the change is worth mentioning in the release notes, add `add-to-release-notes` label - [ ] Changes that require user attention or interaction to upgrade are documented in `docs/sources/setup/upgrade/_index.md` - [ ] For Helm chart changes bump the Helm chart version in `production/helm/loki/Chart.yaml` and update `production/helm/loki/CHANGELOG.md` and `production/helm/loki/README.md`. [Example PR](d10549e) - [ ] If the change is deprecating or removing a configuration option, update the `deprecated-config.yaml` and `deleted-config.yaml` files respectively in the `tools/deprecated-config-checker` directory. [Example PR](0d4416a)
**What this PR does / why we need it**: Following grafana#11123 and in order to enable grafana#10417 the query frontend should send the serialized LogQL AST instead of the query string to the queriers. This enables the frontend to change the AST and inject expressions that are not expressible in LogQL. **Checklist** - [ ] Reviewed the [`CONTRIBUTING.md`](https://github.com/grafana/loki/blob/main/CONTRIBUTING.md) guide (**required**) - [ ] Documentation added - [x] Tests updated - [ ] `CHANGELOG.md` updated - [ ] If the change is worth mentioning in the release notes, add `add-to-release-notes` label - [ ] Changes that require user attention or interaction to upgrade are documented in `docs/sources/setup/upgrade/_index.md` - [ ] For Helm chart changes bump the Helm chart version in `production/helm/loki/Chart.yaml` and update `production/helm/loki/CHANGELOG.md` and `production/helm/loki/README.md`. [Example PR](grafana@d10549e) - [ ] If the change is deprecating or removing a configuration option, update the `deprecated-config.yaml` and `deleted-config.yaml` files respectively in the `tools/deprecated-config-checker` directory. [Example PR](grafana@0d4416a) --------- Signed-off-by: Callum Styan <[email protected]> Co-authored-by: Callum Styan <[email protected]>
**What this PR does / why we need it**: The recent change grafana#11246 requires that `LokiRequest.Plan` is always set. **Checklist** - [ ] Reviewed the [`CONTRIBUTING.md`](https://github.com/grafana/loki/blob/main/CONTRIBUTING.md) guide (**required**) - [ ] Documentation added - [x] Tests updated - [ ] `CHANGELOG.md` updated - [ ] If the change is worth mentioning in the release notes, add `add-to-release-notes` label - [ ] Changes that require user attention or interaction to upgrade are documented in `docs/sources/setup/upgrade/_index.md` - [ ] For Helm chart changes bump the Helm chart version in `production/helm/loki/Chart.yaml` and update `production/helm/loki/CHANGELOG.md` and `production/helm/loki/README.md`. [Example PR](grafana@d10549e) - [ ] If the change is deprecating or removing a configuration option, update the `deprecated-config.yaml` and `deleted-config.yaml` files respectively in the `tools/deprecated-config-checker` directory. [Example PR](grafana@0d4416a)
What this PR does / why we need it:
Following #11123 and in order to enable #10417 the query frontend should send the serialized LogQL AST instead of the query string to the queriers. This enables the frontend to change the AST and inject expressions that are not expressible in LogQL.
Checklist
CONTRIBUTING.md
guide (required)CHANGELOG.md
updatedadd-to-release-notes
labeldocs/sources/setup/upgrade/_index.md
production/helm/loki/Chart.yaml
and updateproduction/helm/loki/CHANGELOG.md
andproduction/helm/loki/README.md
. Example PRdeprecated-config.yaml
anddeleted-config.yaml
files respectively in thetools/deprecated-config-checker
directory. Example PR