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 }}}