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  }