Documentation ¶
Overview ¶
Package hierr provides a simple way to return and display hierarchical errors.
Transforms:
can't pull remote 'origin': can't run git fetch 'origin' 'refs/tokens/*:refs/tokens/*': exit status 128
Into:
can't pull remote 'origin' └─ can't run git fetch 'origin' 'refs/tokens/*:refs/tokens/*' └─ exit status 128
Index ¶
- Constants
- Variables
- func Context(node NestedError, description ...NestedError) error
- func Errorf(nestedError NestedError, message string, args ...interface{}) error
- func Fatalf(nestedError NestedError, message string, args ...interface{})
- func Push(topError NestedError, childError ...NestedError) error
- func String(object interface{}) string
- type Error
- type HierarchicalError
- type NestedError
Examples ¶
Constants ¶
const ( // BranchDelimiterASCII represents a simple ASCII delimiter for hierarchy // branches. // // Use: hierr.BranchDelimiter = hierr.BranchDelimiterASCII BranchDelimiterASCII = `\_ ` // BranchDelimiterBox represents UTF8 delimiter for hierarchy branches. // // Use: hierr.BranchDelimiter = hierr.BranchDelimiterBox BranchDelimiterBox = `└─ ` // BranchChainerASCII represents a simple ASCII chainer for hierarchy // branches. // // Use: hierr.BranchChainer = hierr.BranchChainerASCII BranchChainerASCII = `| ` // BranchChainerBox represents UTF8 chainer for hierarchy branches. // // Use: hierr.BranchChainer = hierr.BranchChainerBox BranchChainerBox = `│ ` // BranchSplitterASCII represents a simple ASCII splitter for hierarchy // branches. // // Use: hierr.BranchSplitter = hierr.BranchSplitterASCII BranchSplitterASCII = `+ ` // BranchSplitterBox represents UTF8 splitter for hierarchy branches. // // Use: hierr.BranchSplitter = hierr.BranchSplitterBox BranchSplitterBox = `├─ ` )
Variables ¶
var ( // BranchDelimiter set delimiter each nested error text will be started // from. BranchDelimiter = BranchDelimiterBox // BranchChainer set chainer each nested error tree text will be started // from. BranchChainer = BranchChainerBox // BranchSplitter set splitter each nested errors splitted by. BranchSplitter = BranchSplitterBox // BranchIndent set number of spaces each nested error will be indented by. BranchIndent = 3 )
Functions ¶
func Context ¶
func Context(node NestedError, description ...NestedError) error
Context adds context to specified top-level node.
Context can be passed to rest of the call to add multiple labels to given error:
hierr.Context( err, hierr.Context(`mailer`, `localhost:25`), hierr.Context(`config`, `/path/to/config.toml`), )
Example ¶
testcases := []error{ Context( Errorf( errors.New(`failed to parse int`), `no config field: %s`, `some_config_field`, ), Context(fmt.Sprintf(`config: %s`, `/path/to/config.yaml`)), ), Context( errors.New(`fatal error`), Context(`database`, `localhost:1234`), ), Context( Errorf( errors.New(`fatal error`), `some error occured`, ), Context(`database`, `localhost:1234`), Context(`node`, `node-a.localdomain`), ), } for _, test := range testcases { fmt.Println() fmt.Println("{{{") fmt.Println(test.Error()) fmt.Println("}}}") }
Output: {{{ no config field: some_config_field ├─ failed to parse int └─ config: /path/to/config.yaml }}} {{{ fatal error └─ database └─ localhost:1234 }}} {{{ some error occured ├─ fatal error │ ├─ database │ └─ localhost:1234 │ └─ node └─ node-a.localdomain }}}
func Errorf ¶
func Errorf( nestedError NestedError, message string, args ...interface{}, ) error
Errorf creates new hierarchy error.
With nestedError == nil call will be equal to `fmt.Errorf()`.
func Fatalf ¶
func Fatalf( nestedError NestedError, message string, args ...interface{}, )
Fatalf creates new hierarchy error, prints to stderr and exit 1
Have same semantics as `hierr.Errorf()`.
func Push ¶
func Push(topError NestedError, childError ...NestedError) error
Push creates new hierarchy error with multiple branches separated by separator, delimited by delimiter and prolongated by prolongator.
Example ¶
testcases := []error{ Push( "the godfather", Push( "son A", "A's son 1", Push( "A's son 2", Push("2' son X", Push("X's son @"), Push("X's son #"), ), ), ), Push("son B", errors.New("B's son 1"), errors.New("B's son 2"), Push("orphan"), ), Errorf( fmt.Sprintf("%s", "B's son 1"), "son B", ), errors.New("police"), ), } for _, test := range testcases { fmt.Println() fmt.Println("{{{") fmt.Println(test.Error()) fmt.Println("}}}") }
Output: {{{ the godfather ├─ son A │ ├─ A's son 1 │ │ │ └─ A's son 2 │ └─ 2' son X │ ├─ X's son @ │ └─ X's son # │ ├─ son B │ ├─ B's son 1 │ ├─ B's son 2 │ └─ orphan │ ├─ son B │ └─ B's son 1 │ └─ police }}}
Types ¶
type Error ¶
type Error struct { // Message is formatter error message, which will be reported when Error() // will be invoked. Message string // Nested error, which can be hierr.Error as well. Nested interface{} }
Error represents hierarchy error, linked with nested error.
Example ¶
testcases := []error{ Errorf(nil, ""), Errorf(nil, "simple error"), Errorf(nil, "integer: %d", 1), Errorf(errors.New("nested"), "top level"), Errorf(errors.New("nested"), "top level: %s", "formatting"), Errorf(Errorf(errors.New("low level"), "nested"), "top level"), Errorf(Errorf(fmt.Sprintf("%s", "string"), "nested"), "top level"), Errorf([]byte("byte"), "top level"), } for _, test := range testcases { fmt.Println() fmt.Println("{{{") fmt.Println(test.Error()) fmt.Println("}}}") } fmt.Println() exiter = func(code int) { fmt.Println("exit code:", code) } tempfile, err := ioutil.TempFile(os.TempDir(), "stderr") if err != nil { panic(err) } os.Stderr = tempfile Fatalf(fmt.Sprintf("%s", "wow"), "critical error") _, err = tempfile.Seek(0, 0) if err != nil { panic(err) } text, err := ioutil.ReadAll(tempfile) if err != nil { panic(err) } fmt.Println("stderr:\n" + string(text))
Output: {{{ }}} {{{ simple error }}} {{{ integer: 1 }}} {{{ top level └─ nested }}} {{{ top level: formatting └─ nested }}} {{{ top level └─ nested └─ low level }}} {{{ top level └─ nested └─ string }}} {{{ top level └─ byte }}} exit code: 1 stderr: critical error └─ wow
func (Error) Error ¶
Error returns string representation of hierarchical error. If no nested error was specified, then only current error message will be returned.
func (Error) GetMessage ¶
GetMessage returns top-level error message.
func (Error) GetNested ¶
func (err Error) GetNested() []NestedError
GetNested returns nested errors, embedded into error.
func (Error) HierarchicalError ¶
HierarchicalError returns pretty hierarchical rendering.
type HierarchicalError ¶
type HierarchicalError interface { // HierarchicalError returns hierarhical string representation. HierarchicalError() string // GetNested returns slice of nested errors. GetNested() []NestedError // GetMessage returns top-level error message. GetMessage() string }
HierarchicalError represents interface, which methods will be used instead of calling String() and Error() methods.
Example ¶
testcases := []error{ Errorf( Errorf( smartError{"smart", errors.New("hierarchical")}, "second", ), "top level", ), Errorf( Errorf( fmt.Sprintf( "%s", smartError{"smart plain", errors.New("error")}, ), "second", ), "top level", ), Push( smartError{"smart", errors.New("hierarchical")}, smartError{"smart", errors.New("hierarchical")}, ), Push( smartError{"smart", errors.New("hierarchical")}, Push( smartError{"smart", errors.New("hierarchical")}, smartError{"smart", errors.New("hierarchical")}, smartError{"smart", Errorf(fmt.Sprintf("%s", "nest"), "top")}, ), ), } for _, test := range testcases { fmt.Println() fmt.Println("{{{") fmt.Println(test.Error()) fmt.Println("}}}") }
Output: {{{ top level └─ second └─ smart └─ hierarchical }}} {{{ top level └─ second └─ {smart plain error} }}} {{{ smart └─ hierarchical └─ smart └─ hierarchical }}} {{{ smart └─ hierarchical └─ smart └─ hierarchical ├─ smart │ └─ hierarchical │ └─ smart └─ top └─ nest }}}