-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
[pkg/ottl] Add condition parser #14783
[pkg/ottl] Add condition parser #14783
Conversation
@TylerHelmuth Thanks for doing that! :) I think this change was inspired by OTTL usage in the routing processor #13158 (comment). We added the OTTL support to the routing processor, as you mentioned above, by adding the Noop function to the only currently supported OTTL statement type. In the future, ideally, it would be great if the routing processor can have support for both statement types: So currently, in this PR, we have two mutually exclusive ASTs that are expressed via I was thinking about the following, what if we can have a single instance of the parser that is able to parse all supported by OTTL grammar statements? So we will have one AST with all possible OTTL statements, so the grammar can look as follows:
So we will have two types of parsed statements (maybe more later). After statements parsing, we can introduce a new layer of abstraction ("analysis") that would basically do all required validations of the parsed statements, e.g. functions look-ups, validation of whether the parsed statement type can be used in a certain context/component (we cannot use the condition statement in the transform processor), etc. It can be some kind of interface that has to be implemented when we create an instance of OTTL in components, but it is probably impl details. After the "analysis" phase, we will have some kind of analyzed statements that can be already evaluated. So essentially,
I guess this can introduce more flexibility in the adoption and usage of OTTL. Let's look at two examples:
I hope some of it makes some sense, however, I am sure that I am missing a lot of OTTL design discussions and some decisions, so this input might sound weird :) |
@kovrus thanks for the detailed feedback. This PR proposes adding parsing for condition functions via a new If I am understanding correctly, from the routing processor's perspective, having to differentiate between a The OTTL grammar could definitely be updated to make the Invocation and I am worried if we try to combine statement types into 1 return type from I was instead anticipating that components that rely on OTTL would use either different config sections, or in the case of the routing processor, a
|
Yes, that's correct.
Not exactly what I was trying to suggest. I was thinking more of modifying the grammar in the way that the root struct of the grammar would contain valid ottl statements (invocation + bool condition, bool condition, etc.) no need to modify valid statements by nulling some of its parts. So I guess, it is basically what you have in this PR, but just with placing conditionStatement and transformationStatement under the common root struct, so then the parser can capture those structs (statements) recursively. In the next step, we can convert those parsed statements to corresponding structs that now (your recent PR with changes to the Statement struct) will implement the Statement interface. I am not sure how the conversion of ParsedStatement to Statement can look like, you are right it can be a bit ugly.
That sounds like a solution. |
This is interesting. Were you thinking something like type statement struct {
TransformationStatement transformationStatement `parser:"( @@"`
ConditionStatement conditionStatement `parser:"| @@ )"`
}
type transformationStatement struct {
Invocation invocation `parser:"@@"`
WhereClause *booleanExpression `parser:"( 'where' @@ )?"`
}
type conditionStatement struct {
BooleanExpression *booleanExpression `parser:"@@"`
} With this structure One thing I don't like with this type of struct is when a new statement type requires new functions on the |
type statement struct {
TransformationStatement transformationStatement `parser:"( @@"`
ConditionStatement conditionStatement `parser:"| @@ )"`
} Exactly!
Yes, exactly one (valid in OTTL terms) statement type would be matched.
Yes, components should not be aware of the grammar and parser implementation details (parsed statements, types, etc.). However, using some statements might not make sense for some components (e.g.
I guess we should be fine with this abstraction All in all, with this pattern it would be possible to avoid adding |
Once the Statement Interface PR is merged I will play with this concept. |
@TylerHelmuth expect significant changes on this to make it consistent with the Statement PR. |
@bogdandrutu are you referring to the conversation @kovrus and I have been having or simply merging in main and adjusting the 2 |
This PR was marked stale due to lack of activity. It will be closed in 14 days. |
Closed as inactive. Feel free to reopen if this PR is still being worked on. |
Description:
Adds a new function to Parser that allows parsing
conditionStatements
, which is a new type of statement that represents only a booleanExpression. These types of statements do not include an Invocation orwhere
token.This new functionality can be used by any component to create complex boolean expressions and then invoke the expression during the hot path to make decisions. The routingprocessor is an example of a component that could use this functionality instead of the existing functionality, where it is forced to add a noop function to the statements.
Link to tracking Issue:
Closes #13545
Testing:
Updated unit tests
Documentation:
If we like this approach I will update documentation.