diff --git a/go.mod b/go.mod index 80a27a3..7fc0e3e 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,14 @@ module github.com/5aaee9/utils go 1.20 -require github.com/stretchr/testify v1.8.4 +require ( + github.com/samber/do v1.6.0 + github.com/stretchr/testify v1.8.4 +) require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fa4b6e6..912098c 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/samber/do v1.6.0 h1:Jy/N++BXINDB6lAx5wBlbpHlUdl0FKpLWgGEV9YWqaU= +github.com/samber/do v1.6.0/go.mod h1:DWqBvumy8dyb2vEnYZE7D7zaVEB64J45B0NjTlY/M4k= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/pkgs/errors/stack.go b/pkgs/errors/stack.go new file mode 100644 index 0000000..5327036 --- /dev/null +++ b/pkgs/errors/stack.go @@ -0,0 +1,100 @@ +package errors + +import ( + "fmt" + "io" + "runtime" + + "github.com/pkg/errors" +) + +func Trace(err error) error { + if err == nil { + return nil + } + + if HasStack(err) { + return err + } + + return WithStack(err) +} + +func WithStack(err error) error { + if err == nil { + return nil + } + + return &ErrorWithStack{ + err, + callers(), + } +} + +func HasStack(err error) bool { + _, ok := err.(ErrorStack) + return ok +} + +type ErrorStack interface { + StackTrace() errors.StackTrace +} + +var _ ErrorStack = (*ErrorWithStack)(nil) + +type ErrorWithStack struct { + error + *stack +} + +func (w *ErrorWithStack) Cause() error { return w.error } + +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *ErrorWithStack) Unwrap() error { return w.error } + +func (w *ErrorWithStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +type stack []uintptr + +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + for _, pc := range *s { + f := errors.Frame(pc) + fmt.Fprintf(st, "\n%+v", f) + } + } + } +} + +func (s *stack) StackTrace() errors.StackTrace { + f := make([]errors.Frame, len(*s)) + for i := 0; i < len(f); i++ { + f[i] = errors.Frame((*s)[i]) + } + return f +} + +func callers() *stack { + const depth = 32 + var pcs [depth]uintptr + n := runtime.Callers(3, pcs[:]) + var st stack = pcs[0:n] + return &st +} diff --git a/pkgs/errors/stack_test.go b/pkgs/errors/stack_test.go new file mode 100644 index 0000000..3a79927 --- /dev/null +++ b/pkgs/errors/stack_test.go @@ -0,0 +1,17 @@ +package errors + +import ( + "errors" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestError(t *testing.T) { + assert.NoError(t, WithStack(nil)) + assert.True(t, HasStack(WithStack(errors.New("test")))) + assert.False(t, HasStack(errors.New("test"))) + + //helper.InitDebugSentry() + //sentry.CaptureException(WithStack(errors.New("test"))) + //sentry.Flush(time.Second * 10) +} diff --git a/pkgs/proxy/sysproxy/sysproxy_windows.go b/pkgs/proxy/sysproxy/sysproxy_windows.go index 50ff8d6..c03ecd9 100644 --- a/pkgs/proxy/sysproxy/sysproxy_windows.go +++ b/pkgs/proxy/sysproxy/sysproxy_windows.go @@ -6,8 +6,6 @@ import ( "math/big" "syscall" "unsafe" - - "github.com/samber/do" ) type WindowsSystemProxy struct{}