From b104c5c973ece98a1d614e372eda215e757f7f9f Mon Sep 17 00:00:00 2001 From: DarthSim Date: Mon, 19 Aug 2019 18:05:34 +0600 Subject: [PATCH] Better stacktrace in errors --- errors.go | 31 +++++++++++++++++++++++++------ server.go | 2 +- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/errors.go b/errors.go index 5c8a5bd8..21029d98 100644 --- a/errors.go +++ b/errors.go @@ -11,12 +11,26 @@ type imgproxyError struct { Message string PublicMessage string Unexpected bool + + stack []uintptr } func (e *imgproxyError) Error() string { return e.Message } +func (e *imgproxyError) ErrorWithStack() string { + if e.stack == nil { + return e.Message + } + + return fmt.Sprintf("%s\n%s", e.Message, formatStack(e.stack)) +} + +func (e *imgproxyError) StackTrace() []uintptr { + return e.stack +} + func newError(status int, msg string, pub string) *imgproxyError { return &imgproxyError{ StatusCode: status, @@ -28,18 +42,23 @@ func newError(status int, msg string, pub string) *imgproxyError { func newUnexpectedError(msg string, skip int) *imgproxyError { return &imgproxyError{ StatusCode: 500, - Message: fmt.Sprintf("Unexpected error: %s\n%s", msg, stacktrace(skip+3)), + Message: msg, PublicMessage: "Internal error", Unexpected: true, + + stack: callers(skip + 3), } } -func stacktrace(skip int) string { - callers := make([]uintptr, 10) - n := runtime.Callers(skip, callers) +func callers(skip int) []uintptr { + stack := make([]uintptr, 10) + n := runtime.Callers(skip, stack) + return stack[:n] +} - lines := make([]string, n) - for i, pc := range callers[:n] { +func formatStack(stack []uintptr) string { + lines := make([]string, len(stack)) + for i, pc := range stack { f := runtime.FuncForPC(pc) file, line := f.FileLine(pc) lines[i] = fmt.Sprintf("%s:%d %s", file, line, f.Name()) diff --git a/server.go b/server.go index 16cd25b4..db5196e0 100644 --- a/server.go +++ b/server.go @@ -109,7 +109,7 @@ func handlePanic(reqID string, rw http.ResponseWriter, r *http.Request, err erro reportError(err, r) } - logResponse(reqID, ierr.StatusCode, ierr.Message) + logResponse(reqID, ierr.StatusCode, ierr.ErrorWithStack()) rw.WriteHeader(ierr.StatusCode)