mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 10:18:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			218 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package errors provides errors that have stack-traces.
 | |
| //
 | |
| // This is particularly useful when you want to understand the
 | |
| // state of execution when an error was returned unexpectedly.
 | |
| //
 | |
| // It provides the type *Error which implements the standard
 | |
| // golang error interface, so you can use this library interchangably
 | |
| // with code that is expecting a normal error return.
 | |
| //
 | |
| // For example:
 | |
| //
 | |
| //  package crashy
 | |
| //
 | |
| //  import "github.com/go-errors/errors"
 | |
| //
 | |
| //  var Crashed = errors.Errorf("oh dear")
 | |
| //
 | |
| //  func Crash() error {
 | |
| //      return errors.New(Crashed)
 | |
| //  }
 | |
| //
 | |
| // This can be called as follows:
 | |
| //
 | |
| //  package main
 | |
| //
 | |
| //  import (
 | |
| //      "crashy"
 | |
| //      "fmt"
 | |
| //      "github.com/go-errors/errors"
 | |
| //  )
 | |
| //
 | |
| //  func main() {
 | |
| //      err := crashy.Crash()
 | |
| //      if err != nil {
 | |
| //          if errors.Is(err, crashy.Crashed) {
 | |
| //              fmt.Println(err.(*errors.Error).ErrorStack())
 | |
| //          } else {
 | |
| //              panic(err)
 | |
| //          }
 | |
| //      }
 | |
| //  }
 | |
| //
 | |
| // This package was original written to allow reporting to Bugsnag,
 | |
| // but after I found similar packages by Facebook and Dropbox, it
 | |
| // was moved to one canonical location so everyone can benefit.
 | |
| package errors
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"runtime"
 | |
| )
 | |
| 
 | |
| // The maximum number of stackframes on any error.
 | |
| var MaxStackDepth = 50
 | |
| 
 | |
| // Error is an error with an attached stacktrace. It can be used
 | |
| // wherever the builtin error interface is expected.
 | |
| type Error struct {
 | |
| 	Err    error
 | |
| 	stack  []uintptr
 | |
| 	frames []StackFrame
 | |
| 	prefix string
 | |
| }
 | |
| 
 | |
| // New makes an Error from the given value. If that value is already an
 | |
| // error then it will be used directly, if not, it will be passed to
 | |
| // fmt.Errorf("%v"). The stacktrace will point to the line of code that
 | |
| // called New.
 | |
