Skip to content
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

Allow "type guards" in VRL #91

Open
jszwedko opened this issue Oct 1, 2021 · 2 comments
Open

Allow "type guards" in VRL #91

jszwedko opened this issue Oct 1, 2021 · 2 comments
Labels
type: enhancement A value-adding code change that enhances its existing functionality vrl: typedef Changes to the type system

Comments

@jszwedko
Copy link
Member

jszwedko commented Oct 1, 2021

I believe we've discussed this in other places before as well, but it came up again in vectordotdev/vector#9406 where a user expected that if they used is_string() that VRL would be able to determine that the argument thereafter was a string if the rest of the expression only executed if is_string was true.

Specifically, they had:

is_string(.message) && !contains(.message, s'test')

But you could also imagine this with if conditions:

if is_string(.message) {
 !contains(.message, s'test')
} else {
  false
}

I'm not 100% sold on if we want to do this, but opening for discussion.

@jszwedko jszwedko added the type: enhancement A value-adding code change that enhances its existing functionality label Oct 1, 2021
@JeanMertz
Copy link
Contributor

see also: vectordotdev/vector#5261 (comment)

@myndzi
Copy link

myndzi commented Nov 11, 2021

(Just to leave a comment reflecting my use case)

I think this kind of expression shortcutting is both common and expected in many contexts. However, the real value is in the separation of concerns. The example in the OP is good:

is_string(.message) && !contains(.message, s'test')

This is essentially: "if the message conforms to my expectations, then evaluate some expression that relies on those expectations", where these two parts are decoupled and explicitly defined. Relying on coercion and failure handling instead makes things messy or unclear (at least, it certainly is less clear to me, being less familiar with the intricate details of VRL).

From discord, for example:

So, if you want to pass a condition if a field exists, and it's a string, and it contains foo, then this would work:

exists(.message) && contains(string!(.message), "foo")

This can still fail at runtime, if .message isn't a string, but it'll never fail if the field is missing.

So this solution is both more verbose and still not complete and correct. A solution like contains(to_string!(.message), "foo") is also unfortunate: if .message is a number for some reason, and that number becomes a string ("42"), there are cases where it might unexpectedly match (the match text being numeric in nature, for example).

All in all, given that properties which don't exist are "null", then the expression is_string(.message) && .... checks both existence and type, which allows you to cleanly express the actual thing you care about and also dictate whether a non-conforming event passes or fails the condition quite naturally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A value-adding code change that enhances its existing functionality vrl: typedef Changes to the type system
Projects
None yet
Development

No branches or pull requests

3 participants