Xray-core/common/errors/errors.go
风扇滑翔翼 61cad5ec8b
Some checks are pending
Build and Release for Windows 7 / check-assets (push) Waiting to run
Build and Release for Windows 7 / build (win7-32, 386, windows) (push) Blocked by required conditions
Build and Release for Windows 7 / build (win7-64, amd64, windows) (push) Blocked by required conditions
Build and Release / check-assets (push) Waiting to run
Build and Release / build (386, freebsd, ) (push) Blocked by required conditions
Build and Release / build (386, linux, ) (push) Blocked by required conditions
Build and Release / build (386, openbsd, ) (push) Blocked by required conditions
Build and Release / build (386, windows, ) (push) Blocked by required conditions
Build and Release / build (amd64, android, android-amd64) (push) Blocked by required conditions
Build and Release / build (amd64, darwin, ) (push) Blocked by required conditions
Build and Release / build (amd64, freebsd, ) (push) Blocked by required conditions
Build and Release / build (amd64, linux, ) (push) Blocked by required conditions
Build and Release / build (amd64, openbsd, ) (push) Blocked by required conditions
Build and Release / build (amd64, windows, ) (push) Blocked by required conditions
Build and Release / build (arm, 5, linux) (push) Blocked by required conditions
Build and Release / build (arm, 6, linux) (push) Blocked by required conditions
Build and Release / build (arm, 7, freebsd) (push) Blocked by required conditions
Build and Release / build (arm, 7, linux) (push) Blocked by required conditions
Build and Release / build (arm, 7, openbsd) (push) Blocked by required conditions
Build and Release / build (arm64, android) (push) Blocked by required conditions
Build and Release / build (arm64, darwin) (push) Blocked by required conditions
Build and Release / build (arm64, freebsd) (push) Blocked by required conditions
Build and Release / build (arm64, linux) (push) Blocked by required conditions
Build and Release / build (arm64, openbsd) (push) Blocked by required conditions
Build and Release / build (arm64, windows) (push) Blocked by required conditions
Build and Release / build (loong64, linux) (push) Blocked by required conditions
Build and Release / build (mips, linux) (push) Blocked by required conditions
Build and Release / build (mips64, linux) (push) Blocked by required conditions
Build and Release / build (mips64le, linux) (push) Blocked by required conditions
Build and Release / build (mipsle, linux) (push) Blocked by required conditions
Build and Release / build (ppc64, linux) (push) Blocked by required conditions
Build and Release / build (ppc64le, linux) (push) Blocked by required conditions
Build and Release / build (riscv64, linux) (push) Blocked by required conditions
Build and Release / build (s390x, linux) (push) Blocked by required conditions
Tests and Checkings / check-assets (push) Waiting to run
Tests and Checkings / check-proto (push) Waiting to run
Tests and Checkings / check-format (push) Waiting to run
Tests and Checkings / test (macos-latest) (push) Blocked by required conditions
Tests and Checkings / test (ubuntu-latest) (push) Blocked by required conditions
Tests and Checkings / test (windows-latest) (push) Blocked by required conditions
Xray-core: Reduce error log usage for performance (#6796)
https://github.com/XTLS/Xray-core/pull/6796#issuecomment-5807809588
2026-09-25 17:59:49 +00:00

175 lines
3.7 KiB
Go

// 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
}
// Error is an error object with underlying error.
type Error struct {
prefix []interface{}
message []interface{}
caller string
inner error
}
// 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
}
// 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,
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_Info, 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_Warning, 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_Error, msg...)
}
func doLog(ctx context.Context, inner error, severity log.Severity, msg ...interface{}) {
if log.GetSeverity() < severity {
return
}
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,
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: severity,
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
}