package logger import ( "fmt" "log/slog" "os" "path/filepath" "strings" ) type Options struct { Level string Output string FilePath string } func New(opts Options) (*slog.Logger, error) { var lvl slog.Level if err := lvl.UnmarshalText([]byte(opts.Level)); err != nil { lvl = slog.LevelInfo } output := strings.ToLower(strings.TrimSpace(opts.Output)) switch output { case "", "console": handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: lvl}) return slog.New(handler), nil case "file": if strings.TrimSpace(opts.FilePath) == "" { return nil, fmt.Errorf("log file path is required") } if err := os.MkdirAll(filepath.Dir(opts.FilePath), 0o755); err != nil { return nil, fmt.Errorf("create log directory: %w", err) } file, err := os.OpenFile(opts.FilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644) if err != nil { return nil, fmt.Errorf("open log file: %w", err) } handler := slog.NewTextHandler(file, &slog.HandlerOptions{Level: lvl}) return slog.New(handler), nil default: return nil, fmt.Errorf("unsupported log output: %s", opts.Output) } }