...

Source file src/github.com/goph/emperror/stack.go

Documentation: github.com/goph/emperror

     1  package emperror
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/pkg/errors"
     8  )
     9  
    10  type stackTracer interface {
    11  	StackTrace() errors.StackTrace
    12  }
    13  
    14  // StackTrace returns the stack trace from an error (if any).
    15  func StackTrace(err error) (errors.StackTrace, bool) {
    16  	st, ok := getStackTracer(err)
    17  	if ok {
    18  		return st.StackTrace(), true
    19  	}
    20  
    21  	return nil, false
    22  }
    23  
    24  // getStackTracer returns the stack trace from an error (if any).
    25  func getStackTracer(err error) (stackTracer, bool) {
    26  	var st stackTracer
    27  
    28  	ForEachCause(err, func(err error) bool {
    29  		if s, ok := err.(stackTracer); ok {
    30  			st = s
    31  
    32  			return false
    33  		}
    34  
    35  		return true
    36  	})
    37  
    38  	return st, st != nil
    39  }
    40  
    41  type withStack struct {
    42  	err error
    43  	st  stackTracer
    44  }
    45  
    46  func (w *withStack) Error() string {
    47  	return w.err.Error()
    48  }
    49  
    50  func (w *withStack) Cause() error {
    51  	return w.err
    52  }
    53  
    54  func (w *withStack) StackTrace() errors.StackTrace {
    55  	return w.st.StackTrace()
    56  }
    57  
    58  // Format implements the fmt.Formatter interface.
    59  func (w *withStack) Format(s fmt.State, verb rune) {
    60  	switch verb {
    61  	case 'v':
    62  		if s.Flag('+') {
    63  			_, _ = fmt.Fprintf(s, "%+v", w.Cause())
    64  			return
    65  		}
    66  		fallthrough
    67  
    68  	case 's':
    69  		_, _ = io.WriteString(s, w.Error())
    70  
    71  	case 'q':
    72  		_, _ = fmt.Fprintf(s, "%q", w.Error())
    73  	}
    74  }
    75  
    76  // ExposeStackTrace exposes the stack trace (if any) in the outer error.
    77  func ExposeStackTrace(err error) error {
    78  	if err == nil {
    79  		return err
    80  	}
    81  
    82  	st, ok := getStackTracer(err)
    83  	if !ok {
    84  		return err
    85  	}
    86  
    87  	return &withStack{
    88  		err: err,
    89  		st:  st,
    90  	}
    91  }
    92  

View as plain text