feat: Add latency to the recover handler context (#2653)

* feat: Make recovey log information more abundant

* feat: Add latency to the recover handler context

* feat: Add latency to the recover handler context

* feat: Add latency to the recover handler context

---------

Co-authored-by: shuai_yang <shuai_yang@intsig.net>
pull/2683/head
hoslo 2 years ago committed by GitHub
parent e4595db3d8
commit 19f008b483
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      middleware/recovery/recovery.go
  2. 8
      middleware/recovery/recovery_test.go

@ -3,12 +3,16 @@ package recovery
import ( import (
"context" "context"
"runtime" "runtime"
"time"
"github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware" "github.com/go-kratos/kratos/v2/middleware"
) )
// Latency is recovery latency context key
type Latency struct{}
// ErrUnknownRequest is unknown request error. // ErrUnknownRequest is unknown request error.
var ErrUnknownRequest = errors.InternalServer("UNKNOWN", "unknown request error") var ErrUnknownRequest = errors.InternalServer("UNKNOWN", "unknown request error")
@ -41,13 +45,14 @@ func Recovery(opts ...Option) middleware.Middleware {
} }
return func(handler middleware.Handler) middleware.Handler { return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (reply interface{}, err error) { return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
startTime := time.Now()
defer func() { defer func() {
if rerr := recover(); rerr != nil { if rerr := recover(); rerr != nil {
buf := make([]byte, 64<<10) //nolint:gomnd buf := make([]byte, 64<<10) //nolint:gomnd
n := runtime.Stack(buf, false) n := runtime.Stack(buf, false)
buf = buf[:n] buf = buf[:n]
log.Context(ctx).Errorf("%v: %+v\n%s\n", rerr, req, buf) log.Context(ctx).Errorf("%v: %+v\n%s\n", rerr, req, buf)
ctx = context.WithValue(ctx, Latency{}, time.Since(startTime).Seconds())
err = op.handler(ctx, req, rerr) err = op.handler(ctx, req, rerr)
} }
}() }()

@ -18,7 +18,13 @@ func TestOnce(t *testing.T) {
next := func(ctx context.Context, req interface{}) (interface{}, error) { next := func(ctx context.Context, req interface{}) (interface{}, error) {
panic("panic reason") panic("panic reason")
} }
_, e := Recovery()(next)(context.Background(), "panic") _, e := Recovery(WithHandler(func(ctx context.Context, _, err interface{}) error {
_, ok := ctx.Value(Latency{}).(float64)
if !ok {
t.Errorf("not latency")
}
return errors.InternalServer("RECOVERY", fmt.Sprintf("panic triggered: %v", err))
}))(next)(context.Background(), "panic")
t.Logf("succ and reason is %v", e) t.Logf("succ and reason is %v", e)
} }

Loading…
Cancel
Save