github.com/mongodb/grip@v0.0.0-20240213223901-f906268d82b9/message/error.go (about) 1 // Error Messages 2 // 3 // The error message composers underpin the Catch<> logging messages, 4 // which allow you to log error messages but let the logging system 5 // elide logging for nil errors. 6 package message 7 8 import ( 9 "fmt" 10 "io" 11 12 "github.com/mongodb/grip/level" 13 "github.com/pkg/errors" 14 ) 15 16 type errorMessage struct { 17 ErrorValue string `bson:"error" json:"error" yaml:"error"` 18 Extended string `bson:"extended,omitempty" json:"extended,omitempty" yaml:"extended,omitempty"` 19 Base `bson:"metadata" json:"metadata" yaml:"metadata"` 20 err error 21 includeExtendedMetadata bool 22 } 23 24 // NewErrorMessage takes an error object and returns an ErrorComposer instance 25 // that only renders a loggable message when the error is non-nil. 26 // 27 // These composers also implement the error interface and the pkg/errors.Causer 28 // interface and so can be passed as errors and used with existing 29 // error-wrapping mechanisms. 30 func NewErrorMessage(p level.Priority, err error) ErrorComposer { 31 m := &errorMessage{ 32 err: err, 33 } 34 _ = m.SetPriority(p) 35 return m 36 } 37 38 // NewError returns an ErrorComposer, like NewErrorMessage, but 39 // without the requirement to specify priority, which you may wish to 40 // specify directly. 41 func NewError(err error) ErrorComposer { 42 return &errorMessage{ 43 err: err, 44 } 45 } 46 47 // NewExtendedErrorMessage is like NewErrorMessage, but also collects extended 48 // logging metadata. 49 func NewExtendedErrorMessage(p level.Priority, err error) ErrorComposer { 50 m := &errorMessage{ 51 err: err, 52 includeExtendedMetadata: true, 53 } 54 _ = m.SetPriority(p) 55 return m 56 } 57 58 // NewExtendedError is like NewError, but also collects extended logging 59 // metadata. 60 func NewExtendedError(err error) ErrorComposer { 61 return &errorMessage{ 62 err: err, 63 includeExtendedMetadata: true, 64 } 65 } 66 67 func (e *errorMessage) String() string { 68 if e.err == nil { 69 return "" 70 } 71 e.ErrorValue = e.err.Error() 72 return e.ErrorValue 73 } 74 75 func (e *errorMessage) Loggable() bool { 76 return e.err != nil 77 } 78 79 func (e *errorMessage) Raw() interface{} { 80 _ = e.Collect(e.includeExtendedMetadata) 81 _ = e.String() 82 83 extended := fmt.Sprintf("%+v", e.err) 84 if extended != e.ErrorValue { 85 e.Extended = extended 86 } 87 88 return e 89 } 90 91 func (e *errorMessage) Error() string { return e.String() } 92 func (e *errorMessage) Cause() error { return e.err } 93 func (e *errorMessage) Format(s fmt.State, verb rune) { 94 switch verb { 95 case 'v': 96 if s.Flag('+') { 97 fmt.Fprintf(s, "%+v\n", errors.Cause(e.err)) 98 _, _ = io.WriteString(s, e.String()) 99 return 100 } 101 fallthrough 102 case 's', 'q': 103 _, _ = io.WriteString(s, e.Error()) 104 } 105 }