func (rec recoverer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { reqID := gmiddleware.GetReqID(*rec.c) defer func() { if r := recover(); r != nil { var err error switch x := r.(type) { case error: err = x default: err = fmt.Errorf("%v", x) } rec.l.WithFields(logrus.Fields{ "req_id": reqID, "method": req.Method, "uri": req.RequestURI, "remote": req.RemoteAddr, "err": err.Error(), "stack": stack.Callers(0), }).Warn("service.err") http.Error(resp, http.StatusText(500), 500) } }() rec.h.ServeHTTP(resp, req) }
// Get finds the name of test and the package from the stack, if possible, or tries its best otherwise. func Get(id string) string { s := stack.Callers(1) for _, f := range s { if strings.HasSuffix(f.File, "_test.go") { var name string if strings.HasPrefix(f.Name, "Test") { name = f.Name } else if strings.HasSuffix(f.Name, "SetUpSuite") { name = "SetUpSuite" } else if strings.HasSuffix(f.Name, "SetUpTest") { name = "SetUpTest" } if name != "" { file := replacer.Replace(f.File) return fmt.Sprintf("%s_%s_", file, name) } } } // find the first caller outside ourselves outside := s[0].File for _, f := range s { if f.File != s[0].File { outside = f.Name break } } return fmt.Sprintf("TestNameNotFound_%s_%s_", id, outside) }
// New returns a middleware that: recovers from panics, logs the panic and backtrace, // writes a HTML response and Internal Server Error status. // // If a JSON content type is detected it returns a JSON response. func New(opts *Options) func(h http.Handler) http.Handler { if opts == nil || opts.Log == nil { opts = &Options{Log: log.Print} } return func(h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { defer func() { if err := recover(); err != nil { frames := stack.Callers(3) opts.Log(fmt.Sprintf(logFmt, titleClr("PANIC"), err, frames.String())) w.WriteHeader(http.StatusInternalServerError) ct := r.Header.Get(contentType) if strings.HasPrefix(ct, applicationJSON) { w.Header().Set(contentType, applicationJSONCharsetUTF8) e := jsonError{Message: err, Location: frames[0].String()} json.NewEncoder(w).Encode(e) } else { w.Write(compileTemplate(r, err, frames)) } } }() h.ServeHTTP(w, r) } return http.HandlerFunc(fn) } }
func (c *Client) errors(skip int, errs ...error) error { l := make([]Event, len(errs)) for i, e := range errs { // we add one to skip because we want to skip errors() as well l[i] = convertError(e, stack.Callers(skip+1)) } return c.Notify(l) }
func (c cond) String() string { var b bytes.Buffer if c.DisableDeleteSelf { fmt.Fprint(&b, "\n") } else { fmt.Fprint(&b, deleteSelf) } fmt.Fprint(&b, pstack(stack.Callers(c.Skip+1), c.DisableDeleteSelf)) if c.Format != "" { fmt.Fprintf(&b, c.Format, c.FormatArgs...) } if len(c.Extra) != 0 { fmt.Fprint(&b, "\n") fmt.Fprint(&b, tsdump(c.Extra...)) } return b.String() }
// WrapSkip may wrap the error and return an augmented error depending on the // configuration in the context. The defaults result in the error being // returned as is. It also handles nils correctly, returning a nil in that // case. If the given error is already wrapped, it returns it as-is. func WrapSkip(ctx context.Context, err error, skip int) error { switch err := err.(type) { case nil: return nil case *singleFrameError: return err case *singleStackError: return err case *multiStackError: err.multiStack.AddCallers(skip + 1) return err } config := ContextConfig(ctx) switch config.StackMode { case StackModeSingleFrame: return &singleFrameError{ config: config, underlying: err, frame: stack.Caller(skip + 1), } case StackModeSingleStack: return &singleStackError{ config: config, underlying: err, stack: stack.Callers(skip + 1), } case StackModeMultiStack: return &multiStackError{ config: config, underlying: err, multiStack: stack.CallersMulti(skip + 1), } } return err }
func (m typ) indirect1() stack.Stack { return stack.Callers(0) }
func BenchmarkCallers(b *testing.B) { for i := 0; i < b.N; i++ { stack.Callers(0) } }