123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- // Package errors is a drop-in replacement for Golang lib 'errors'.
- package errors // import "github.com/xtls/xray-core/common/errors"
- import (
- "context"
- "runtime"
- "strings"
- c "github.com/xtls/xray-core/common/ctx"
- "github.com/xtls/xray-core/common/log"
- "github.com/xtls/xray-core/common/serial"
- )
- const trim = len("github.com/xtls/xray-core/")
- type hasInnerError interface {
- // Unwrap returns the underlying error of this one.
- Unwrap() error
- }
- type hasSeverity interface {
- Severity() log.Severity
- }
- // Error is an error object with underlying error.
- type Error struct {
- prefix []interface{}
- message []interface{}
- caller string
- inner error
- severity log.Severity
- }
- // Error implements error.Error().
- func (err *Error) Error() string {
- builder := strings.Builder{}
- for _, prefix := range err.prefix {
- builder.WriteByte('[')
- builder.WriteString(serial.ToString(prefix))
- builder.WriteString("] ")
- }
- if len(err.caller) > 0 {
- builder.WriteString(err.caller)
- builder.WriteString(": ")
- }
- msg := serial.Concat(err.message...)
- builder.WriteString(msg)
- if err.inner != nil {
- builder.WriteString(" > ")
- builder.WriteString(err.inner.Error())
- }
- return builder.String()
- }
- // Unwrap implements hasInnerError.Unwrap()
- func (err *Error) Unwrap() error {
- if err.inner == nil {
- return nil
- }
- return err.inner
- }
- func (err *Error) Base(e error) *Error {
- err.inner = e
- return err
- }
- func (err *Error) atSeverity(s log.Severity) *Error {
- err.severity = s
- return err
- }
- func (err *Error) Severity() log.Severity {
- if err.inner == nil {
- return err.severity
- }
- if s, ok := err.inner.(hasSeverity); ok {
- as := s.Severity()
- if as < err.severity {
- return as
- }
- }
- return err.severity
- }
- // AtDebug sets the severity to debug.
- func (err *Error) AtDebug() *Error {
- return err.atSeverity(log.Severity_Debug)
- }
- // AtInfo sets the severity to info.
- func (err *Error) AtInfo() *Error {
- return err.atSeverity(log.Severity_Info)
- }
- // AtWarning sets the severity to warning.
- func (err *Error) AtWarning() *Error {
- return err.atSeverity(log.Severity_Warning)
- }
- // AtError sets the severity to error.
- func (err *Error) AtError() *Error {
- return err.atSeverity(log.Severity_Error)
- }
- // String returns the string representation of this error.
- func (err *Error) String() string {
- return err.Error()
- }
- type ExportOptionHolder struct {
- SessionID uint32
- }
- type ExportOption func(*ExportOptionHolder)
- // New returns a new error object with message formed from given arguments.
- func New(msg ...interface{}) *Error {
- pc, _, _, _ := runtime.Caller(1)
- details := runtime.FuncForPC(pc).Name()
- if len(details) >= trim {
- details = details[trim:]
- }
- i := strings.Index(details, ".")
- if i > 0 {
- details = details[:i]
- }
- return &Error{
- message: msg,
- severity: log.Severity_Info,
- caller: details,
- }
- }
- func LogDebug(ctx context.Context, msg ...interface{}) {
- doLog(ctx, nil, log.Severity_Debug, msg...)
- }
- func LogDebugInner(ctx context.Context, inner error, msg ...interface{}) {
- doLog(ctx, inner, log.Severity_Debug, msg...)
- }
- func LogInfo(ctx context.Context, msg ...interface{}) {
- doLog(ctx, nil, log.Severity_Info, msg...)
- }
- func LogInfoInner(ctx context.Context, inner error, msg ...interface{}) {
- doLog(ctx, inner, log.Severity_Debug, msg...)
- }
- func LogWarning(ctx context.Context, msg ...interface{}) {
- doLog(ctx, nil, log.Severity_Warning, msg...)
- }
- func LogWarningInner(ctx context.Context, inner error, msg ...interface{}) {
- doLog(ctx, inner, log.Severity_Debug, msg...)
- }
- func LogError(ctx context.Context, msg ...interface{}) {
- doLog(ctx, nil, log.Severity_Error, msg...)
- }
- func LogErrorInner(ctx context.Context, inner error, msg ...interface{}) {
- doLog(ctx, inner, log.Severity_Debug, msg...)
- }
- func doLog(ctx context.Context, inner error, severity log.Severity, msg ...interface{}) {
- pc, _, _, _ := runtime.Caller(2)
- details := runtime.FuncForPC(pc).Name()
- if len(details) >= trim {
- details = details[trim:]
- }
- i := strings.Index(details, ".")
- if i > 0 {
- details = details[:i]
- }
- err := &Error{
- message: msg,
- severity: severity,
- caller: details,
- inner: inner,
- }
- if ctx != nil && ctx != context.Background() {
- id := uint32(c.IDFromContext(ctx))
- if id > 0 {
- err.prefix = append(err.prefix, id)
- }
- }
- log.Record(&log.GeneralMessage{
- Severity: GetSeverity(err),
- Content: err,
- })
- }
- // Cause returns the root cause of this error.
- func Cause(err error) error {
- if err == nil {
- return nil
- }
- L:
- for {
- switch inner := err.(type) {
- case hasInnerError:
- if inner.Unwrap() == nil {
- break L
- }
- err = inner.Unwrap()
- default:
- break L
- }
- }
- return err
- }
- // GetSeverity returns the actual severity of the error, including inner errors.
- func GetSeverity(err error) log.Severity {
- if s, ok := err.(hasSeverity); ok {
- return s.Severity()
- }
- return log.Severity_Info
- }
|