Skip to content
This repository has been archived by the owner on Feb 24, 2020. It is now read-only.

Make errors structured #1937

Merged
merged 16 commits into from Jan 28, 2016
Merged

Conversation

blixtra
Copy link
Collaborator

@blixtra blixtra commented Jan 6, 2016

This PR is intended to get feedback on the general approach.

Up to now errors in rkt have been a concatenated string. This often
ended with the user being presented with a very long, hard to decipher
error message. Furthermore, sometimes the message was prefixed with the
name of the command, sometimes not. In essencce, errors messages were
inconsistent and confusing.

This patch introduces structured error messages using the errwrap
package. The goal is to have errors be useful & consistant, and have a
single location (common/errors.go) where we can modify the error output.

The common/errors.go provides a type called ErrorSanitizer that manages
error output. It is set up in the cobra.Command's PresisentPreRun func
so that each subcommand is able to initialize errOut with the
evaluated --debug flag. This also allows each subcommand to set the
prefix appropriately. It uses the --debug flag to decide whether to show
just the inner-most error or all errors. The format of the error with
--debug=false is...

cat-manifest: problem retrieving pod
└─no matches found for "asdfasdf"

With --debug=true the output show all the errors.

cat-manifest: problem retrieving pod
└─unable to resolve UUID
  └─no matches found for "asdfasdf"

In this case only one more but some errors are 5 or more deep. See
#1550 for an example.

This change does not change messages that are simply printing
a message to stderr. These still use the stderr function.

This change only handles errors but it may be useful to make
ErrorSanitizer a more general "output" type that handles all output to
console in a central place.

I think the ErrorSanitizer methods Print and Error could be better named. Also I'm thinking it may be better to have the error message only be on one line when --debug is false. For example, the one line output could be...

cat-manifest: problem retrieving pod: no matches found for "asdfasdf"

and the --debug=true output could be...

cat-manifest: problem retrieving pod: no matches found for "asdfasdf"
└─unable to resolve UUID
  └─no matches found for "asdfasdf"

This PR will intend to fix #1550 and #1754.

Note: This will not pass the tests because the tests parse error output and I've not yet updated those.

