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

feat(remap): diagnostic error messages #6023

Merged
merged 21 commits into from
Jan 18, 2021
Merged

Conversation

JeanMertz
Copy link
Contributor

@JeanMertz JeanMertz commented Jan 13, 2021

This PR adds the initial infrastructure to support diagnostic error messages in VRL.

Given this source:

if .foo {
	true
}

This is the diagnostic message returned by the compiler (running inside Vector):

I'm fairly happy how this ended up for the initial 0.12 release, but there's plenty of more to do here. I'll be filing separate issues to track future improvements.

On a high-level, here's what has changed:

  • A new Diagnostic type (and friends) is introduced to record detailed information about an error.
  • The parser can now continue parsing if it encounters a recoverable parsing error.
    • Invalid token errors are currently unrecoverable (although we can improve this by trying to continue to parse the next expression)
    • All other non-grammar related errors are recoverable (e.g. providing a non-boolean value to an if-statement condition)
    • In the case of recoverable errors, the compiler state is reverted to before parsing began of the given expression, such that any invalid variable/target assignments are removed before continuing.
  • A Program now returns Result<(Vec<Expression>, DiagnosticList), DiagnosticList>. The Err case is returned if any of the diagnostic recorded are of level "error" or higher. The Ok case only contains diagnostic messages of "warning" or lower (or none at all).
  • The Runtime now returns a single Abort error if it failed to run. This is the case if you use ! in a function (e.g. parse_json!(.foo)), which would satisfy the error-handling constraint at compile-time, but can still terminate the program at runtime.

closes #4803
closes #6027

@JeanMertz JeanMertz added the domain: vrl Anything related to the Vector Remap Language label Jan 13, 2021
@JeanMertz JeanMertz added this to the 2021-01-04 Xenomass Well milestone Jan 13, 2021
@JeanMertz JeanMertz self-assigned this Jan 13, 2021
@JeanMertz
Copy link
Contributor Author

Moving this back to draft, since I'm doing some internal changes to allow multiple diagnostics to be returned (and also in general improving the internal API design).

cc #6027

@JeanMertz JeanMertz marked this pull request as draft January 14, 2021 07:50
Base automatically changed from jean/remap-test-harness to master January 14, 2021 08:52
Comment on lines -65 to +55
let value = object
.get(&self.path)
.map_err(|e| E::from(Error::Resolve(e)))?
.unwrap_or(Value::Null);
let value = object.get(&self.path).ok().flatten().unwrap_or(Value::Null);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged (some of) #5941 into this PR, as it made it easier to implement/test the changes in this PR.

Err("remap error: function error: unknown enum variant: baz, must be one of: foo, bar"),
Ok(().into()),
),
// TODO: move to `remap-tests`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once this PR and #6105 are merged, I'll be moving these tests to our UI testing set-up.

Comment on lines +138 to +141
pub struct ParsedExpression {
span: Span,
expr: Expr,
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually, I want to encode span information into our Expr type, but that proved to be a bigger change than needed right now.

.with_primary(format!("got: {}", got), arguments_span)
.with_context(format!("expected: {} (at most)", max), arguments_span)
}
// TODO: have spans for each individual keyword
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something I'll tackle in a follow-up PR.

# = hint: assign to "ok", without assigning to "err"
# = see language documentation at: https://vector.dev/docs/reference/vrl/

ok, err = 5;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When reviewing, consider these early prototype messages.

The actual URLs, notes, and exact messages will be iterated on in future PRs. This PR's main purpose is to have the plumbing in place to allow us to improve these messages going forward.

Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
@JeanMertz JeanMertz marked this pull request as ready for review January 18, 2021 11:06
@JeanMertz JeanMertz removed the request for review from jszwedko January 18, 2021 11:06
Signed-off-by: Jean Mertz <git@jeanmertz.com>
span.clone(),
);

match () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, this would be nicer as an if .. else if .. else.

Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
.filter(|e| e.type_def(&state).is_fallible())
.for_each(|e| {
diagnostics.push(
Diagnostic::error("unhandled error")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes the expression results in a runtime error because the function is a fallible one (eg. parse_json). But other times it can because it has been passed a parameter that it can't determine is the correct type.

I think ultimately it would be nice to be able to distinguish between these. So for example with this:

 if .ook == true { x = 2 } else { x = "boo" }
 .thing = round(.x)

It would be nice for the error reporting to say :

error: unhandled error
  ┌─ :2:2
  │
2 │     .thing = round(.x)
  │     ^^^^^^^^^^^^^^^^^^
  │     │
  │     expression can't determine the correct types for the parameters and so may fail if it is passed
  │     an incorrect type.
  │     handle the error case to ensure runtime success
  │

However that probably requires a bit of change to the fallibility checks to make fallibilty more than just a simple boolean, which would be out of scope for this PR.

Perhaps would could just change the below error message to say expression can result in runtime error, possibly because it can't determine the correct types for the parameters? That would help point the user in the right direction without having to jump to the docs..

Copy link
Contributor Author

@JeanMertz JeanMertz Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, as long as we use the try_boolean() etc functions in the function implementation, this will already display something like unexpected type "string" for value. But I agree that this can use a further refinement (specifically to mention the parameter name), and indeed it requires a bit more work that I considered to be outside the scope of this PR.

Copy link
Contributor

@StephenWakely StephenWakely left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Will all the commented out tests be moved out in a future PR, or is this still to do?

@JeanMertz
Copy link
Contributor Author

JeanMertz commented Jan 18, 2021

Will all the commented out tests be moved out in a future PR, or is this still to do?

They will! See my earlier comment: #6023 (comment)

Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
Signed-off-by: Jean Mertz <git@jeanmertz.com>
@JeanMertz JeanMertz merged commit a2107bb into master Jan 18, 2021
@JeanMertz JeanMertz deleted the jean/remap-diagnostics branch January 18, 2021 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain: vrl Anything related to the Vector Remap Language
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support continued parsing even when error occurs Better remap-lang error reporting
3 participants