forked from creasty/apperrors
-
Notifications
You must be signed in to change notification settings - Fork 1
/
error.go
121 lines (103 loc) · 2.82 KB
/
error.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package fail
import (
"errors"
"fmt"
"strings"
)
const (
messageDelimiter = ": "
)
// Error is an error that has contextual metadata
type Error struct {
// Err is the original error (you might call it the root cause)
Err error
// Messages is an annotated description of the error
Messages []string
// Code is a status code that is desired to be contained in responses, such as HTTP Status code.
Code interface{}
// Ignorable represents whether the error should be reported to administrators
Ignorable bool
// Tags represents tags of the error which is classified errors.
Tags []string
// Params is an annotated parameters of the error.
Params H
// StackTrace is a stack trace of the original error
// from the point where it was created
StackTrace StackTrace
}
// New returns an error that formats as the given text.
// It also records the stack trace at the point it was called.
func New(text string) error {
err := &Error{Err: errors.New(text)}
withStackTrace(0)(err)
return err
}
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
// It also records the stack trace at the point it was called.
func Errorf(format string, args ...interface{}) error {
err := &Error{Err: fmt.Errorf(format, args...)}
withStackTrace(0)(err)
return err
}
// Error implements error interface.
// It returns a string of messages and the root error concatenated with ": ".
func (e *Error) Error() string {
messages := append(e.Messages, e.Err.Error())
return strings.Join(messages, messageDelimiter)
}
// Copy creates a copy of the current object
func (e *Error) Copy() *Error {
return &Error{
Err: e.Err,
Messages: e.Messages,
Code: e.Code,
Ignorable: e.Ignorable,
Tags: e.Tags,
Params: e.Params,
StackTrace: e.StackTrace,
}
}
// LastMessage returns the last message
func (e *Error) LastMessage() string {
if len(e.Messages) == 0 {
return ""
}
return e.Messages[0]
}
// Unwrap provides compatibility for Go 1.13 error chains.
func (e *Error) Unwrap() error { return e.Err }
// Wrap returns an error annotated with a stack trace from the point it was called,
// and with the specified annotators.
// It returns nil if err is nil.
func Wrap(err error, annotators ...Annotator) error {
if err == nil {
return nil
}
failErr := Unwrap(err)
if failErr == nil {
failErr = &Error{
Err: err,
}
}
withStackTrace(0)(failErr)
for _, f := range annotators {
f(failErr)
}
return failErr
}
// Unwrap extracts an underlying *fail.Error from an error.
// If the given error isn't eligible for retriving context from,
// it returns nil
func Unwrap(err error) *Error {
if err == nil {
return nil
}
if failErr, ok := err.(*Error); ok {
return failErr.Copy()
}
if failErr := convertPkgError(err); failErr != nil {
return failErr
}
return nil
}