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

errdefs: add support for typed errors #1454

Merged
merged 12 commits into from
Apr 27, 2020
Merged

Conversation

tonistiigi
Copy link
Member

@tonistiigi tonistiigi commented Apr 21, 2020

Add support for typed errors that are maintained through components and rpc calls.

As a first example, error from the client side also contains stack traces from the daemon side components.

Users shouldn't care about the grpc errors handling. Just use regular errors.Wrap and errors.Is/As checks that should match supported error types from errdefs package automatically.

@AkihiroSuda @hinshun

solver/errdefs/stack.go Outdated Show resolved Hide resolved
repeated string Cmdline = 2;
string Checksum = 3;
int32 Pid = 4;
// go commit, frontend digest
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is the intention here to eventually support propagating errors.WithStack from within frontends?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. You can look at https://gist.github.com/tonistiigi/3f3cfcf274f5dde5b7cb69f44f44ed84 for an example. That trace contains stacks from buildctl, buildkitd and two dockerfile containers (one that does the build and other that forwards #syntax). Bit verbose because of pkg/errors#75 but we're not going to show this part to users by default anyway.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Awesome, this is really useful.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
@tonistiigi tonistiigi marked this pull request as ready for review April 22, 2020 05:58
@tonistiigi
Copy link
Member Author

Vertex and source support added in addition to stack support. I'll continue adding more but this should be enough to review for the first PR.

@tonistiigi
Copy link
Member Author

Probably need to change some code around in follow-up. Next step would be to add this to fsutil transfer errors, but that would require a backlinked dependency.

@@ -130,7 +132,7 @@ func (e *parseError) Error() string {
return fmt.Sprintf("dockerfile parse error line %d: %v", e.node.StartLine, e.inner.Error())
}

func (e *parseError) Unwarp() error {
Copy link
Member Author

Choose a reason for hiding this comment

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

🙈

Filename: filename,
Local: local,
Locations: make([]*errdefs.Range, 0, len(locations)),
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is... source mapping? Wow!

Copy link
Collaborator

@hinshun hinshun left a comment

Choose a reason for hiding this comment

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

PR currently failing with:

#13 5.205 The result of "go generate" differs
#13 5.205 
#13 5.205  M solver/errdefs/errdefs.pb.go
#13 5.205 
#13 5.205 Please update with "make generated-files"

@@ -53,6 +54,7 @@ type state struct {

vtx Vertex
clientVertex client.Vertex
origDigest digest.Digest // original LLB digest. TODO: probably better to use string ID so this isn't needed
Copy link
Collaborator

Choose a reason for hiding this comment

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

TODO will be done in another PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is a solver internals change that I don't want to do atm.

grpc "google.golang.org/grpc"
)

func WrapServerErrors(srv ControlServer) ControlServer {
Copy link
Member Author

Choose a reason for hiding this comment

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

maybe I should do grpc.StreamInterceptor grpc.UnaryInterceptor instead. Not much cleaner and need to merge with existing ones. But no changes required on new API endpoints.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This reverts commit 3f77f04.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
}
st, ok := status.FromError(err)
if !ok {
return err
Copy link
Collaborator

Choose a reason for hiding this comment

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

when would you do FromGRPC(notAGRPCError{})? Maybe do (error, bool) like status.FromError.

Copy link
Member Author

Choose a reason for hiding this comment

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

this doesn't return any extra info/type so I don't think bool is needed and just complicated the caller side

switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v\n", w.Error())
Copy link
Collaborator

@tiborvass tiborvass Apr 23, 2020

Choose a reason for hiding this comment

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

w.Error() always returns a string, so no need for %+v afaict, could be %s which is less confusing (I thought there would be some kind of recursion due to %+v like it is the case in pkg/errors. If there is any recursion it will be in the Error() method itself.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this basically should be io.WriteString(s, w.Error()) like when it woudl fallthrough if not +

for _, f := range stack.Frames {
fmt.Fprintf(s, "%s\n\t%s:%d\n", f.Name, f.File, f.Line)
}
fmt.Fprintf(s, "\n")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Fprintln

func convertStack(s errors.StackTrace) *Stack {
var out Stack
for _, f := range s {
dt, err := f.MarshalText()
Copy link
Collaborator

Choose a reason for hiding this comment

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

🤮

@tonistiigi tonistiigi force-pushed the errdefs branch 2 times, most recently from e0ceb12 to 704f544 Compare April 23, 2020 02:20
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
type Range struct {
Start Position
End Position
}

// Position is a point in source code
type Position struct {
Line int
Character int
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This maps directly to LSP: https://github.com/sourcegraph/go-lsp/blob/4631ffd93a18dc7dd940f937be13589f6ff79826/structures.go#L5-L40

I think at some point we can build a frontend from an IDE and see diagonistics there directly via LSP.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is where I took it so it would be compatible. Now, who is up to rewriting the Dockerfile parser to LSP? :)

Copy link
Collaborator

@hinshun hinshun Apr 24, 2020

Choose a reason for hiding this comment

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

I think a better solution is to write a generic frontend integration for LSP error diagnosis. I think they call it "code actions"? In order to run frontends, diagnose errors, or even a LLB debugger (That's shareable between frontends). You can supplement that with frontend-specific implementations like jump definition, autocomplete, semantic highlighting for Dockerfile.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, the errors come from LLB level and using VertexError (and probably typed error for every op type in future) here can be mapped to source but to be useful for the user they need to be mapped to original source code.

@tiborvass tiborvass merged commit 1088921 into moby:master Apr 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants