-
Notifications
You must be signed in to change notification settings - Fork 65
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
Upgrade to go 1.20 and add multi-cause error support #121
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Go 1.20 introduces the idea of an error with multiple causes instead of a single chain. This commit updates the errors library to properly encode, decode, and format these error types. For encoding and decoding we use the existing `EncodedLeaf` type and embellish it with a `causes` field. This is done in order to keep the encoding/decoding backwards compatible. `EncodedLeaf` types containing multiple causes when decided by earlier versions will simply see an opaque leaf with a message inside. The reason the `EncodedWrapper` is not used here is because the wrapper already contains a mandatory single `cause` field that we cannot fill with the multi-errors. A new type cannot be used because it would not be decodable by older versions of this library.
support multi-cause errors in go 1.20
Previously, error formatting logic was based on a single linear chain of causality. Error causes would be printed vertically down the page, and their interpretation was natural. This commit adds multi-cause formatting support with two goals in mind: 1. Preserve output exactly as before for single-cause error chains 2. Format multi-errors in a way that preserves the existing vertical layout style. For non-verbose error display (`.Error()`, `%s`, `%v`) there are no changes implemented here. We rely on the error's own display logic and typically a multi-cause error will have a message within that has been constructed from all of its causes during instantiation. For verbose error display (`%+v`) which relies on object introspection, whenever we encounter a multi-cause error in the chain, we mark that subtree as being displayed with markers for the "depth" of various causes. All child errors of the parent, will be at depth "1", their child errors will be at depth "2", etc. During display, we indent the error by its "depth" and add a `└─` symbol to illustrate the parent/child relationship. Example: Printing the error produced by this construction using the format directive `%+v` ``` fmt.Errorf( "prefix1: %w", fmt.Errorf( "prefix2 %w", goErr.Join( fmt.Errorf("a%w", fmt.Errorf("b%w", fmt.Errorf("c%w", goErr.New("d")))), fmt.Errorf("e%w", fmt.Errorf("f%w", fmt.Errorf("g%w", goErr.New("h")))), ))) ``` Produces the following output: ``` prefix1: prefix2: abcd (1) prefix1 Wraps: (2) prefix2 Wraps: (3) abcd | efgh └─ Wraps: (4) efgh └─ Wraps: (5) fgh └─ Wraps: (6) gh └─ Wraps: (7) h └─ Wraps: (8) abcd └─ Wraps: (9) bcd └─ Wraps: (10) cd └─ Wraps: (11) d Error types: (1) *fmt.wrapError (2) *fmt.wrapError (3) *errors.joinError (4) *fmt.wrapError (5) *fmt.wrapError (6) *fmt.wrapError (7) *errors.errorString (8) *fmt.wrapError (9) *fmt.wrapError (10) *fmt.wrapError (11) *errors.errorString`, ``` Note the following properties of the output: * The top-level single cause chain maintains the left-aligned `Wrap` lines which contain each cause one at a time. * As soon as we hit the multi-cause errors within the `joinError` struct (`(3)`), we add new indentation to show that The child errors of `(3)` are `(4)` and `(8)` * Subsequent causes of errors after `joinError`, are also indented to disambiguate the causal chain * The `Error types` section at the bottom remains the same and the numbering of the types can be matched to the errors above using the integers next to the `Wrap` lines. * No special effort has been made to number the errors in a way that describes the causal chain or tree. This keeps it easy to match up the error to its type descriptor.
Previous support for multi-cause encode/decode functionality, did not include support for custom encoder and decoder logic. This commits adds the ability to register encoders and decoders for multi-cause errors to encode custom types unknown to this library.
add formatting for multi-cause errors
This commit introduces a drop-in replacement of the go errors lib `Join` method which constructs a simple multi-cause error object. Some simple unit tests are added and `Join` wrappers are also integrated into the datadriven formatting test. Our existing format code for multi-cause errors is compatible with this new type which allows us to remove the custom formatter from the implementation. The public Join API contains wrappers that automatically attach stacktraces to the join errors. Signed-off-by: Steve Coffman <[email protected]>
Add Go 1.20 errors.Join support
This commit modifies the causal detail collection code in `report.go` to recurse through both the single-cause chain and the multi-cause chain if applicable when collecting information for the Sentry report.
Add multi-cause unwrap into Sentry reporting
update README with new public API changes
knz
approved these changes
Aug 23, 2023
knz
reviewed
Aug 23, 2023
.github/workflows/ci.yaml
Outdated
@@ -2,9 +2,9 @@ name: Go | |||
|
|||
on: | |||
push: | |||
branches: [ master ] | |||
branches: [ master, go-1.20-upgrade ] | |||
pull_request: |
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 guess this can change here too.
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.
Done.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This work was done separately on the
go-1.20-upgrade
branch and reviewed in:#113
#115
#118
#119
#120
This change is