package logging import ( "context" "encoding/json" "fmt" "time" "git.ikuban.com/server/kratos-utils/v2/codes" "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/middleware" "github.com/go-kratos/kratos/v2/transport" ) // Server is an server logging middleware. func Server(logger log.Logger) middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { var ( code int32 reason string kind string operation string ) startTime := time.Now() if info, ok := transport.FromServerContext(ctx); ok { kind = info.Kind().String() operation = info.Operation() } reply, err = handler(ctx, req) if se := errors.FromError(err); se != nil { code = se.Code reason = se.Reason } if code == 0 { return } level, stack := extractError(err) log.WithContext(ctx, logger).Log(level, "kind", "server", "component", kind, "operation", operation, "args", extractArgs(req), "code", code, "reason", reason, "stack", stack, "latency", time.Since(startTime).Seconds(), ) return } } } // Client is an client logging middleware. func Client(logger log.Logger) middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { var ( code int32 reason string kind string operation string ) startTime := time.Now() if info, ok := transport.FromClientContext(ctx); ok { kind = info.Kind().String() operation = info.Operation() } reply, err = handler(ctx, req) if se := errors.FromError(err); se != nil { code = se.Code reason = se.Reason } if code == 0 { return } level, stack := extractError(err) log.WithContext(ctx, logger).Log(level, "component", kind, "operation", operation, "args", extractArgs(req), "code", code, "reason", reason, "stack", stack, "latency", time.Since(startTime).Seconds(), ) return } } } // extractArgs returns the string of the req func extractArgs(req interface{}) string { if stringer, ok := req.(fmt.Stringer); ok { return stringer.String() } j, err := json.Marshal(req) if err != nil { return fmt.Sprintf("%+v", req) } return string(j) } // extractError returns the string of the error func extractError(err error) (log.Level, string) { if err != nil { return log.LevelError, fmt.Sprintf("%+v", codes.ParseErrorMsg(err)) } return log.LevelInfo, "" }