github.com/v2fly/v2ray-core/v4@v4.45.2/common/errors/errors.go (about)

     1  // Package errors is a drop-in replacement for Golang lib 'errors'.
     2  package errors
     3  
     4  import (
     5  	"os"
     6  	"reflect"
     7  	"strings"
     8  
     9  	"github.com/v2fly/v2ray-core/v4/common/log"
    10  	"github.com/v2fly/v2ray-core/v4/common/serial"
    11  )
    12  
    13  type hasInnerError interface {
    14  	// Inner returns the underlying error of this one.
    15  	Inner() error
    16  }
    17  
    18  type hasSeverity interface {
    19  	Severity() log.Severity
    20  }
    21  
    22  // Error is an error object with underlying error.
    23  type Error struct {
    24  	pathObj  interface{}
    25  	prefix   []interface{}
    26  	message  []interface{}
    27  	inner    error
    28  	severity log.Severity
    29  }
    30  
    31  func (err *Error) WithPathObj(obj interface{}) *Error {
    32  	err.pathObj = obj
    33  	return err
    34  }
    35  
    36  func (err *Error) pkgPath() string {
    37  	if err.pathObj == nil {
    38  		return ""
    39  	}
    40  	path := reflect.TypeOf(err.pathObj).PkgPath()
    41  	path = strings.TrimPrefix(path, "github.com/v2fly/v2ray-core/v4/")
    42  	path = strings.TrimPrefix(path, "github.com/v2fly/v2ray-core/v4")
    43  	return path
    44  }
    45  
    46  // Error implements error.Error().
    47  func (err *Error) Error() string {
    48  	builder := strings.Builder{}
    49  	for _, prefix := range err.prefix {
    50  		builder.WriteByte('[')
    51  		builder.WriteString(serial.ToString(prefix))
    52  		builder.WriteString("] ")
    53  	}
    54  
    55  	path := err.pkgPath()
    56  	if len(path) > 0 {
    57  		builder.WriteString(path)
    58  		builder.WriteString(": ")
    59  	}
    60  
    61  	msg := serial.Concat(err.message...)
    62  	builder.WriteString(msg)
    63  
    64  	if err.inner != nil {
    65  		builder.WriteString(" > ")
    66  		builder.WriteString(err.inner.Error())
    67  	}
    68  
    69  	return builder.String()
    70  }
    71  
    72  // Inner implements hasInnerError.Inner()
    73  func (err *Error) Inner() error {
    74  	if err.inner == nil {
    75  		return nil
    76  	}
    77  	return err.inner
    78  }
    79  
    80  func (err *Error) Base(e error) *Error {
    81  	err.inner = e
    82  	return err
    83  }
    84  
    85  func (err *Error) atSeverity(s log.Severity) *Error {
    86  	err.severity = s
    87  	return err
    88  }
    89  
    90  func (err *Error) Severity() log.Severity {
    91  	if err.inner == nil {
    92  		return err.severity
    93  	}
    94  
    95  	if s, ok := err.inner.(hasSeverity); ok {
    96  		as := s.Severity()
    97  		if as < err.severity {
    98  			return as
    99  		}
   100  	}
   101  
   102  	return err.severity
   103  }
   104  
   105  // AtDebug sets the severity to debug.
   106  func (err *Error) AtDebug() *Error {
   107  	return err.atSeverity(log.Severity_Debug)
   108  }
   109  
   110  // AtInfo sets the severity to info.
   111  func (err *Error) AtInfo() *Error {
   112  	return err.atSeverity(log.Severity_Info)
   113  }
   114  
   115  // AtWarning sets the severity to warning.
   116  func (err *Error) AtWarning() *Error {
   117  	return err.atSeverity(log.Severity_Warning)
   118  }
   119  
   120  // AtError sets the severity to error.
   121  func (err *Error) AtError() *Error {
   122  	return err.atSeverity(log.Severity_Error)
   123  }
   124  
   125  // String returns the string representation of this error.
   126  func (err *Error) String() string {
   127  	return err.Error()
   128  }
   129  
   130  // WriteToLog writes current error into log.
   131  func (err *Error) WriteToLog(opts ...ExportOption) {
   132  	var holder ExportOptionHolder
   133  
   134  	for _, opt := range opts {
   135  		opt(&holder)
   136  	}
   137  
   138  	if holder.SessionID > 0 {
   139  		err.prefix = append(err.prefix, holder.SessionID)
   140  	}
   141  
   142  	log.Record(&log.GeneralMessage{
   143  		Severity: GetSeverity(err),
   144  		Content:  err,
   145  	})
   146  }
   147  
   148  type ExportOptionHolder struct {
   149  	SessionID uint32
   150  }
   151  
   152  type ExportOption func(*ExportOptionHolder)
   153  
   154  // New returns a new error object with message formed from given arguments.
   155  func New(msg ...interface{}) *Error {
   156  	return &Error{
   157  		message:  msg,
   158  		severity: log.Severity_Info,
   159  	}
   160  }
   161  
   162  // Cause returns the root cause of this error.
   163  func Cause(err error) error {
   164  	if err == nil {
   165  		return nil
   166  	}
   167  L:
   168  	for {
   169  		switch inner := err.(type) {
   170  		case hasInnerError:
   171  			if inner.Inner() == nil {
   172  				break L
   173  			}
   174  			err = inner.Inner()
   175  		case *os.PathError:
   176  			if inner.Err == nil {
   177  				break L
   178  			}
   179  			err = inner.Err
   180  		case *os.SyscallError:
   181  			if inner.Err == nil {
   182  				break L
   183  			}
   184  			err = inner.Err
   185  		default:
   186  			break L
   187  		}
   188  	}
   189  	return err
   190  }
   191  
   192  // GetSeverity returns the actual severity of the error, including inner errors.
   193  func GetSeverity(err error) log.Severity {
   194  	if s, ok := err.(hasSeverity); ok {
   195  		return s.Severity()
   196  	}
   197  	return log.Severity_Info
   198  }