errors.go 4.8 KB

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