package logger import ( "context" "log/slog" "time" ) import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) func GRPCLoggerClientInterceptor(logger *slog.Logger) grpc.UnaryClientInterceptor { return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { start := time.Now() logger.Info("request", slog.String("method", method), slog.Any("payload", req), ) err := invoker(ctx, method, req, reply, cc, opts...) duration := time.Since(start) if err != nil { logger.Error("response", slog.String("method", method), slog.Duration("duration", duration), slog.String("error", err.Error()), ) } else { logger.Info("response", slog.String("method", method), slog.Duration("duration", duration), slog.Any("reply", reply), ) } return err } } func GRPCLoggerServerInterceptor(logger *slog.Logger) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { start := time.Now() method := info.FullMethod // 在请求处理前记录 logger.Info("request", slog.String("method", method), slog.Any("payload", req), ) // 调用实际的服务方法 resp, err = handler(ctx, req) // 在请求处理后记录 duration := time.Since(start) statusCode := codes.OK // 默认成功 if err != nil { s, ok := status.FromError(err) if ok { statusCode = s.Code() // 从 gRPC 错误中获取状态码 } else { statusCode = codes.Unknown // 非 gRPC 错误则视为未知 } } if err != nil { logger.Error("response", slog.String("method", method), slog.Duration("duration", duration), slog.String("status_code", statusCode.String()), slog.String("error", err.Error()), ) } else { logger.Info("response", slog.String("method", method), slog.Duration("duration", duration), slog.Any("reply", resp), ) } return resp, err } }