-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Conversation
solver/errdefs/errdefs.proto
Outdated
repeated string Cmdline = 2; | ||
string Checksum = 3; | ||
int32 Pid = 4; | ||
// go commit, frontend digest |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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>
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. |
Probably need to change some code around in follow-up. Next step would be to add this to |
@@ -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 { |
There was a problem hiding this comment.
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)), | ||
} |
There was a problem hiding this comment.
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!
There was a problem hiding this 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
api/services/control/errors.go
Outdated
grpc "google.golang.org/grpc" | ||
) | ||
|
||
func WrapServerErrors(srv ControlServer) ControlServer { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
util/stack/stack.go
Outdated
switch verb { | ||
case 'v': | ||
if s.Flag('+') { | ||
fmt.Fprintf(s, "%+v\n", w.Error()) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 +
util/stack/stack.go
Outdated
for _, f := range stack.Frames { | ||
fmt.Fprintf(s, "%s\n\t%s:%d\n", f.Name, f.File, f.Line) | ||
} | ||
fmt.Fprintf(s, "\n") |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤮
e0ceb12
to
704f544
Compare
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 | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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? :)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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
anderrors.Is/As
checks that should match supported error types fromerrdefs
package automatically.@AkihiroSuda @hinshun