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: Display schema parse errors. #136

Merged
merged 15 commits into from
Dec 8, 2021

Conversation

o0Ignition0o
Copy link
Contributor

@o0Ignition0o o0Ignition0o commented Nov 15, 2021

fixes #182

With the previous apollo-rs dependency bump, we are now able to provide a bit more context and details when a schema parse failed.

This commit displays the schema errors that have been noticed during parsing.

@o0Ignition0o
Copy link
Contributor Author

     Running `target/debug/router -s ./examples/local.graphql`
Nov 15 11:41:30.511 ERROR apollo_router: Failed to read schema: Could not read schema: parse errors [
    ERROR@1716:1717 "Unexpected character" ;,
    ERROR@1702:1716 "expected definition" theiakjldfjsad,
    ERROR@1717:1723 "expected definition" fkjasf,
]
Nov 15 11:41:30.512  INFO router: Starting Apollo Router
*******************************************************************
⚠️  Experimental software, not YET recommended for production use ⚠️
*******************************************************************
Nov 15 11:41:30.513  INFO router: Stopped with error
Nov 15 11:41:30.513 ERROR router: Schema was not supplied.
Error: Schema was not supplied.

We can possibly iterate on this if / when we have a display impl for apollo_parser::Error, but this would be a nice first step for us to be able to work on supported features with users.

Comment on lines 184 to 190
#[derive(Debug, Error)]
pub enum SchemaError {
/// IO error: {0}
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
/// Parsing error(s).
#[error("parse errors {0:#?}")]
Copy link
Contributor

Choose a reason for hiding this comment

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

Keep using Display as it provides the doc at the same time than the error message

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the parser errors don't expose any impl display, do you want me to build an impl display for ParseErrors ?

Copy link
Contributor

Choose a reason for hiding this comment

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

no I meant displaydoc::Display

Copy link
Contributor

Choose a reason for hiding this comment

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

But eventually parse errors should implement Display indeed. Just not in this repository

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I see, thanks for clearing it up!

@Geal
Copy link
Contributor

Geal commented Nov 15, 2021

since the error has span information, could we get the context too? Like https://github.com/zkat/miette

@o0Ignition0o
Copy link
Contributor Author

@Geal @cecton This sounds like good ideas!

CCing @lrlna because I think they have something else in mind since the members are pub(crate) and there is no impl Display or Error.

@lrlna
Copy link
Member

lrlna commented Nov 15, 2021

I haven't yet implemented display for errors, but I was going to use miette. Might be able to get you something workable this week!

@o0Ignition0o
Copy link
Contributor Author

Super cool, marking this as draft, until we can do it right! Thanks again for your feedback @lrlna 🚀

@o0Ignition0o o0Ignition0o marked this pull request as draft November 15, 2021 14:24
@o0Ignition0o o0Ignition0o self-assigned this Nov 18, 2021
With the previous apollo-rs dependency bump, we are now able to provide a bit more context and details when a schema parse failed.

This commit displays the schema errors that have been noticed during parsing.
@o0Ignition0o o0Ignition0o force-pushed the igni/schema_parse_errors_display branch from 7da9988 to 00b82a3 Compare November 23, 2021 15:54
@o0Ignition0o
Copy link
Contributor Author

image

This looks super good! 🎉

@o0Ignition0o o0Ignition0o marked this pull request as ready for review November 23, 2021 19:57
span: SourceSpan,
}

impl std::fmt::Display for ParseErrors {
Copy link
Contributor

Choose a reason for hiding this comment

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

Super cool PR!

Though I'm not sure you are handling this properly. This diagnostic library inserts colors to the terminal. This is fine in the terminal but not so great for the logs in a text file. I believe Display should still be free of any ansi codes and stuff.

What I would suggest is:

  1. move this code to its own function: rename fmt() to print_pretty() or something
  2. it doesn't need to take the formatter in argument, you can use stdout or stderr directly (the formatter is a requirement for Display but here we know that the output will has to be the tty)
  3. You will need to change the main.rs to inspect the error you return and do a special handling for SchemaError::Parse

I know this sounds a lot more complicated but it will be more correct. The risk here is to sending logs with ansi codes somewhere by mistake.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm so what you mean is that we're conflating Error propagation and reporting, which is very true!

I wonder what responsibility should lie within Display and to the std::fmt::formatter. I would for example have liked to be able to ask the formatter if it supports colors.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There might be a couple of clues https://docs.rs/miette/3.2.0/miette/trait.ReportHandler.html around here, I'll let you know what I've found!

Copy link
Contributor

Choose a reason for hiding this comment

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

I would for example have liked to be able to ask the formatter if it supports colors.

afaik this is unsupported. That is why I think you can't put ansi code in implementations of Debug and Display.

For example ToString depends on Display. Is a string supposed to have ansi codes like that?

But then really my concern is that we report errors through other channels (journald, syslog, etc...) and we incorrectly send ansi codes in them.

Again this is all fancy but we should make it clear that this targets only the terminal (aka stdout or stderr if and only if it is a tty, otherwise you need to strip the ansi codes).

Copy link
Member

Choose a reason for hiding this comment

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

ohhh i did not know this is how you were going to send the error to the logs! I think the logs should just get the error slice, nothing should be formatted at all! Whatever reads the logs can do the formatting, or you can pipe the logs to a formatter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well it's in flux really, We do show the logs to a console at the moment, so we might as well have nice ones. OTOH we do have log exporters as well, so I'll probably move the formating to the "console logging layer", I feel this is what @cecton is hinting at?

Copy link
Contributor

Choose a reason for hiding this comment

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

To be sure we understand each other:

  1. Remove the {0} from the doc comment which will prevent this enum's Display to use the Display impl of ParseErrors. If the error gets logged, the user will have no other message than "Parsing error(s).". This is fine.

    /// Parsing error(s).
    Parse(ParseErrors),
  2. Change this piece of code:

    impl std::fmt::Display for ParseErrors {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            // ...
        }
    }

    To this:

    impl ParseErrors {
        fn print_pretty(&self) {
            // ... also replace writeln!(f, ...) by eprintln!(...)
        }
    }

    So we don't end up with a Display implementation and a ToString implementation that renders ansi codes (things like this ESC[38;5; in the string. See ANSI escape codes).

  3. In crates/apollo-router-core/src/schema.rs, instead of just simply returning the error, use your print_pretty function:

    if !tree.errors().is_empty() {
        let err = SchemaError::from_parse_errors(
            s.to_string(),
            tree.errors().to_vec(),
        );
        if isatty() {
            err.print_pretty();
        }
        return Err(err);

    You'll need this: isatty

crates/apollo-router-core/src/schema.rs Outdated Show resolved Hide resolved
@o0Ignition0o
Copy link
Contributor Author

marking it as draft, until errors return an iterator

@o0Ignition0o o0Ignition0o marked this pull request as draft November 25, 2021 10:19
@cecton
Copy link
Contributor

cecton commented Nov 25, 2021

I'm unsubscribing for now. Ping me when you need a review again.

@o0Ignition0o
Copy link
Contributor Author

o0Ignition0o commented Dec 6, 2021

This input:

schema
  @core(feature: "https://specs.apollo.dev/core/v0.1"),
  @core(feature: "https://specs.apollo.dev/join/v0.1")
{
  query: Query
  mutation: Mutation
}

directive @core(feature: String!) repeatable on SCHEMA
thisdoesntbelonghere
directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION

generates this output in a TTY:

image

and this output if not in a TTY:

Running `target/debug/router -s ./examples/supergraph.graphql`
ERROR@214:234 "expected definition" thisdoesntbelonghere
2021-12-06T15:33:58.217603Z ERROR apollo_router: Failed to read schema: Could not read schema: Parsing error(s).

I think this can be refactored and then reviewed.

@o0Ignition0o o0Ignition0o marked this pull request as ready for review December 6, 2021 16:25
@o0Ignition0o o0Ignition0o added enhancement An enhancement to an existing feature size/medium labels Dec 6, 2021
apollo-router-core/src/error.rs Outdated Show resolved Hide resolved
apollo-router-core/src/error.rs Outdated Show resolved Hide resolved
apollo-router-core/src/error.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@cecton cecton left a comment

Choose a reason for hiding this comment

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

Awesomely simple 👏

@o0Ignition0o o0Ignition0o merged commit 87c88a6 into main Dec 8, 2021
@o0Ignition0o o0Ignition0o deleted the igni/schema_parse_errors_display branch December 8, 2021 12:32
o0Ignition0o added a commit that referenced this pull request Jan 11, 2022
# [v0.1.0-alpha.3] 2022-01-11

## 🚀🌒 Public alpha release

> An alpha or beta release is in volatile, active development. The release might not be feature-complete, and breaking API changes are possible between individual versions.

## ✨ Features

- Trace sampling [#228](#228): Tracing each request can be expensive. The router now supports sampling, which allows us to only send a fraction of the received requests.

- Health check [#54](#54)

## 🐛 Fixes

- Schema parse errors [#136](#136): The router wouldn't display what went wrong when parsing an invalid Schema. It now displays exactly where a the parsing error occurred, and why.

- Various tracing and telemetry fixes [#237](#237): The router wouldn't display what went wrong when parsing an invalid Schema. It now displays exactly where a the parsing error occurred, and why.

- Query variables validation [#62](#62): Now that we have a schema parsing feature, we can validate the variables and their types against the schemas and queries.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement An enhancement to an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Display schema parse errors
5 participants