| func New(e interface{}) *Error {
 | |
| 	var err error
 | |
| 
 | |
| 	switch e := e.(type) {
 | |
| 	case error:
 | |
| 		err = e
 | |
| 	default:
 | |
| 		err = fmt.Errorf("%v", e)
 | |
| 	}
 | |
| 
 | |
| 	stack := make([]uintptr, MaxStackDepth)
 | |
| 	length := runtime.Callers(2, stack[:])
 | |
| 	return &Error{
 | |
| 		Err:   err,
 | |
| 		stack: stack[:length],
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Wrap makes an Error from the given value. If that value is already an
 | |
| // error then it will be used directly, if not, it will be passed to
 | |
| // fmt.Errorf("%v"). The skip parameter indicates how far up the stack
 | |
| // to start the stacktrace. 0 is from the current call, 1 from its caller, etc.
 | |
| func Wrap(e interface{}, skip int) *Error {
 | |
| 	var err error
 | |
| 
 | |
| 	switch e := e.(type) {
 | |
| 	case *Error:
 | |
| 		return e
 | |
| 	case error:
 | |
| 		err = e
 | |
| 	default:
 | |
| 		err = fmt.Errorf("%v", e)
 | |
| 	}
 | |
| 
 | |
| 	stack := make([]uintptr, MaxStackDepth)
 | |
| 	length := runtime.Callers(2+skip, stack[:])
 | |
| 	return &Error{
 | |
| 		Err:   err,
 | |
| 		stack: stack[:length],
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // WrapPrefix makes an Error from the given value. If that value is already an
 | |
| // error then it will be used directly, if not, it will be passed to
 | |
| // fmt.Errorf("%v"). The prefix parameter is used to add a prefix to the
 | |
| // error message when calling Error(). The skip parameter indicates how far
 | |
| // up the stack to start the stacktrace. 0 is from the current call,
 | |
| // 1 from its caller, etc.
 | |
| func WrapPrefix(e interface{}, prefix string, skip int) *Error {
 | |
| 
 | |
| 	err := Wrap(e, 1+skip)
 | |
| 
 | |
| 	if err.prefix != "" {
 | |
| 		prefix = fmt.Sprintf("%s: %s", prefix, err.prefix)
 | |
| 	}
 | |
| 
 | |
| 	return &Error{
 | |
| 		Err:    err.Err,
 | |
| 		stack:  err.stack,
 | |
| 		prefix: prefix,
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| // Is detects whether the error is equal to a given error. Errors
 | |
| // are considered equal by this function if they are the same object,
 | |
| // or if they both contain the same error inside an errors.Error.
 | |
| func Is(e error, original error) bool {
 | |
| 
 | |
| 	if e == original {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	if e, ok := e.(*Error); ok {
 | |
| 		return Is(e.Err, original)
 | |
| 	}
 | |
| 
 | |
| 	if original, ok := original.(*Error); ok {
 | |
| 		return Is(e, original.Err)
 | |
| 	}
 | |
| 
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // Errorf creates a new error with the given message. You can use it
 | |
| // as a drop-in replacement for fmt.Errorf() to provide descriptive
 | |
| // errors in return values.
 | |
| func Errorf(format string, a ...interface{}) *Error {
 | |
| 	return Wrap(fmt.Errorf(format, a...), 1)
 | |
| }
 | |
| 
 | |
| // Error returns the underlying error's message.
 | |
| func (err *Error) Error() string {
 | |
| 
 | |
| 	msg := err.Err.Error()
 | |
| 	if err.prefix != "" {
 | |
| 		msg = fmt.Sprintf("%s: %s", err.prefix, msg)
 | |
| 	}
 | |
| 
 | |
| 	return msg
 | |
| }
 | |
| 
 | |
| // Stack returns the callstack formatted the same way that go does
 | |
| // in runtime/debug.Stack()
 | |
| func (err *Error) Stack() []byte {
 | |
| 	buf := bytes.Buffer{}
 | |
| 
 | |
| 	for _, frame := range err.StackFrames() {
 | |
| 		buf.WriteString(frame.String())
 | |
| 	}
 | |
| 
 | |
| 	return buf.Bytes()
 | |
| }
 | |
| 
 | |
| // Callers satisfies the bugsnag ErrorWithCallerS() interface
 | |
| // so that the stack can be read out.
 | |
| func (err *Error) Callers() []uintptr {
 | |
| 	return err.stack
 | |
| }
 | |
| 
 | |
| // ErrorStack returns a string that contains both the
 | |
| // error message and the callstack.
 | |
| func (err *Error) ErrorStack() string {
 | |
| 	return err.TypeName() + " " + err.Error() + "\n" + string(err.Stack())
 | |
| }
 | |
| 
 | |
| // StackFrames returns an array of frames containing information about the
 | |
| // stack.
 | |
| func (err *Error) StackFrames() []StackFrame {
 | |
| 	if err.frames == nil {
 | |
| 		err.frames = make([]StackFrame, len(err.stack))
 | |
| 
 | |
| 		for i, pc := range err.stack {
 | |
| 			err.frames[i] = NewStackFrame(pc)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return err.frames
 | |
| }
 | |
| 
 | |
| // TypeName returns the type this error. e.g. *errors.stringError.
 | |
| func (err *Error) TypeName() string {
 | |
| 	if _, ok := err.Err.(uncaughtPanic); ok {
 | |
| 		return "panic"
 | |
| 	}
 | |
| 	return reflect.TypeOf(err.Err).String()
 | |
| }
 | 
