package util import ( "errors" "fmt" "net/http" "runtime" //"github.com/iand/logfmtr" "git.giftfish.de/ston1th/logfmtr" ) var ( reallyCrash = true log = logfmtr.New() panicErr = errors.New("observed a panic") ) func HandleCrash() { if r := recover(); r != nil { logPanic(r) if reallyCrash { panic(r) } } } // logPanic logs the caller tree when a panic occurs (except in the special case of http.ErrAbortHandler). func logPanic(r interface{}) { if r == http.ErrAbortHandler { // honor the http.ErrAbortHandler sentinel panic value: // ErrAbortHandler is a sentinel panic value to abort a handler. // While any panic from ServeHTTP aborts the response to the client, // panicking with ErrAbortHandler also suppresses logging of a stack trace to the server's error log. return } // Same as stdlib http server code. Manually allocate stack trace buffer size // to prevent excessively large logs const size = 64 << 10 stacktrace := make([]byte, size) stacktrace = stacktrace[:runtime.Stack(stacktrace, false)] if _, ok := r.(string); ok { log.Error(panicErr, fmt.Sprintf("%s\n%s", r, stacktrace)) } else { log.Error(panicErr, fmt.Sprintf("%#v (%v)\n%s", r, r, stacktrace)) } }