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

Formatting: Simple multi-error format #74

Open
abhinav opened this issue Dec 11, 2023 · 3 comments
Open

Formatting: Simple multi-error format #74

abhinav opened this issue Dec 11, 2023 · 3 comments

Comments

@abhinav
Copy link
Contributor

abhinav commented Dec 11, 2023

The tree output format should be opt-in, and we should default to just empty-line-separated leaf errors.
For leaf errors, multi-error parent just provides an additional piece of the error trace, so there will be some repetition of frames between those errors.

This also ties into #71: we can expose a simple iterator func(error, []frame) with the understanding that parent/child relationships don't need to be exposed.

@prashantv
Copy link
Contributor

+1 on formatting customization options.

I'd also like to experiment with an option to deduplicate the error messages in the tree for common uses of errors.Join.

@abhinav
Copy link
Contributor Author

abhinav commented May 4, 2024

So here's my thinking:
Tree representation is not actually useful.
Nobody wants an ASCII error representation in their error output.
They either want structured information (which is now possible with #102),
or they want simple readable output.

I propose that we change Format and FormatString to do empty-line-separated errors for multi-errors.
So the trace for a single error chain is:

error message

path/to/package.Func
        path/to/file.go:42
path/to/package.Func
        path/to/file.go:42
...

And the trace for a multi-error is:

error message 1

path/to/package.Func
        path/to/file.go:42
path/to/package.Func
        path/to/file.go:42
...

error message 2

path/to/package.Func
        path/to/file.go:42
path/to/package.Func
        path/to/file.go:42
...

...

This matches the simplicity of errors.Join, which does newline-separated messages.
Anything more customizable can be done with UnwrapFrame directly.

If anyone actually finds the tree functionality useful, we can put it in a FormatTree function.

Thoughts?

Edit: Update:
Tried it out. The output doesn't look good if we also print the multi-error.
You end up with:

err 1
err 2
err 3

err 1

path/to/package.Func
        path/to/file.go:42
path/to/package.Func
        path/to/file.go:42

err 2

path/to/package.Func
        path/to/file.go:42
path/to/package.Func
        path/to/file.go:42

err 3

path/to/package.Func
        path/to/file.go:42
path/to/package.Func
        path/to/file.go:42

The above case looks better if we don't print the multi-error itself (which makes sense since we're traversing its children), but it loses information if there was a trace leading up to the multi-error.

@abhinav
Copy link
Contributor Author

abhinav commented May 4, 2024

Example from playing around:

Flat:

std err 1
std err 2
std err 3
std err 4

braces.dev/errtrace_test.Example_tree
        /path/to/errtrace/example_tree_test.go:2

std err 1

std err 2

braces.dev/errtrace_test.wrapNormalErr
        /path/to/errtrace/example_tree_test.go:1

std err 3

std err 4

braces.dev/errtrace_test.wrapNormalErr
        /path/to/errtrace/example_tree_test.go:1

Tree:

+- std err 1
|
+- std err 2
|
|  braces.dev/errtrace_test.wrapNormalErr
|       /path/to/errtrace/example_tree_test.go:1
|
|  +- std err 3
|  |
|  +- std err 4
|  |
|  |  braces.dev/errtrace_test.wrapNormalErr
|  |    /path/to/errtrace/example_tree_test.go:1
|  |
+- std err 3
|  std err 4
|
std err 1
std err 2
std err 3
std err 4

braces.dev/errtrace_test.Example_tree
        /path/to/errtrace/example_tree_test.go:2

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

No branches or pull requests

2 participants