errors.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Package errors is a drop-in replacement for Golang lib 'errors'.
  2. package errors
  3. import (
  4. "context"
  5. "strings"
  6. "v2ray.com/core/common/log"
  7. "v2ray.com/core/common/serial"
  8. "v2ray.com/core/common/session"
  9. )
  10. type hasInnerError interface {
  11. // Inner returns the underlying error of this one.
  12. Inner() error
  13. }
  14. type hasSeverity interface {
  15. Severity() log.Severity
  16. }
  17. type hasContext interface {
  18. Context() context.Context
  19. }
  20. // Error is an error object with underlying error.
  21. type Error struct {
  22. message []interface{}
  23. inner error
  24. severity log.Severity
  25. path []string
  26. ctx context.Context
  27. }
  28. // Error implements error.Error().
  29. func (v *Error) Error() string {
  30. msg := serial.Concat(v.message...)
  31. if v.inner != nil {
  32. msg += " > " + v.inner.Error()
  33. }
  34. if len(v.path) > 0 {
  35. msg = strings.Join(v.path, "|") + ": " + msg
  36. }
  37. return msg
  38. }
  39. // Inner implements hasInnerError.Inner()
  40. func (v *Error) Inner() error {
  41. if v.inner == nil {
  42. return nil
  43. }
  44. return v.inner
  45. }
  46. func (v *Error) Base(err error) *Error {
  47. v.inner = err
  48. return v
  49. }
  50. func (v *Error) WithContext(ctx context.Context) *Error {
  51. v.ctx = ctx
  52. return v
  53. }
  54. func (v *Error) Context() context.Context {
  55. if v.ctx != nil {
  56. return v.ctx
  57. }
  58. if v.inner == nil {
  59. return nil
  60. }
  61. if c, ok := v.inner.(hasContext); ok {
  62. return c.Context()
  63. }
  64. return nil
  65. }
  66. func (v *Error) atSeverity(s log.Severity) *Error {
  67. v.severity = s
  68. return v
  69. }
  70. func (v *Error) Severity() log.Severity {
  71. if v.inner == nil {
  72. return v.severity
  73. }
  74. if s, ok := v.inner.(hasSeverity); ok {
  75. as := s.Severity()
  76. if as < v.severity {
  77. return as
  78. }
  79. }
  80. return v.severity
  81. }
  82. // AtDebug sets the severity to debug.
  83. func (v *Error) AtDebug() *Error {
  84. return v.atSeverity(log.Severity_Debug)
  85. }
  86. // AtInfo sets the severity to info.
  87. func (v *Error) AtInfo() *Error {
  88. return v.atSeverity(log.Severity_Info)
  89. }
  90. // AtWarning sets the severity to warning.
  91. func (v *Error) AtWarning() *Error {
  92. return v.atSeverity(log.Severity_Warning)
  93. }
  94. // AtError sets the severity to error.
  95. func (v *Error) AtError() *Error {
  96. return v.atSeverity(log.Severity_Error)
  97. }
  98. // Path sets the path to the location where this error happens.
  99. func (v *Error) Path(path ...string) *Error {
  100. v.path = path
  101. return v
  102. }
  103. // String returns the string representation of this error.
  104. func (v *Error) String() string {
  105. return v.Error()
  106. }
  107. // WriteToLog writes current error into log.
  108. func (v *Error) WriteToLog() {
  109. ctx := v.Context()
  110. var sid session.ID
  111. if ctx != nil {
  112. sid = session.IDFromContext(ctx)
  113. }
  114. var c interface{} = v
  115. if sid > 0 {
  116. c = sessionLog{
  117. id: sid,
  118. content: v,
  119. }
  120. }
  121. log.Record(&log.GeneralMessage{
  122. Severity: GetSeverity(v),
  123. Content: c,
  124. })
  125. }
  126. // New returns a new error object with message formed from given arguments.
  127. func New(msg ...interface{}) *Error {
  128. return &Error{
  129. message: msg,
  130. severity: log.Severity_Info,
  131. }
  132. }
  133. // Cause returns the root cause of this error.
  134. func Cause(err error) error {
  135. if err == nil {
  136. return nil
  137. }
  138. for {
  139. inner, ok := err.(hasInnerError)
  140. if !ok || inner.Inner() == nil {
  141. break
  142. }
  143. err = inner.Inner()
  144. }
  145. return err
  146. }
  147. // GetSeverity returns the actual severity of the error, including inner errors.
  148. func GetSeverity(err error) log.Severity {
  149. if s, ok := err.(hasSeverity); ok {
  150. return s.Severity()
  151. }
  152. return log.Severity_Info
  153. }
  154. type sessionLog struct {
  155. id session.ID
  156. content interface{}
  157. }
  158. func (s sessionLog) String() string {
  159. return serial.Concat("[", s.id, "] ", s.content)
  160. }