@@ -105,6 +111,11 @@ func init() {
cmdRkt.PersistentFlags().BoolVar(&globalFlags.TrustKeysFromHttps, "trust-keys-from-https",
true, "automatically trust gpg keys fetched from https")

// Run this before the execution of each subcommand to set up output
cmdRkt.PersistentPreRun = func(cmd *cobra.Command, args []string) {
errOut = common.NewErrorSanitizer(os.Stderr, cmd.Name(), globalFlags.Debug)
Copy link
Member

Choose a reason for hiding this comment

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

common.NewErrorSanitizer is only called in the rkt binary but not in stage1's binaries (init or gc). How does it print the errors when the errors are not generated from the rkt binary?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

right. We need to separate the idea of making the errors structured and outputting the errors. For stage1 binaries, the errors have now been structured but I haven't dealt with output part yet. A large majority, if not all, of the output for stage1 goes to log.

Currently the wrapped errors will only show the outer most message. Will probable need to change that.

@alban alban added this to the v0.16.0 milestone Jan 7, 2016
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/hashicorp/errwrap"
)

// ErrorSanitizer is designed to handle
Copy link
Contributor

Choose a reason for hiding this comment

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

designed to handle ...

@blixtra
Copy link
Collaborator Author

blixtra commented Jan 20, 2016

This is close to the final PR. Need to fix the tests now.

@blixtra blixtra changed the title Make errors structured [DO NOT MERGE] Make errors structured Jan 20, 2016
@blixtra
Copy link
Collaborator Author

blixtra commented Jan 20, 2016

Please review. I'm currently working on getting the tests to past but the main code is pretty much where I want it.

@@ -16,7 +16,10 @@

package fileutil

import "syscall"
import (
"os"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice catch!

@@ -151,7 +153,7 @@ func verifyFailure(shouldFail bool, contents string, err error) error {
var vErr error = nil
if err != nil {
if !shouldFail {
vErr = fmt.Errorf("Expected test to succeed, failed unexpectedly (contents: `%s`): %v", contents, err)
vErr = errwrap.Wrapf(fmt.Sprintf("Expected test to succeed, failed unexpectedly (contents: `%s`): {{err}}", contents), err)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure if there is a point in using errwrap in unit tests.

@@ -134,7 +135,7 @@ func (s *Store) populateSize() error {
return err
})
if err != nil {
return fmt.Errorf("populateSize(): error retrieving ACI Infos: %v", err)
return errwrap.Wrap(errors.New("populateSize(): error retrieving ACI Infos"), err)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd remove that populateSize(): prefix.

@krnowak
Copy link
Collaborator

krnowak commented Jan 27, 2016

About stderr in rkt/pubkey and rkt/image packages - I suggest forwarding the logger from the users of those packages, that is - make *rktlog.Logger a member of pubkey.Manager and image.action structs. I guess that this member will need to be added to other fetchers as well.

@iaguis
Copy link
Member

iaguis commented Jan 28, 2016

There're some panic()s that are not changed to PanicE()s but I don't thing this is a blocker.

@iaguis
Copy link
Member

iaguis commented Jan 28, 2016

Missing wrapping: https://github.com/coreos/rkt/blob/dc837ae7fe6f36552cf3bcde7b938f307361c7d2/stage1/common/run.go

We should document this new way of handling errors (for example, in hacking.md) so developers use it.

@iaguis
Copy link
Member

iaguis commented Jan 28, 2016

Otherwise, LGTM.

I'm sure we're missing some things but we'll fix them eventually.

@blixtra blixtra force-pushed the blixtra/make-errors-structured branch 2 times, most recently from 9d25ed6 to f028b20 Compare January 28, 2016 16:04
errwrap provides a means of structuring error messages.
Up to now errors in rkt have been a concatenated string. This often
ended with the user being presented with a very long, hard to decipher
error message. Furthermore, sometimes the message was prefixed with the
name of the command, sometimes not. In essencce, errors messages were
inconsistent and confusing.

This patch introduces structured error messages using the errwrap
package. The goal is to have errors be useful & consistant, and have a
single location (common/errors.go) where we can modify the error output.

Errors are stored as an inner and outer errors. We do this by nesting
errors using errwrap.Wrap. With this structure we have much more control
over how we can display errors.
This change creates a new type, Logger, that wraps go's own Logger type
to provide consistent output across go commands. Along with the methods
from go's log package, there are also methods that accept our structured
error type introduced in the previous commit. These commands append an
'E' to the end of the familiar methods. For example, we now have
'PrintE', 'PanicE', & 'FatalE'.

With this, we have one, central location to modify the way output is displayed in
rkt.

The output generated when printing errors is:

```
cat-manifest: problem retrieving pod: no matches found for "asf"
```

or when using the `--debug` flag we'll get the entire error stack.

```
cat-manifest: problem retrieving pod
  └─unable to resolve UUID
    └─no matches found for "asf"
```

From this example we can see that when no `--debug` flag is used, you
get the innermost error as the last output on the line. All other errors
are hidden. This text between the 'command name' is the programmer
defined message that accompanies the errors sent to output. This can be
left empty.

When using the `--debug` flag we only get the 'command name' and
accompanying message on the first line. Under that we get the unwound
error messages, with the innermost one at the bottom.

Furthermore, all output to stderr has a prefix that is either
programatically set using the command or subsommand name, or one set in
the package.

refs: rkt#1550
fixes: rkt#1754
This makes casing for diagnostic and error messages consistent across
rkt.
With the changes in error and diagnostic tests, some strings needed to
be updated.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bad error message when dependences imageID does not match
5 participants