You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
2.6 KiB
108 lines
2.6 KiB
package logging
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"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"
|
|
)
|
|
|
|
// Redacter defines how to log an object
|
|
type Redacter interface {
|
|
Redact() string
|
|
}
|
|
|
|
// 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
|
|
}
|
|
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 a 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
|
|
}
|
|
level, stack := extractError(err)
|
|
_ = log.WithContext(ctx, logger).Log(level,
|
|
"kind", "client",
|
|
"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 redacter, ok := req.(Redacter); ok {
|
|
return redacter.Redact()
|
|
}
|
|
if stringer, ok := req.(fmt.Stringer); ok {
|
|
return stringer.String()
|
|
}
|
|
return fmt.Sprintf("%+v", req)
|
|
}
|
|
|
|
// extractError returns the string of the error
|
|
func extractError(err error) (log.Level, string) {
|
|
if err != nil {
|
|
return log.LevelError, fmt.Sprintf("%+v", err)
|
|
}
|
|
return log.LevelInfo, ""
|
|
}
|
|
|