github.com/mongodb/grip@v0.0.0-20240213223901-f906268d82b9/slogger/stack_error.go (about) 1 package slogger 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/mongodb/grip/message" 8 ) 9 10 // StackError is a grip re implementation of a type from legacy 11 // slogger. It combines a stacktrace of the call site of the logged 12 // message and a message composer. StackError also implements the 13 // error interface. The composer's "loggability" is derived from the 14 // embedded composer. 15 type StackError struct { 16 message.Composer 17 Stacktrace []string 18 message string 19 } 20 21 // NewStackError produces a StackError object, collecting the 22 // stacktrace and building a Formatted message composer 23 // (e.g. fmt.Sprintf). 24 func NewStackError(messageFmt string, args ...interface{}) *StackError { 25 return &StackError{ 26 Composer: message.NewFormatted(messageFmt, args...), 27 Stacktrace: stacktrace(), 28 } 29 } 30 31 // Raw produces a structure that contains the mesage, stacktrace, and 32 // raw metadata from the embedded composer for use by some logging 33 // backends. 34 func (s *StackError) Raw() interface{} { 35 return &struct { 36 Message string `bson:"message" json:"message" yaml:"message"` 37 Stacktrace []string `bson:"stacktrace" json:"stacktrace" yaml:"stacktrace"` 38 Metadata interface{} `bson:"metadata" json:"metadata" yaml:"metadata"` 39 }{ 40 Message: s.Composer.String(), 41 Stacktrace: s.Stacktrace, 42 Metadata: s.Composer.Raw(), 43 } 44 } 45 46 // Error returns the resolved error message for the StackError 47 // instance and satisfies the error interface. 48 func (s *StackError) Error() string { return s.String() } 49 50 // String lazily resolves a message for the instance and caches that 51 // message internally. 52 func (s *StackError) String() string { 53 if s.message != "" { 54 return s.message 55 } 56 57 s.message = fmt.Sprintf("%s\n\t%s", 58 s.Composer.String(), 59 strings.Join(s.Stacktrace, "\n\t")) 60 61 return s.message 62 }